Classes NSSet and NSMutableSet

A collection is a big object that can contain little objects. More precisely, the collection can contain pointers to the little objects, not the little objects themselves. The simplest example of a collection is a set. A set contains only the little objects, but no additional information about them (such as which little object comes first and which one last). We’re doing sets as the first example of a collection because touches are delivered to your app in the form of a “set of touches”. There may be more than one touch in progress at any given moment.

The main function instantiates a NSSet object containing five pointers that point to NSString objects. But we often abbreviate this by saying that the set contains five NSString objects. These values contained in the set are called the elements of the set.

The count method of class NSSet returns an NSUInteger rather than a plain vanilla int, since the number of elements in a set can never be negative. NSLog must therefore print the count with the %u format rather than the %d format.

The keyword if must be followed by a pair of parentheses, and it would make your instructor happy if the parentheses were followed by a pair of {curly braces}. Similarly, the keyword for must be followed by a pair of parentheses, and it would make your instructor happy if the parentheses were followed by a pair of {curly braces}. I declared borough to be a pointer to an NSString because I knew in advance that each element of the set was a pointer to an NSString. Since our collection is a set, rather than an array, there is no guarantee that the for loop will visit the elements in the order in which we inserted them. The %@ format of NSLog prints the description of an object, and the description of an NSString object is simply the string itself.

You can send the anyObject message to a set only if you have first made sure that the set’s count is greater than zero.

An NSSet and an NSMutableSet can hold only pointers to objects. If you want them to hold numbers (e.g., integers), each number will have to be “wrapped” in an NSNumber object.

Source code in Set.zip

  1. main.m

Create the project

Create a Window-Based Application named Set. Don’t bother making an application delegate. All the new code will be in the main function.

The main.m file

A method that accepts a variable number of arguments, such as the initWithObjects: method of class NSSet, must have commas between the arguments, and a last argument of nil.

The output

Build and Run. The following output should appear in the Debug Area.
View → Debug Area → Show Debug Area

2014-06-08 20:40:02.953 Set[1910:60b] boroughs.count == 5
2014-06-08 20:40:02.957 Set[1910:60b] Brooklyn
2014-06-08 20:40:02.958 Set[1910:60b] Queens
2014-06-08 20:40:02.959 Set[1910:60b] Manhattan
2014-06-08 20:40:02.959 Set[1910:60b] Staten Island
2014-06-08 20:40:02.960 Set[1910:60b] Bronx
2014-06-08 20:40:02.961 Set[1910:60b] Yonkers is not a borough.
2014-06-08 20:40:02.962 Set[1910:60b] The borough of the week is Brooklyn.
2014-06-08 20:40:03.393 Set[1910:60b] Application windows are expected to have a root view controller at the end of application launch

Things to try

  1. Create an NSMutableSet instead of an NSSet. You can change the contents of an NSMutableSet with addObject: and removeObject:.
    	NSMutableSet *boroughs = [[NSMutableSet alloc] init];	//born empty
    	[boroughs addObject: @"Bronx"];
    	[boroughs addObject: @"Brooklyn"];
    	[boroughs addObject: @"Manhattan"];
    	[boroughs addObject: @"Queens"];
    	[boroughs addObject: @"Staten Island"];
    	//Do not add nil at the end.
    

  2. The set’s description is a multi-line NSString. Print it. The elements will appear in an unpredictable order. All three of the following do the same thing.
    	NSLog(@"%@", [boroughs description]);
    	NSLog(@"%@", boroughs.description);
    	NSLog(@"%@", boroughs);
    
    2013-10-23 18:09:53.080 Set[4859:a0b] {(
        Manhattan,
        Queens,
        "Staten Island",
        Bronx,
        Brooklyn
    )}
    

  3. The following pair of nested loops will print every combination of “one from group A and one from group B” (the cartesian product of two sets).
    	NSSet *parties = [NSSet setWithObjects:
    		@"Democratic",
    		@"Republican",
    		nil
    	];
    
    	NSSet *leanings = [NSSet setWithObjects:
    		@"liberal",
    		@"moderate",
    		@"conservative",
    		nil
    	];
    
    	for (NSString *party in parties) {
    		for (NSString *leaning in leanings) {
    			NSLog(@"%@ %@", party, leaning);
    		}
    	}
    
    2013-10-23 18:11:01.883 Set[4871:a0b] Republican conservative
    2013-10-23 18:11:01.886 Set[4871:a0b] Republican moderate
    2013-10-23 18:11:01.886 Set[4871:a0b] Republican liberal
    2013-10-23 18:11:01.887 Set[4871:a0b] Democratic conservative
    2013-10-23 18:11:01.887 Set[4871:a0b] Democratic moderate
    2013-10-23 18:11:01.889 Set[4871:a0b] Democratic liberal
    
    Can you list the combinations leaning by leaning, rather than party by party?

  4. Another interesting topic: the method makeObjectsPerformSelector. Suppose each borough had a method named visit.
    	[boroughs makeObjectsPerformSelector: @selector(visit)];