@property (nonatomic, copy) NSArray *wheels;
@property (nonatomic, strong) UIColor *bodyColor;
@property (nonatomic, copy) NSArray *doors;
@end
Теперь, когда наш протокол определен, создадим класс, обозначающий автомобиль, - например, Jaguar, - а потом обеспечим соответствие этого класса протоколу. Просто выполните все шаги, перечисленные в подразделе "Как создавать классы и правильно пользоваться ими" данного раздела, после чего обеспечьте его соответствие протоколу Car следующим образом:
#import <Foundation/Foundation.h>
#import "Car.h"
@interface Jaguar: NSObject <Car>
@
end
Если вы попробуете собрать ваш проект на данном этапе, то компилятор выдаст вам несколько предупреждений, например такое:
Auto property synthesis will not synthesize property declared in a protocol
Это означает, что ваш класс Jaguar пытается соответствовать протоколу Car, но на самом деле не реализует всех требуемых свойств и/или методов, описанных в этом протоколе. Теперь вы уже знаете, что в протоколе могут содержаться необходимые и факультативные (опциональные) элементы, которые вы помечаете ключевыми словами @optional или @required. По умолчанию действует квалификатор @required, и поскольку мы явно не указываем квалификатор для этого протокола, компилятор неявно выбирает @required за нас. Следовательно, класс Jaguar теперь обязан реализовывать все аспекты, требуемые протоколом Car, вот так:
#import <Foundation/Foundation.h>
#import "Car.h"
@interface Jaguar: NSObject <Car>
@property (nonatomic, copy) NSArray *wheels;
@property (nonatomic, strong) UIColor *bodyColor;
@property (nonatomic, copy) NSArray *doors;
@end
Отлично. Теперь мы понимаем основы работы с протоколами, то, как они работают и как их определить. Далее в этой книге мы подробнее поговорим о протоколах, а на данный момент вы получили довольно полное представление о них.
Хранение элементов в коллекциях и получение элементов из коллекций
Коллекции - это такие объекты, в экземплярах которых могут храниться другие объекты. Одна из самых распространенных разновидностей коллекций - это массив, который инстанцирует NSArray или NSMutableArray. В массиве можно хранить любой объект, причем массив может содержать несколько экземпляров одного и того же объекта. В следующем примере мы создаем массив из трех строк:
NSArray *stringsArray = @[
@"String 1",
@"String 2",
@"String 3"
];
__unused NSString *firstString = stringsArray[0];
__unused NSString *secondString = stringsArray[1];
__unused NSString *thirdString = stringsArray[2];
Макрос __unused приказывает компилятору "не жаловаться", когда переменная - в нашем случае переменная firstString - объявлена, но ни разу не использовалась. По умолчанию в такой ситуации компилятор выдает в консоль предупреждение, сообщающее, что переменная не используется. В нашем кратком примере мы объявили переменные, но не задействовали их. Поэтому, если добавить вышеупомянутый макрос в начале объявления переменной, это вполне устроит и нас, и компилятор.
Изменяемый массив - это такой массив, в который можно вносить изменения уже после того, как он был создан. Как мы видели ранее, неизменяемый массив не может быть дополнен новой информацией уже после создания. Вот пример неизменяемого массива:
NSString *string1 = @"String 1";
NSString *string2 = @"String 2";
NSString *string3 = @"String 3";
NSArray *immutableArray = @[string1, string2, string3];
NSMutableArray *mutableArray = [[NSMutableArray alloc]
initWithArray: immutableArray];
[mutableArray exchangeObjectAtIndex:0 withObjectAtIndex:1];
[mutableArray removeObjectAtIndex:1];
[mutableArray setObject: string1 atIndexedSubscript:0];
NSLog(@"Immutable array = %@", immutableArray);
NSLog(@"Mutable Array = %@", mutableArray);
Вывод этой программы таков:
Immutable array = (
"String 1",
"String 2",
"String 3"
)
Mutable Array = (
"String 1",
"String 3"
)
Еще одна распространенная коллекция, которая часто встречается в программах для iOS, - это словарь. Словари похожи на массивы, но каждому объекту в словаре присваивается ключ, и по этому ключу вы можете позже получить интересующий вас объект. Рассмотрим пример:
NSDictionary *personInformation =
@{
@"firstName": @"Mark",
@"lastName": @"Tremonti",
@"age": @30,
@"sex": @"Male"
};
NSString *firstName = personInformation[@"firstName"];
NSString *lastName = personInformation[@"lastName"];
NSNumber *age = personInformation[@"age"];
NSString *sex = personInformation[@"sex"];
NSLog(@"Full name = %@ %@", firstName, lastName);
NSLog(@"Age = %@, Sex = %@", age, sex);
А вот и вывод этой программы:
Full name = Mark Tremonti
Age = 30, Sex = Male
Можно также использовать изменяемые словари, которые довольно сильно похожи на изменяемые массивы. Содержимое изменяемого словаря можно изменить после того, как словарь инстанцирован. Пример:
NSDictionary *personInformation =
@{
@"firstName": @"Mark",
@"lastName": @"Tremonti",
@"age": @30,
@"sex": @"Male"
};
NSMutableDictionary *mutablePersonInformation =
[[NSMutableDictionary alloc] initWithDictionary: personInformation];
mutablePersonInformation[@"age"] = @32;
NSLog(@"Information = %@", mutablePersonInformation);
Вывод этой программы таков:
Information = {
age = 32;
firstName = Mark;
lastName = Tremonti;
sex = Male;
}
Еще можно работать с множествами. Множества похожи на массивы, но любой объект, входящий в состав множества, должен встречаться в нем только один раз. Иными словами, в одном множестве не может быть двух экземпляров одного и того же объекта. Пример множества:
NSSet *shoppingList = [[NSSet alloc] initWithObjects:
@"Milk",
@"Bananas",
@"Bread",
@"Milk", nil];
NSLog(@"Shopping list = %@", shoppingList);
Запустив эту программу, вы получите следующий вывод:
Shopping list = {(
Milk,
Bananas,
Bread
)}
Обратите внимание: элемент Milk упомянут в программе дважды, а в множество добавлен всего один раз. Эта черта множеств - настоящее волшебство. Изменяемые множества можно использовать и вот так:
NSSet *shoppingList = [[NSSet alloc] initWithObjects:
@"Milk",
@"Bananas",
@"Bread",
@"Milk", nil];
NSMutableSet *mutableList = [NSMutableSet setWithSet: shoppingList];
[mutableList addObject:@"Yogurt"];