This chapter will help you work with arrays and dictionaries using the Foundation framework with Objective-C.
The recipes in this chapter will show you how to:
NSArray
and NSMutableArray
NSDictionary
and NSMutableDictionary
NSSet
and NSMutableSet
NOTE: There are three types of objects collections to work with in Objective-C: arrays, dictionaries, and sets. Your choice of collection will depend on the needs of your app.
Arrays organize objects in lists that are indexed by integers.
Dictionaries organize objects with keys; each object in a dictionary is associated with a string key that you can use later to retrieve the object.
Sets contain objects, but don’t assume that they will be in any order be indexed. Objects in sets also must be unique (no duplicates). Retrieving objects from sets is very fast because sets don’t have the overhead of an index so you will see this used in situations where performance is a consideration.
Your app requires you to group objects together in a list.
Objective-C has two Foundation classes named NSArray
and NSMutableArray
that you can use to create lists of objects. Use NSArray
when you have a list that you know you won’t need to change on the fly and NSMutableArray
when you know you will need to add and remove objects from the array at a later time.
Arrays are created in Objective-C like other objects: you use the alloc
and init
constructors or convenience functions like arrayWithObjects
to create the array. If you use NSArray
to create your array, you can’t make any changes to the array once the array is created. Use NSMutableArray
to create arrays that you can later modify.
Here is an example of creating an array of strings:
NSArray *listOfLetters = [NSArray arrayWithObjects:@"A", @"B", @"C", nil];
When you use arrayWithObjects
to create your array, you must pass in the objects in a comma-separated list that ends with nil
. This example used NSString
objects but you can use any object that you like with NSArray
and NSMutableArray
, including objects instantiated from your custom classes.
If you choose to use NSMutableArray
, you can use the same constructors to create your arrays (NSMutableArray
is a subclass of NSArray
). You can also create your NSMutableArray
by using alloc
and init
since you will likely add objects to your array at some future point. See Table 3-1 for a complete list of available constructors for NSArray
and NSMutableArray
and Listing 3-1 for the code.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSArray *listOfLetters1 = [NSArray arrayWithObjects:@"A", @"B", @"C", nil];
NSLog(@"listOfLetters1 = %@", listOfLetters1);
NSNumber *number1 = [NSNumber numberWithInt:1];
NSNumber *number2 = [NSNumber numberWithInt:2];
NSNumber *number3 = [NSNumber numberWithInt:3];
NSMutableArray *listOfNumbers1 = [[NSMutableArray alloc]
initWithObjects:number1, number2, number3, nil];
NSLog(@"listOfNumbers1 = %@", listOfNumbers1);
id list[3];
list[0] = @"D";
list[1] = @"E";
list[2] = @"F";
NSMutableArray *listOfLetters2 = [[NSMutableArray alloc] initWithObjects:list
count:3];
NSLog(@"listOfLetters2 = %@", listOfLetters2);
}
return 0;
}
To use this code, build and run your Mac app from Xcode. Inspect the log to see the contents of each array. In the next recipe, you will see how to reference each of these array elements so you can print out their contents to the log or use them elsewhere in your programs.
You would like to get references to the objects in your arrays to either access their properties or to send messages to the objects.
Use the objectAtIndex:
method to get a reference to an object in the array that corresponds to an integer position. You may also get a reference to the last object in an array using the lastObject
function.
NSArray
organizes objects in a list that is indexed by integers starting with the number 0. If you want to get a reference to an object in your array and know the position of the object, you can use the objectAtIndex:
function to get a reference to that object.
NSString *stringObject1 = [listOfLetters objectAtIndex:0];
There is also a very convenient function named lastObject
that you can use to quickly get a reference to the last object in your array.
NSString *stringObject2 = [listOfLetters lastObject];
Often, you won’t know where in the array your object is located. If you already have a reference to the object in question, you can use the indexOfObject:
function with the object reference as a parameter to find out where in the array the object is located.
NSUInteger position = [listOfLetters indexOfObject:@"B"];
See Listing 3-2 for the code.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSMutableArray *listOfLetters = [NSMutableArray arrayWithObjects:@"A", @"B",
@"C", nil];
NSString *stringObject1 = [listOfLetters objectAtIndex:0];
NSLog(@"stringObject1 = %@", stringObject1);
NSString *stringObject2 = [listOfLetters lastObject];
NSLog(@"stringObject2 = %@", stringObject2);
NSUInteger position = [listOfLetters indexOfObject:@"B"];
NSLog(@"position = %lu", position);
}
return 0;
}
To use this code, build and run your Mac app from Xcode. You can see that the objects were successfully referenced by the output written to the console.
stringObject1 = A
stringObject2 = C
position = 1
Your app is working with the content in your arrays and you need to know how many elements are in the array in order to present your content appropriately.
NSArray
objects have a count
property that you can use to find out how many elements are in the array.
To use the count property, you can use dot notation (listOfLetters.count
) on any array object or you can send the count message ([listOfLetters count
]) to find out how many elements are in the array. See Listing 3-3 for the code.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSMutableArray *listOfLetters = [NSMutableArray arrayWithObjects:@"A", @"B",
@"C", nil];
NSLog(@"listOfLetters has %lu elements", listOfLetters.count);
}
return 0;
}
To use this code, build and run your Mac app from Xcode. The log message will present the number of elements.
listOfLetters has 3 elements
You have an array of objects and you would like to be able to send the same message or access the same property for every object in the array.
NSArray
objects come with three built-in ways to iterate through a list of objects. Many people use a for-each
loop to iterate through each element in the array. This structure gives you the ability to set up lines of code that will be applied to each element in the array.
You can also use a method named makeObjectsPerformSelector:withObject:
where you can pass in the name of the method that you want each object to perform along with one parameter.
Finally, you now have the option of using blocks of code as a parameter that will be applied to each object in the array using the enumerateObjectsUsingBlock:
method. This method gives you the same thing as a for-each
loop, but you don’t need to write the code for the loop itself and you get a parameter that will help you keep track of the current element’s index.
Since you need content to use as an example for this recipe, create three NSMutableString
objects to put into a new array.
NSMutableString *string1 = [NSMutableString stringWithString:@"A"];
NSMutableString *string2 = [NSMutableString stringWithString:@"B"];
NSMutableString *string3 = [NSMutableString stringWithString:@"C"];
NSArray *listOfObjects = [NSArray arrayWithObjects:string1, string2, string3, nil];
To go through this array with a for-each
loop, you need to set up the loop and provide a local variable that you can reference that will represent the current object within the array. You also need to add the code that will execute for each object in your list.
for(NSMutableString *s in listOfObjects){
NSLog(@"This string in lowercase is %@", [s lowercaseString]);
}
In this for-each
loop, you go through each mutable string in the array and write out a message to the log. The lowercaseString
function is an NSString
function that returns the string but in all lowercase letters.
You can send a message to each object in your array without using a for-each
loop by sending the makeObjectsPerformSelector:withObject:
message. You need to pass in the method by using the @selector
keyword and the name of the method in parentheses. Pass in the parameter value after the property decoration withObject:
.
[listOfObjects makeObjectsPerformSelector:@selector(appendString:)
withObject:@"-MORE"];
What you are doing here is sending the appendString
message with the string parameter @”-MORE” to every mutable string in the array. So now each string has been changed to include the extra characters at the end.
WARNING: Make sure that the objects in your array are capable of responding to the messages that you are trying to send. If you attempt to send a message to an object in your array that the object can’t respond to, your program will crash and you will get an unrecognized selector sent to instance
error message.
You can use blocks to define a block of code that you can apply to each object in the array. Blocks are a way to encapsulate code so that the code can be treated as an object and therefore passed to another object as a parameter. The NSArray
method enumerateObjectsUsingBlock:
gives you the ability to execute a block of code for each element in an array.
[listOfObjects enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
NSLog(@"object(%lu)'s description is %@",idx, [obj description]);
}];
This essentially gives you the same thing as the for-each
loop but you only need to use one line of code. Also, the block comes with built-in parameters for the object that you need to reference and an index to help you keep track of your position in the array. In this example, you are using blocks to write out a message to the log for each object in the list using the object’s description function and the index parameter. See Listing 3-4 for the code.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSMutableString *string1 = [NSMutableString stringWithString:@"A"];
NSMutableString *string2 = [NSMutableString stringWithString:@"B"];
NSMutableString *string3 = [NSMutableString stringWithString:@"C"];
NSArray *listOfObjects = [NSArray arrayWithObjects:string1, string2, string3,
nil];
for(NSMutableString *s in listOfObjects){
NSLog(@"This string in lowercase is %@", [s lowercaseString]);
}
[listOfObjects makeObjectsPerformSelector:@selector(appendString:)
withObject:@"-MORE"];
[listOfObjects enumerateObjectsUsingBlock:^(id obj, NSUInteger idx,
BOOL *stop) {
NSLog(@"object(%lu)'s description is %@",idx, [obj description]);
}];
}
return 0;
}
To use this code, build and run your Mac app from Xcode. The log message will present the results of each way of iterating through the array that was created at the beginning.
This string in lowercase is a
This string in lowercase is b
This string in lowercase is c
object(0)'s description is A-MORE
object(1)'s description is B-MORE
object(2)'s description is C-MORE
You are using arrays to group your custom objects and you would like the objects to appear in lists sorted by the values of the object’s properties.
Create one NSSortDescriptor
object for each property that you want to use to sort your array. Put all these NSSortDescriptor
objects into an array, which you will use as a parameter in the next step. Use the NSArray sortedArrayUsingDescriptors:
method and pass the array of NSSortDescriptor
objects as a parameter to return an array sorted by the properties that you specified.
This recipe uses Person
objects. See Listing 3-5 for the class definition of a Person
object. While you can use this recipe to sort objects like strings or numbers, you can really see the power behind NSSortDescriptor
when you use it with custom objects.
Your custom class is named Person
and has three properties: firstName
, lastName
, and age
. Your Person
class also has two methods: reportState
and initWithFirstName:lastName:andAge
, which is a custom constructor.
First, create an array of Person
objects.
//Instantiate Person objects and add them all to an array:
Person *p1 = [[Person alloc] initWithFirstName:@"Rebecca"
lastName:@"Smith"
andAge:33];
Person *p2 = [[Person alloc] initWithFirstName:@"Albert"
lastName:@"Case"
andAge:24];
Person *p3 = [[Person alloc] initWithFirstName:@"Anton"
lastName:@"Belfey"
andAge:45];
Person *p4 = [[Person alloc] initWithFirstName:@"Tom"
lastName:@"Gun"
andAge:17];
Person *p5 = [[Person alloc] initWithFirstName:@"Cindy"
lastName:@"Lou"
andAge:6];
Person *p6 = [[Person alloc] initWithFirstName:@"Yanno"
lastName:@"Dirst"
andAge:76];
NSArray *listOfObjects = [NSArray arrayWithObjects:p1, p2, p3, p4, p5, p6, nil];
If you print out each element in this array, the objects will appear in the order that you put them into the array. If you want to sort this array by each person’s age, last name, and first name, you can use NSSortDescriptor
objects. You need one sort descriptor for each Person
property that you’re using to sort.
//Create three sort descriptors and add to an array:
NSSortDescriptor *sd1 = [NSSortDescriptor sortDescriptorWithKey:@"age"
ascending:YES];
NSSortDescriptor *sd2 = [NSSortDescriptor sortDescriptorWithKey:@"lastName"
ascending:YES];
NSSortDescriptor *sd3 = [NSSortDescriptor sortDescriptorWithKey:@"firstName"
ascending:YES];
NSArray *sdArray1 = [NSArray arrayWithObjects:sd1, sd2, sd3, nil];
You must pass in the name of the property as a string and specify whether you want that property sorted ascending or descending. Finally, all the sort descriptors need to be in an array.
The position of each sort descriptor in the array determines the order in which the objects will be sorted. So, if you want the array sorted by age and then last name, make sure you add the sort descriptor corresponding to age before the sort descriptor corresponding to last name.
To get your sorted array, send the sortedArrayUsingDescriptors
message to the array that you want to sort and pass the array of sort descriptors as a parameter.
NSArray *sortedArray1 = [listOfObjects sortedArrayUsingDescriptors:sdArray1];
To see the results, use the makeObjectsPerformSelector
method to have each object in the sorted array report its state to the log.
[sortedArray1 makeObjectsPerformSelector:@selector(reportState)];
This will print out the details of each Person
object to the log in the order that was specified by the sort descriptors (age, last name, first name). See Listings 3-5 through 3-7 for the code.
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property(strong) NSString *firstName;
@property(strong) NSString *lastName;
@property(assign) int age;
-(id)initWithFirstName:(NSString *)fName lastName:(NSString *)lName andAge:(int)a;
-(void)reportState;
@end
#import "Person.h"
@implementation Person
@synthesize firstName, lastName, age;
-(id)initWithFirstName:(NSString *)fName lastName:(NSString *)lName andAge:(int)a{
self = [super init];
if (self) {
self.firstName = fName;
self.lastName = lName;
self.age = a;
}
return self;
}
-(void)reportState{
NSLog(@"This person's name is %@ %@ who is %i years old", firstName, lastName, age);
}
@end
#import <Foundation/Foundation.h>
#import "Person.h"
int main (int argc, const char * argv[])
{
@autoreleasepool {
//Instantiate Person objects and add them all to an array:
Person *p1 = [[Person alloc] initWithFirstName:@"Rebecca"
lastName:@"Smith"
andAge:33];
Person *p2 = [[Person alloc] initWithFirstName:@"Albert"
lastName:@"Case"
andAge:24];
Person *p3 = [[Person alloc] initWithFirstName:@"Anton"
lastName:@"Belfey"
andAge:45];
Person *p4 = [[Person alloc] initWithFirstName:@"Tom"
lastName:@"Gun"
andAge:17];
Person *p5 = [[Person alloc] initWithFirstName:@"Cindy"
lastName:@"Lou"
andAge:6];
Person *p6 = [[Person alloc] initWithFirstName:@"Yanno"
lastName:@"Dirst"
andAge:76];
NSArray *listOfObjects = [NSArray arrayWithObjects:p1, p2, p3, p4, p5, p6,
nil];
NSLog(@"PRINT OUT ARRAY UNSORTED");
[listOfObjects makeObjectsPerformSelector:@selector(reportState)];
//Create three sort descriptors and add to an array:
NSSortDescriptor *sd1 = [NSSortDescriptor sortDescriptorWithKey:@"age"
ascending:YES];
NSSortDescriptor *sd2 = [NSSortDescriptor sortDescriptorWithKey:@"lastName"
ascending:YES];
NSSortDescriptor *sd3 = [NSSortDescriptor sortDescriptorWithKey:@"firstName"
ascending:YES];
NSArray *sdArray1 = [NSArray arrayWithObjects:sd1, sd2, sd3, nil];
NSLog(@"PRINT OUT SORTED ARRAY (AGE,LASTNAME,FIRSTNAME)");
NSArray *sortedArray1 = [listOfObjects sortedArrayUsingDescriptors:sdArray1];
[sortedArray1 makeObjectsPerformSelector:@selector(reportState)];
NSArray *sdArray2 = [NSArray arrayWithObjects:sd2, sd1, sd3, nil];
NSArray *sortedArray2 = [listOfObjects sortedArrayUsingDescriptors:sdArray2];
NSLog(@"PRINT OUT SORTED ARRAY (LASTNAME,FIRSTNAME,AGE)");
[sortedArray2 makeObjectsPerformSelector:@selector(reportState)];
}
return 0;
}
To use this code, you need to create a file for the Person
class. This is an Objective-C class, and you may use the Xcode file templates to start it. The Person
class must be imported into code located in main.m
(for Mac command line apps). Build and run the project and then inspect the console log to see the results of the sorted arrays.
PRINT OUT ARRAY UNSORTED
This person's name is Rebecca Smith who is 33 years old
This person's name is Albert Case who is 24 years old
This person's name is Anton Belfey who is 45 years old
This person's name is Tom Gun who is 17 years old
This person's name is Cindy Lou who is 6 years old
This person's name is Yanno Dirst who is 76 years old
PRINT OUT SORTED ARRAY (AGE,LASTNAME,FIRSTNAME)
This person's name is Cindy Lou who is 6 years old
This person's name is Tom Gun who is 17 years old
This person's name is Albert Case who is 24 years old
This person's name is Rebecca Smith who is 33 years old
This person's name is Anton Belfey who is 45 years old
This person's name is Yanno Dirst who is 76 years old
PRINT OUT SORTED ARRAY (LASTNAME,FIRSTNAME,AGE)
This person's name is Anton Belfey who is 45 years old
This person's name is Albert Case who is 24 years old
This person's name is Yanno Dirst who is 76 years old
This person's name is Tom Gun who is 17 years old
This person's name is Cindy Lou who is 6 years old
This person's name is Rebecca Smith who is 33 years old
You have a significant array full of objects and you would like to select a subset of this array based on some criteria to use in controls like the search bar in the table of an iOS app.
The first thing that you need is an NSPredicate
object. NSPredicate
is used to define a search query. Next, you can use the original array’s filteredArrayUsingPredicate
function to return a subset of the original array based on the specifications of the NSPredicate:
object that you defined.
For this recipe, use the same Person
objects as you did in Recipe 3.5. You are going to define a predicate to return an array containing only Person
objects with an age greater than 30.
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age > 30"];
Predicates require a logical expression to apply to the objects in the array. Here age is a property that must be part of the objects in the array that you are querying. You use the same comparison operators that you use in programming (see Table 3-2 for a complete list of NSPredicate
operators).
Once you have your predicate set up, all you need to do is get the subset of the array by using the filteredArrayUsingPredicate:
function while passing the NSPredicate
object as a parameter.
NSArray *arraySubset = [listOfObjects filteredArrayUsingPredicate:predicate];
You will end up with another array that has only those objects that match the specifications that you coded in the NSPredicate
object. See Listings 3-8 through 3-10 for the code.
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property(strong) NSString *firstName;
@property(strong) NSString *lastName;
@property(assign) int age;
-(id)initWithFirstName:(NSString *)fName lastName:(NSString *)lName andAge:(int)a;
-(void)reportState;
@end
#import "Person.h"
@implementation Person
@synthesize firstName, lastName, age;
-(id)initWithFirstName:(NSString *)fName lastName:(NSString *)lName
andAge:(int)a{
self = [super init];
if (self) {
self.firstName = fName;
self.lastName = lName;
self.age = a;
}
return self;
}
-(void)reportState{
NSLog(@"This person's name is %@ %@ who is %i years old", firstName, lastName, age);
}
@end
#import <Foundation/Foundation.h>
#import "Person.h"
int main (int argc, const char * argv[])
{
@autoreleasepool {
//Instantiate Person objects and add them all to an array:
Person *p1 = [[Person alloc] initWithFirstName:@"Rebecca"
lastName:@"Smith"
andAge:33];
Person *p2 = [[Person alloc] initWithFirstName:@"Albert"
lastName:@"Case"
andAge:24];
Person *p3 = [[Person alloc] initWithFirstName:@"Anton"
lastName:@"Belfey"
andAge:45];
Person *p4 = [[Person alloc] initWithFirstName:@"Tom"
lastName:@"Gun"
andAge:17];
Person *p5 = [[Person alloc] initWithFirstName:@"Cindy"
lastName:@"Lou"
andAge:6];
Person *p6 = [[Person alloc] initWithFirstName:@"Yanno"
lastName:@"Dirst"
andAge:76];
NSArray *listOfObjects = [NSArray arrayWithObjects:p1, p2, p3, p4, p5, p6,
nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age > 30"];
NSArray *arraySubset = [listOfObjects filteredArrayUsingPredicate:predicate];
NSLog(@"PRINT OUT ARRAY SUBSET");
[arraySubset makeObjectsPerformSelector:@selector(reportState)];
}
return 0;
}
To use this code, build and run your Mac app from Xcode. Check the console to see the results of the query made by the NSPredicate
object.
PRINT OUT ARRAY SUBSET
This person's name is Rebecca Smith who is 33 years old
This person's name is Anton Belfey who is 45 years old
This person's name is Yanno Dirst who is 76 years old
You want your array content to be more dynamic so that you or your users can add, remove, and insert objects into arrays. However, NSArray
is an immutable class, so once you create an NSArray
you can’t make any changes to its contents.
If you know that your array needs to be dynamic, use NSMutableArray
. NSMutableArray
is a subclass of NSArray
, so you can work with NSMutableArray
as you would with NSArray
. But NSMutableArray
provides methods that let you add, remove, and insert objects into the array list.
First, instantiate a NSMutableArray
object. You can use any constructor to do this. To create a new empty NSMutableArray
, you may simply use alloc
and init
.
NSMutableArray *listOfLetters = [[NSMutableArray alloc] init];
To add objects to this array, you must send the addObject:
message to the array with the object that you are adding to the array as a parameter.
[listOfLetters addObject:@"A"];
[listOfLetters addObject:@"B"];
[listOfLetters addObject:@"C"];
When you use addObject:
you are always adding objects to the end of the array list. If you would like to insert an object into another postion in the array, you need to use the insertObject:atIndex:
method.
[listOfLetters insertObject:@"a"
atIndex:0];
This will insert the object into the first position in the array.
If you want to completely replace one object with another object at a particular index, you can use the replaceObjectAtIndex:withObject:
method. Here is how to replace the string C with the lowercase c:
[listOfLetters replaceObjectAtIndex:2
withObject:@"c"];
To have two objects in the array exchange places, you can use the exchangeObjectAtIndex:withObjectAtIndex:
method.
[listOfLetters exchangeObjectAtIndex:0
withObjectAtIndex:2];
When you need to remove objects from your array, you have a few different methods to choose from. You can remove an object at a specified index, you can remove the last object in the array, and you can remove all objects from the list. If you have a reference to the object on hand, you can also use that object reference to remove that object from the array. Here are some examples of removing objects:
[listOfLetters removeObject:@"A"];
[listOfLetters removeObjectAtIndex:1];
[listOfLetters removeLastObject];
[listOfLetters removeAllObjects];
See Listing 3-11 for the code.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSMutableArray *listOfLetters = [[NSMutableArray alloc] init];
[listOfLetters addObject:@"A"];
[listOfLetters addObject:@"B"];
[listOfLetters addObject:@"C"];
NSLog(@"OBJECTS ADDED TO ARRAY: %@", listOfLetters);
[listOfLetters insertObject:@"a"
atIndex:0];
NSLog(@"OBJECT 'a' INSERTED INTO ARRAY: %@", listOfLetters);
[listOfLetters replaceObjectAtIndex:2
withObject:@"c"];
NSLog(@"OBJECT 'c' REPLACED 'C' IN ARRAY: %@", listOfLetters);
[listOfLetters exchangeObjectAtIndex:0
withObjectAtIndex:2];
NSLog(@"OBJECT AT INDEX 1 EXCHANGED WITH OBJECT AT INDEX 2 IN ARRAY: %@",
listOfLetters);
[listOfLetters removeObject:@"A"];
NSLog(@"OBJECT 'A' REMOVED IN ARRAY: %@", listOfLetters);
[listOfLetters removeObjectAtIndex:1];
NSLog(@"OBJECT AT INDEX 1 REMOVED IN ARRAY: %@", listOfLetters);
[listOfLetters removeLastObject];
NSLog(@"LAST OBJECT REMOVED IN ARRAY: %@", listOfLetters);
[listOfLetters removeAllObjects];
NSLog(@"ALL OBJECTS REMOVED IN ARRAY: %@", listOfLetters);
}
return 0;
}
To use this code, build and run your Mac app from Xcode. Check the console to see what happens to the array after each operation is applied.
OBJECTS ADDED TO ARRAY: (
A,
B,
C
)
OBJECT 'a' INSERTED INTO ARRAY: (
a,
A,
B,
C
)
OBJECT 'c' REPLACED 'C' IN ARRAY: (
a,
A,
B,
c
)
OBJECT AT INDEX 1 EXCHANGED WITH OBJECT AT INDEX 2 IN ARRAY: (
B,
A,
a,
c
)
OBJECT 'A' REMOVED IN ARRAY: (
B,
a,
c
)
OBJECT AT INDEX 1 REMOVED IN ARRAY: (
B,
c
)
LAST OBJECT REMOVED IN ARRAY: (
B
)
ALL OBJECTS REMOVED IN ARRAY: (
)
You want to save the objects in your array to the file system to be used later or by another program.
If your array contains lists of number or string objects, you can save all of these to your file system to be used later. Use the writeToFile:atomically:
method to do this. Note that this does not work with custom objects. Custom objects require you to adopt the NSCoding protocol and use an archiving class (Chapter 9) or Core Data (Chapter 10).
For this recipe, create an array filled up with strings and numbers.
NSArray *listOfObjects = [NSArray arrayWithObjects:@"A", @"B", @"C", [NSNumber
numberWithInt:1], [NSNumber numberWithInt:2], [NSNumber numberWithInt:3], nil];
To save this to the file system, you first need a file reference.
NSString *filePathName = @"/Users/Shared/array.txt";
NOTE: This recipe assumes that you are trying this from a Mac app. iOS file references work differently; see Recipe 2.5 for examples of how to get iOS file references.
Now you can use the writeToFile:atomically:
method to write the contents of this array to the Mac’s file system.
[listOfObjects writeToFile:filePathName
atomically:YES];
See Listing 3-12 for the code.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSArray *listOfObjects = [NSArray arrayWithObjects:@"A", @"B", @"C", [NSNumber
numberWithInt:1], [NSNumber numberWithInt:2], [NSNumber numberWithInt:3], nil];
NSString *filePathName = @"/Users/Shared/array.txt";
[listOfObjects writeToFile:filePathName
atomically:YES];
}
return 0;
}
To use this code, build and run your Mac app from Xcode. Use Finder to locate the file that was created, which will be at /Users/Shared/array.txt
. Here is what the contents of the text file will look like:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<string>A</string>
<string>B</string>
<string>C</string>
<integer>1</integer>
<integer>2</integer>
<integer>3</integer>
</array>
</plist>
The data is organized in XML format as a property list (an Objective-C format to store keyed data).
You have files available to your app that contain content organized like an array and you want to use this content in your application.
If you have a file from an array that was saved using the writeToFile:atomically:
method, use the initWithContentsOfFile:
constructor to instantiate a new array populated with the contents from the file.
For this recipe, use the file from Recipe 3.8 where you saved the contents of an array to the file system. So, use the same file path name here:
NSString *filePathName = @"/Users/Shared/array.txt";
NOTE: This recipe assumes that you are trying this from a Mac app. iOS file references work differently; see Recipe 2.5 for examples of how to get iOS file references.
Once you have that, you can use the initWithContentsOfFile:
constructor to create a new array populated with the content from the file.
NSArray *listOfObjects = [[NSArray alloc] initWithContentsOfFile:filePathName];
See Listing 3-13 for the code.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSString *filePathName = @"/Users/Shared/array.txt";
NSArray *listOfObjects = [[NSArray alloc] initWithContentsOfFile:filePathName];
NSLog(@"%@", listOfObjects);
}
return 0;
}
To use this code, build and run your Mac app from Xcode. Inspect the log to see the contents of the array.
(
A,
B,
C,
1,
2,
3
)
Your app requires you to group objects together in a list and you want to be able to reference the objects using a key.
Objective-C has two Foundation classes named NSDictionary
and NSMutableDictionary
that you can use to create lists of objects with keys. Use NSDictionary
when you want a list that you know you won’t need to change on the fly and NSMutableDictionary
when you know you will need to add and remove objects from the dictionary later.
Dictionaries are created in Objective-C like other objects: you can use the alloc
and init
constructors or convenience functions like dictionaryWithObjects:forKeys:
to create the dictionary. If you use NSDictionary
to create your dictionary, you can’t make any changes to the dictionary once the dictionary is created. Use NSMutableDictionary
to create dictionaries that you can later modify.
Here is an example of creating a dictionary that contains Hello World
in different languages. Each version of the phrase is keyed to its language.
NSArray *listOfObjects = [NSArray arrayWithObjects:@"Hello World", @"Bonjour tout le
monde", @"Hola Mundo", nil];
NSArray *listOfKeys = [NSArray arrayWithObjects:@"english", @"french", @"spanish", nil];
NSDictionary *dictionary2 = [NSDictionary dictionaryWithObjects:listOfObjects
forKeys:listOfKeys];
The NSDictionary
constructor arrayWithObjects:forKeys:
requires two arrays as parameters. The first array must contain the objects to be stored while the second array must contain the keys associated with the objects.
If you choose to use NSMutableDictionary
, you can use the same constructors to create your arrays (NSMutableDictionary
is a subclass of NSDictionary
). You can also create your NSMutableDictionary
by using alloc
and init
since you will likely add objects to your array at some future point. See Table 3-3 for a complete list of available constructors for NSDictionary
and NSMutableDictionary
and Listing 3-14 for the code.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSDictionary *dictionary1 = [[NSDictionary alloc] init];
NSArray *listOfObjects = [NSArray arrayWithObjects:@"Hello World",
@"Bonjour tout le monde", @"Hola Mundo", nil];
NSArray *listOfKeys = [NSArray arrayWithObjects:@"english", @"french",
@"spanish", nil];
NSDictionary *dictionary2 = [NSDictionary dictionaryWithObjects:listOfObject
forKeys:listOfKeys];
NSLog(@"dictionary2 = %@", dictionary2);
}
return 0;
}
To use this code, build and run your Mac app from Xcode. You can set a breakpoint and use the Xcode debugger to inspect the contents of these dictionaries. In the next recipe, you will see how to reference each of these dictionary elements so you can print out their contents to the log or use them elsewhere in your programs. You can see the entire contents of the dictionary printed out in your log.
dictionary2 = {
english = "Hello World";
french = "Bonjour tout le monde";
spanish = "Hola Mundo";
}
You would like to get references to the objects in your dictionaries to either access their properties or to send messages to the objects.
Use the objectForKey:
method to get a reference to the object referenced by the key that you supply.
NSDictionary
objects keep lists of objects organized based on the keys that you provide. This makes it very easy and fast to look up any object of interest. Simply use objectForKey:
and provide the key for the object that you want to look up to get the reference that you need.
NSString *helloWorld = [dictionary objectForKey:@"english"];
See Listing 3-15 for the code.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSArray *listOfObjects = [NSArray arrayWithObjects:@"Hello World",
@"Bonjour tout le monde", @"Hola Mundo", nil];
NSArray *listOfKeys = [NSArray arrayWithObjects:@"english", @"french",
@"spanish", nil];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:listOfObjects
forKeys:listOfKeys];
NSString *helloWorld = [dictionary objectForKey:@"english"];
NSLog(@"%@", helloWorld);
}
return 0;
}
To use this code, build and run your Mac app from Xcode. The hello world
message that prints out is the one keyed to English.
Hello World
To see the hello world message in French, add this code to your application:
helloWorld = [dictionary objectForKey:@"french"];
NSLog(@"%@", helloWorld);
Run the app again and take a look at the last console message to see the French hello world message. You can do the same for Spanish as well.
Your app is working with the content in your dictionaries and you need to know how many elements are in the dictionary to present your content appropriately.
NSDictionary
objects have a count
property that you can use to find out how many elements are in the dictionary.
To use the count
property, you can use dot notation (dictionary.count
) on any dictionary object or you can send the count message ([dictionary count
]) to find out how many elements are in the dictionary. See Listing 3-16 for the code.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSArray *listOfObjects = [NSArray arrayWithObjects:@"Hello World",
@"Bonjour tout le monde", @"Hola Mundo", nil];
NSArray *listOfKeys = [NSArray arrayWithObjects:@"english", @"french",
@"spanish", nil];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:listOfObjects
forKeys:listOfKeys];
NSUInteger count = dictionary.count;
NSLog(@"The dictionary contains %lu items", count);
}
return 0;
}
To use this code, build and run your Mac app from Xcode. The log message will present the number of elements.
The dictionary contains 3 items
You have a dictionary of objects and you would like to be able to send the same message or access the same property for every object in the dictionary.
Use the allValues NSDictionary
function to convert the dictionary to an array that you can use with a for-each
loop. Or use enumerateKeysAndObjectsUsingBlock:
to work with each object in the dictionary.
NSDictionary
objects come with one built-in way to iterate through a list of objects. However, you can temporarily convert the dictionary key and object contents to arrays if you would rather use the methods described in Recipe 3.4. For instance, to iterate through the objects in a dictionary using a for-each
loop, you could do something like this:
The allValues NSDictionary
function is what gives you the objects organized like an array instead of a dictionary. There is also an allKeys
function that gives you all the key values as an array.
for (NSString *s in [dictionary allKeys]) {
NSLog(@"key: %@", s);
}
You can also use blocks to execute code for each object in a dictionary by using the enumerateKeysAndObjectsUsingBlock:
method. You can use this to define a block of code that will be applied to each object in the dictionary without setting up a for-each
loop or getting references to the array version of the dictionary.
[dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSLog(@"key = %@ and obj = %@", key, obj);
}];
See Listing 3-17 for the code.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSArray *listOfObjects = [NSArray arrayWithObjects:@"Hello World",
@"Bonjour tout le monde", @"Hola Mundo", nil];
NSArray *listOfKeys = [NSArray arrayWithObjects:@"english", @"french",
@"spanish", nil];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:listOfObjects
forKeys:listOfKeys];
for (NSString *s in [dictionary allValues]) {
NSLog(@"value: %@", s);
}
for (NSString *s in [dictionary allKeys]) {
NSLog(@"key: %@", s);
}
[dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSLog(@"key = %@ and obj = %@", key, obj);
}];
}
return 0;
}
To use this code, build and run your Mac app from Xcode. The log message will present the results of each way of iterating through the dictionary.
value: Hello World
value: Bonjour tout le monde
value: Hola Mundo
key: english
key: french
key: spanish
key = english and obj = Hello World
key = french and obj = Bonjour tout le monde
key = spanish and obj = Hola Mundo
You want your dictionary content to be more dynamic so that you or users can add, remove, and insert objects into dictionaries. However, NSDictionary
is an immutable class, so once you create an NSDictionary
you can’t make any changes to its contents.
When you know that your dictionary needs to be dynamic, use NSMutableDictionary
. It is a subclass of NSDictionary
, which means that you can work with NSMutableDictionary
as you would with NSDictionary
. But NSMutableDictionary
gives you methods that let you add, remove, and insert objects into the dictionary.
First, you must instantiate an NSMutableDictionary
object. You can use any constructor to do this. To create a new empty NSMutableDictionary
, you may simply use alloc
and init
.
To add objects to this array, you must send the setObject:forKey:
message to the dictionary with the object that you are adding and the key that goes with the object.
[dictionary setObject:@"Hello World"
forKey:@"english"];
[dictionary setObject:@"Bonjour tout le monde"
forKey:@"french"];
[dictionary setObject:@"Hola Mundo
forKey:@"spanish"];
When you use setObject:forKey
you are always adding objects to the dictionary indexed by the key that you provide.
To remove an object from a dictionary, you must have the key that is matched to the object. If you have the key, you can use the removeObjectForKey:
method to remove an object.
[dictionary removeObjectForKey:@"french"];
Finally, you can remove all the objects from the dictionary at once by using the removeAllObjects
method. See Listing 3-18 for the code.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
[dictionary setObject:@"Hello World"
forKey:@"english"];
[dictionary setObject:@"Bonjour tout le monde"
forKey:@"french"];
[dictionary setObject:@"Hola Mundo"
forKey:@"spanish"];
NSLog(@"OBJECTS ADDED TO DICTIONARY: %@", dictionary);
[dictionary removeObjectForKey:@"french"];
NSLog(@"OBJECT REMOVED FROM DICTIONARY: %@", dictionary);
[dictionary removeAllObjects];
NSLog(@"ALL OBJECTS REMOVED FROM DICTIONARY: %@", dictionary);
}
return 0;
}
To use this code, build and run your Mac app from Xcode. Check the log console to see what happens to the dictionary after each operation is applied.
OBJECTS ADDED TO DICTIONARY: {
english = "Hello World";
french = "Bonjour tout le monde";
spanish = "Hola Mundo";
}
OBJECT REMOVED FROM DICTIONARY: {
english = "Hello World";
spanish = "Hola Mundo";
}
ALL OBJECTS REMOVED FROM DICTIONARY: {
}
You want to save the objects in your dictionary to the file system to be used later on or by another program.
If your dictionary contains lists of number or string objects, you can save all of these to your file system to be used later. Use the writeToFile:atomically:
method to do this. Note that this does not work with custom objects.
For this recipe, set up a dictionary with phrases matched to keys.
NSArray *listOfObjects = [NSArray arrayWithObjects:@"Hello World",
@"Bonjour tout le monde", @"Hola Mundo", nil];
NSArray *listOfKeys = [NSArray arrayWithObjects:@"english", @"french", @"spanish", nil];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:listOfObjects
forKeys:listOfKeys];
To save this to the file system, you first need a file reference.
NSString *filePathName = @"/Users/Shared/dictionary.txt";
NOTE: This recipe assumes that you are trying this from a Mac app. iOS file references work differently; see Recipe 2.5 for examples of how to get iOS file references.
Now you can use the writeToFile:atomically:
method to write the contents of this dictionary to the Mac’s file system.
[dictionary writeToFile:filePathName
atomically:YES];
See Listing 3-19 for the code.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSArray *listOfObjects = [NSArray arrayWithObjects:@"Hello World",
@"Bonjour tout le monde", @"Hola Mundo", nil];
NSArray *listOfKeys = [NSArray arrayWithObjects:@"english", @"french",
@"spanish", nil];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:listOfObjects
forKeys:listOfKeys];
NSString *filePathName = @"/Users/Shared/dictionary.txt";
[dictionary writeToFile:filePathName
atomically:YES];
}
return 0;
}
To use this code, build and run your Mac app from Xcode. Use Finder to locate the file that was created (which will be at /Users/Shared/dictionary.txt)
. Here is what the contents of the text file will look like:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>english</key>
<string>Hello World</string>
<key>french</key>
<string>Bonjour tout le monde</string>
<key>spanish</key>
<string>Hola Mundo</string>
</dict>
</plist>
The data is organized in XML format as a property list (an Objective-C format to store keyed data).
You have files available to your app that contain content organized like a dictionary and you want to use this content in your application.
If you have a file from a dictionary that was saved using the writeToFile:atomically:
method, use the initWithContentsOfFile:
constructor to instantiate a new dictionary populated with the contents from the file.
For this recipe, use the file from Recipe 3.15 with the contents of that dictionary on the file system. So, you can use the same file path name here:
NSString *filePathName = @"/Users/Shared/dictionary.txt";
NOTE: This recipe assumes that you are trying this from a Mac app. iOS file references work differently; see Recipe 2.5 for examples of how to get iOS file references.
Once you have that, you can use the initWithContentsOfFile:
constructor to create a new dictionary populated with the content from the file.
NSDictionary *dictionary = [[NSDictionary alloc] initWithContentsOfFile:filePathName];
See Listing 3-20 for the code.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSString *filePathName = @"/Users/Shared/dictionary.txt";
NSDictionary *dictionary = [[NSDictionary alloc]
initWithContentsOfFile:filePathName];
NSLog(@"dictionary: %@", dictionary);
}
return 0;
}
To use this code, build and run your Mac app from Xcode. Inspect the log to see the contents of the dictionary.
dictionary: {
english = "Hello World";
french = "Bonjour tout le monde";
spanish = "Hola Mundo";
}
Your app requires you to group objects together in an unordered collection or a set.
Objective-C has two Foundation classes named NSSet
and NSMutableSet
that you can use to create sets. Use NSSet
when you have a set that you know you won’t need to change on the fly and NSMutableSet
when you know you will need to add and remove objects from the set later.
Sets are created in Objective-C like other objects: use the alloc
and init
constructors or convenience functions like setWithObjects:
to create the set. If you use NSSet
to create your set, you can’t make any changes to the dictionary once the set is created. Use NSMutableSet
to create sets that you can later modify.
Here is an example of creating a set that contains Hello World
in different languages:
NSSet *set = [NSSet setWithObjects:@"Hello World", @"Bonjour tout le monde", @"Hola
Mundo", nil];
The NSSet
constructor setWithObjects:
requires a nil-terminated array with the objects that will appear in the set.
If you choose to use NSMutableSet
, you can use the same constructors to create your sets (NSMutableSet
is a subclass of NSSet
). You can also create your NSMutableSet
by using alloc
and init
since you will likely add objects to your set at some future point. See Table 3-4 for a complete list of available constructors for NSSet
and NSMutableSet
and Listing 3-21 for the code.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSSet *set = [NSSet setWithObjects:@"Hello World", @"Bonjour tout le monde",
@"Hola Mundo", nil];
NSLog(@"set: %@",set);
}
return 0;
}
To use this code, build and run your Mac app from Xcode. In your log you can see the entire contents of the set printed out.
set: {(
"Bonjour tout le monde",
"Hello World",
"Hola Mundo"
)}
Your app is working with the content in your sets and you need to know how many elements are in the set to present your content appropriately.
NSSet
objects have a count
property that you can use to find out how many elements are in the set.
To use the count property, you can use dot notation (set.count
) on any set object or you can send the count message ([set count
]) to find out how many elements are in the set. See Listing 3-22 for the code.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSSet *set = [NSSet setWithObjects:@"Hello World", @"Bonjour tout le monde",
@"Hola Mundo", nil];
NSUInteger count = set.count;
NSLog(@"The set contains %lu items", count);
}
return 0;
}
To use this code, build and run your Mac app from Xcode. The log message will present the number of elements.
The set contains 3 items
You work with many sets in your app and you would like to find out more information about each set and what objects are in each of your sets.
NSSet
comes with some built-in methods that you can use to compare sets. You can find out if two sets intercept (they have some elements in common). You can find out if one set is a subset of another (one set is composed of objects that are entirely in another set). You can also find out if one set is equal to another or if an object is already in a set.
For this recipe, you need two sets. These sets should simply have string objects for letters in the alphabet.
NSSet *set1 = [NSSet setWithObjects:@"A", @"B", @"C", @"D", @"E", nil];
NSSet *set2 = [NSSet setWithObjects:@"D", @"E", @"F", @"G", @"H", nil];
If you want to see if these sets have objects that overlap (the sets intersect), you can use the intersectsSet:
function to return a BOOL
.
BOOL setsIntersect = [set1 intersectsSet:set2];
To find out if one set contains objects that are entirely in another set, use the isSubsetOfSet:
function.
BOOL set2IsSubset = [set2 isSubsetOfSet:set1];
To test whether two sets are identical, use the isEqualToSet:
function.
BOOL set1IsEqualToSet2 = [set1 isEqualToSet:set2];
Finally, if you want to know whether an object is already in a set, use containsObject:
to find out.
BOOL set1ContainsD = [set1 containsObject:@"D"];
See Listing 3-23 for the code.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSSet *set1 = [NSSet setWithObjects:@"A", @"B", @"C", @"D", @"E", nil];
NSSet *set2 = [NSSet setWithObjects:@"D", @"E", @"F", @"G", @"H", nil];
NSLog(@"set1 contains:%@", set1);
NSLog(@"set2 contains:%@", set2);
BOOL setsIntersect = [set1 intersectsSet:set2];
BOOL set2IsSubset = [set2 isSubsetOfSet:set1];
BOOL set1IsEqualToSet2 = [set1 isEqualToSet:set2];
BOOL set1ContainsD = [set1 containsObject:@"D"];
NSLog(@"setsIntersect = %i, set2IsSubset = %i, set1IsEqualToSet2 = %i,
set1ContainsD = %i", setsIntersect, set2IsSubset, set1IsEqualToSet2, set1ContainsD);
}
return 0;
}
To use this code, build and run your Mac app from Xcode. The log message will present the sets and the results of the various tests. The log will print out 1
when a BOOL
is YES
and 0
when a BOOL
is NO
.
set1 contains:{(
A,
D,
B,
E,
C
)}
set2 contains:{(
H,
F,
D,
G,
E
)}
setsIntersect = 1, set2IsSubset = 0, set1IsEqualToSet2 = 0, set1ContainsD = 1
You have a set of objects and you would like to be able to send the same message or access the same property for every object in the set.
Use the allObjects NSSet
function to convert the set to an array and then you can use a for-each
loop. Or use enumerateObjectsUsingBlock:
to work with each object in the set. NSSet
also supports makeObjectsPerformSelector:
, which is great when you specifically want each object to execute just one method.
You can temporarily convert the set contents to an array if you would like to use the methods described in Recipe 3.4. For instance, to iterate through the objects in a set using a for-each
loop, you could do something like this:
for (NSString *s in [set allObjects]) {
NSLog(@"value: %@", s);
}
You can also use blocks to execute code for each object in a set by using the enumerateObjectsUsingBlock:
method. You can use this to define a block of code that will be applied to each object in the dictionary without setting up a for-each
loop or getting references to the array version of the set.
[set enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
NSLog(@"obj = %@", obj);
}];
If you want to simply perform one action on each object and that action is a method coded in the object’s class definition, you can use makeObjectsPerformSelector:.
[set makeObjectsPerformSelector:@selector(description)];
See Listing 3-24 for the code.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSSet *set = [NSSet setWithObjects:@"Hello World", @"Bonjour tout le monde",
@"Hola Mundo", nil];
for (NSString *s in [set allObjects]) {
NSLog(@"value: %@", s);
}
[set enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
NSLog(@"obj = %@", obj);
}];
[set makeObjectsPerformSelector:@selector(description)];
}
return 0;
}
To use this code, build and run your Mac app from Xcode. The log message will present the results of each way of iterating through the set.
value: Bonjour tout le monde
value: Hello World
value: Hola Mundo
obj = Bonjour tout le monde
obj = Hello World
obj = Hola Mundo
You want your set contents to be more dynamic so that you or your users can add objects to sets and remove objects from sets. However, NSSet
is an immutable class, so once you create an NSSet
you can’t make any changes to its contents.
When you know that your set needs to be dynamic, use NSMutableSet
. It is a subclass of NSSet
and so you can work with NSMutableArray
as you would with NSSet
. But NSMutableSet
provides methods to add and remove objects.
First, instantiate a NSMutableSet
object. You can use any constructor to do this. To create a new empty NSMutableSet
, you can use alloc
and init
.
NSMutableSet *set = [[NSMutableSet alloc] init];
To add objects to this set, you must send the addObject:
message to the set with the object that you are adding as a parameter.
[set addObject:@"Hello World"];
[set addObject:@"Bonjour tout le monde"];
[set addObject:@"Hola Mundo"];
To remove an object from a set, you must already have a reference to the object. If you have this, then you can use removeObject
.
[set removeObject:@"Bonjour tout le monde"];
Finally, you can remove all the objects from the set at once by using the removeAllObjects
method. See Listing 3-25 for the code.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSMutableSet *set = [[NSMutableSet alloc] init];
[set addObject:@"Hello World"];
[set addObject:@"Bonjour tout le monde"];
[set addObject:@"Hola Mundo"];
NSLog(@"Objects added to set:%@", set);
[set removeObject:@"Bonjour tout le monde"];
NSLog(@"Object removed from set:%@", set);
[set removeAllObjects];
NSLog(@"All objects removed from set:%@", set);
}
return 0;
}
To use this code, build and run your Mac app from Xcode. Check the console to see what happens to the set after each operation is applied.
Objects added to set:{(
"Bonjour tout le monde",
"Hello World",
"Hola Mundo"
)}
Object removed from set:{(
"Hello World",
"Hola Mundo"
)}
All objects removed from set:{(
)}
18.118.24.106