Справочник по objective-c

20
Справочник по Objective-c основы введение стороки массивы ассоциативные массивы ООП создание класса конструктор/деструктор методы инкапсуляция свойства протокол категории селектор разное исключения управление памятью

Upload: -

Post on 10-Oct-2014

2.463 views

Category:

Documents


5 download

TRANSCRIPT

Page 1: Справочник по  Objective-C

Справочник по Objective-cосновывведениесторокимассивы ассоциативные массивы ООПсоздание класса конструктор/деструктор методы инкапсуляция свойства протокол категории селектор разноеисключения управление памятью

Page 2: Справочник по  Objective-C

Строки

Класс NSString описывает не изменяемую строку. Ниже приведены основные методы:

• + stringWithFormat - создает строку из указанных аргументов;• + localizedStringWithFormat - создает локализованную строку из

указанных аргументов;• + stringWithUTF8String - создание utf8 строки;• length - число символов в строке;• stringByAppendingString - добавить строку;• componentsSeparatedByString - разбивает строку в массив по указанным

символам;• substringFromIndex - выделить подстроку с указанного символа;• substringWithRange - выделить подстроку в указанном диапазоне;• substringToIndex - выделить подстроку до указанного символа;• hasPrefix - начинается ли строка с указанной подстроки;• hasSuffix - завершается ли строка указанной подстрокой;• isEqualToString - равенство строк;• compare - сравнение строк, возвращается тип enum:

◦ NSOrderedAscending - если эта строка меньше;◦ NSOrderedSame - если строки равны;◦ NSOrderedDescending - если эта строка больше;

• caseInsensitiveCompare - сравнение строк без учета регистра символов;• localizedCompare - сравнение строк с учетом локализации;• localizedCaseInsensitiveCompare - сравнение строк без учета регистра

символов, с учетом локализации• capitalizedString - первые символы слов в верхний регистр;• lowercaseString - все символы в нижний регистр;• uppercaseString - все символы в верхний регистр;• doubleValue - разобрать строку как число типа double;• floatValue - разобрать строку как число типа float;• intValue - разобрать строку как целое число;• integerValue - разобрать строку как целое число ;• longLongValue - разобрать строку как целое число;• boolValue - разобрать строку как логический тип, возвращает YES если

первый символ "Y", "y", "T", "t" или цифра от 1 до 9;

Page 3: Справочник по  Objective-C

• stringByAddingPercentEscapesUsingEncoding - возвращает строку готовую для использования в качестве URL (%последовательностью), в качестве параметра кодировки рекомендуется использовать stringByReplacingPercentEscapesUsingEncoding;

• stringByReplacingPercentEscapesUsingEncoding - обратная операция предыдущему методу;

Литерально строку можно задать @"....".NSString *str = @"Hello world";NSString *str1 = [NSString stringWithFormat:@"%@ %@ ", s1, s2];

// поиск подстрокиNSString *src = @"Hello world! - most known sentence";NSRange range = [src rangeOfString:@"most"]; // а теперь определяем, есть ли такая подстрока ?if (range.length > 0) NSLog(@"Range is: %@", NSStringFromRange(range));

Если строка часто изменяется, то следует воспользоваться классом NSMutableString:

• appendFormat - добавляет указанную строку формата с параметрами, далее следуют параметры;

• appendString - добавляет указанную строку;• deleteCharactersInRange - удаляет символы из указанного диапазона;• insertString - вставляет строку в указанную позицию;• replaceCharactersInRange - заменяет подстроку указанной строкой;• replaceOccurrencesOfString - заменяет все вхождения строки;• setString - устанавливает значение в новую строку;

Page 4: Справочник по  Objective-C

Массивы

Для работы с массивами в Cocoa определены следующие классы:• NSArray - класс описывающий статический массив, т.е. с неизменяемым

числом элементов• NSMutableArray - класс описывающий динамический массив.

Расширение класса NSArray, к которому добавлены методы добавление, вставки и удаления объектов;

Кроме этого можно работать с массивами в стиле C.

создание и инициализация статического массива• + array - создает пустой массив, используется дочерними классами;• + arrayWithArray:- создает и возвращает массив, содержащий объекты из

указанного массива;• + arrayWithContentsOfFile: - загружает элементы из файла содержащего

список свойств• + arrayWithContentsOfURL: - аналогично предыдущему, только xml

файл загружается по указанному url;• + arrayWithObject: - создает массив с одним указанным объектом;• + arrayWithObjects: - создает массив из перечисленных через запятую

объектов, последним должен быть nil;• + arrayWithObjects:count: - создает массив из объектов в С-массиве;• – initWithArray: - инициализирует массив объектами из указанного

массива;• – initWithArray:copyItems: - аналогично предыдущему, только создаются

копии объектов массива, соответственно объекты должны поддерживать протокол NSCopying ;

• – initWithContentsOfFile: - инициализирует массив данными из файла (см. arrayWithContentsOfFile);

• – initWithContentsOfURL: - инициализирует массив данными из файла по указанному url (см. arrayWithContentsOfURL);

• – initWithObjects: - инициализирует массив перечисленными через запятую объектами, последним должен быть nil;

• – initWithObjects:count: - инициализирует массив объектами в указанном C-массиве;

Page 5: Справочник по  Objective-C

доступ к элементам массива• – containsObject: - определяет содержит ли массив указанный объект;• – count - число элементов в массиве;• – getObjects:range: - копирует объекты из указанного диапазона в буфер

(указатель на С-массив типа (id*));• – lastObject - возвращает последний элемент, или nil если массив пустой;• – objectAtIndex: - возвращает объект по указанному индексу;• – objectsAtIndexes: - возвращает массив объектов по указанному

множеству индексов;• – objectEnumerator - возвращает итератор по массиву от младшего к

большему индексу;• – reverseObjectEnumerator - возвращает обратный итератор по массиву,

т.е. от большего к меньшему индексу;

поиск элементовПоиск объекта происходит через метод isEqual: протокола NSObject. Если

ничего не найдено возвращается значение NSNotFound.• – indexOfObject: - поиск указанного объекта;• – indexOfObject:inRange: - возвращает наименьший индекс в указанном

диапазоне по которому есть объект;• – indexOfObjectPassingTest: - ищет первый объект, который пройдет

указанный тест;• – indexOfObjectWithOptions:passingTest: - ищет первый объект, который

пройдет указанный тест;• – indexOfObjectAtIndexes:options:passingTest: - вариация предыдущего ;• – indexesOfObjectsPassingTest: - возвращает множество индексов

объектов, прошедших указанный тест;• – indexesOfObjectsWithOptions:passingTest: - вариация предыдущего;• – indexesOfObjectsAtIndexes:options:passingTest: - ;

удаление элементов• – removeAllObjects - удалить все объекты;• – removeLastObject - удалить последний объект;• – removeObject: - удаляет все вхождения указанного объекта;• – removeObject:inRange: - удалить объект в указанном диапазоне;• – removeObjectAtIndex: - удалить объект в указанной позиции;• – removeObjectsAtIndexes: - удалить объекты по указанному множеству

индексов;

Page 6: Справочник по  Objective-C

• – removeObjectsInArray: - удалить все объекты в указанном массиве;• – removeObjectsInRange: - удалить все объекты в указанном диапазоне;

Ассоциативный массивДля работы с ассоциативными массивами определены следующие классы:

• NSDictionary - класс описывающий статический массив, т.е. с неизменяемым числом элементов

• NSMutableDictionary - класс описывающий динамический массив. Расширение класса NSDictionary, к которому добавлены методы добавление и удаления объектов;

В терминологии objective-c ассоциативные массивы называются словарями.// массив ключей, массив объектовNSArray *keys = [[NSArray alloc] initWithObjects:@"key1", @"key2",

@"key3", nil];NSArray *objs = [[NSArray alloc] initWithObjects:@"obj1", @"obj2",

@"obj3", nil];

//инициализируем словарь массивамиNSDictionary *dic = [[NSDictionary alloc] initWithObjects:objs

forKeys:keys];

// проходимся по словарюfor (id key in dic) { NSLog(@"key: %@ value:%@", key, [dic objectForKey:key]);}! // освобождаем ресурсы[keys release];[objs release];[dic release];

создание/инициализация• + (id)dictionaryWithObjectsAndKeys:(id)firstObject , ... - создает словарь

по указанным парам объект/ключ. Завершается перечисление объектом nil без ключа;

• + (id)dictionaryWithObject:(id)anObject forKey:(id)aKey - создает словарь с одним элементом;

• + (id)dictionaryWithObjects:(NSArray *)objects forKeys:(NSArray *)keys - создает словарь по массиву объектов и массиву ключей;

• Creates and returns a dictionary containing count objects from the objects array.

Page 7: Справочник по  Objective-C

• + (id)dictionaryWithObjects:(id *)objects forKeys:(id *)keys count:(NSUInteger)count - создает словарь на основе массива объектов и массива ключей в стиле C;

• + (id)dictionaryWithContentsOfFile:(NSString *)path - создает словарь на основе файла свойств;

• + (id)dictionaryWithContentsOfURL:(NSURL *)aURL - создает словарь но основе файла свойств указанного url ссылкой;

Также есть аналогичные конструкторы, вместо префикса dictionary префикс initWith.

доступ к элементам• – objectForKey: - возвращает объект по указанному ключу;• – valueForKey:• – allKeys - возвращает массив всех ключей;• – allKeysForObject: - возвращает новый массив ключей по которым

сохранен указанный объект;• – allValues - возвращает новый массив всех значений в словаре;• - (void)getObjects:(id *)objects andKeys:(id *)keys - сохраняет в

аргументах ссылки на массив объектов и ключей в стиле C;• - (NSArray *)objectsForKeys:(NSArray *)keys notFoundMarker:

(id)anObject - возвращает массив объектов соответствующие ключам из указанного массива;

динамический ассоциативный массивСледующие методы доступны только для NSMutableDictionary:

• - (void)setObject:(id)anObject forKey:(id)aKey - добавляет элемент в словарь;

• - (void)setValue:(id)value forKey:(NSString *)key - добавляет элемент в словарь, если значение равно nil, элемент удаляется;

• - (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary - добавляет элементы из другого словаря;

• - (void)setDictionary:(NSDictionary *)otherDictionary - удаляет все элементы из словаря, и добавляет все элементы из указанного словаря;

• - (void)removeObjectForKey:(id)aKey - удаляет элемент по указанному ключу;

• – removeAllObjects - удаляет все элементы;• - (void)removeObjectsForKeys:(NSArray *)keyArray - удаляет элемент по

ключам в указанному массиве;

Page 8: Справочник по  Objective-C

Создание класса

описание классаВ Cocoa базовым классом является NSObject. Класс объявляется в файле с

расширением .h по следующему шаблону #import "ИмяРодительскийКласс.h"// если наследуем от NSObject// #import<Foundation/NSObject.h>

@interface ИмяКласса : ИмяРодительскийКласс{// члены, как в структуре Cfloat width;float height;BOOL filled;NSColor *fillColor; }

// объявление методов+ alloc; // методы с + доступны через имя класса (как static в С++/Java) - (void)display;- (float)radius;

// методы с параметрами- (void)setRadius:(float)aRadius;- (void)setWidth:(float)width height:(float)height;

@end

Page 9: Справочник по  Objective-C

реализация классаРеализация класса делается в файлах с расширением .m.// импортируем объявление класса#import "ClassName.h"

@implementation ClassName

// определяем методы+ (id)alloc{ ...}

- (BOOL)isFilled{ ...}

- (void)setFilled:(BOOL)flag{ ...}@end

Создание и уничтожение объекта

Создание и уничтожение основано на методах и протоколах корневого класса NSObject:

• alloc - выделяет память под объект, дочерние классы не должны его переопределять;

• allocWithZone - выделяет память под объект из указанной области;• init - инициализирует объект. Объект не должен использоваться пока не

инициализирован;• release - уменьшает внутренний счетчик ссылок на объект. Когда

счетчик равен 0, то память выделенная под объект освобождается, соответственно сам объект уничтожается;

• retain - увеличивает внутренний счетчик ссылок на объект;• autorelease - добавляет объект в особый пул. Объект автоматически

будет уничтожен, при уничтожении пула;

Page 10: Справочник по  Objective-C

• finalize - автоматически вызывается перед уничтожением объекта, дочерние классы могут его переопределить для освобождения каких-либо ресурсов;

• retainCount - возвращает число ссылок на объект;Таким образом, следующий шаблон кода является типичнымMyClass *myClass = [[MyClass alloc] init]; // создаем/

инициализируем объект ... [myClass release]; // освобождаем ссылку на объектТакже есть устаревшее сообщение new являющееся, краткой записью

[[MyClass alloc] init].MyClass *myClass = [MyClass new];

инициализацияДля инициализации собственных классов нужно переопределить метод init.

Если инициализация по каким-либо причинам не проходит нужно освободить выделенную под объект память и возвратить nil. В некоторых случаях полезно уничтожить созданный объект и вернуть другой на замену.Каждый класс должен гарантировать, что init метод возвращает либо

полностью функциональный объект либо вызывать исключение- (id)init { self = [super init]; // инициализируем родительский класс

// если все ок if (self) { /* проводим инициализацию этого класса */ }

return self;}Альтернативные методы инициализации рекомендуется называть init...- (id)initWithTag:(int)tag;- (id)initWithTag:(int)tag data:(struct info *)data;

- (id)init{ return [self initWithTag:-1];}

Page 11: Справочник по  Objective-C

- (id)initWithTag:(int)tag{ return [self initWithTag:tag data:NULL];}

- (id)initWithTag:(int)tag data:(struct info *)data{ self = [super init...]; if (self) { ... } return self;}

уничтожение объектаОсвобождение ресурсов выносят в метод dealloc-(void)dealloc { array = NULL; [arrayData release]; [super dealloc];}

Если используется самоуничтожение, то нужно перегрузить метод finalize.- (void)finalize { if (log_file != NULL) { fclose(log_file); log_file = NULL; } [super finalize];}

Не рекомендуется определять оба метода. Либо используйте связку malloc/dealloc, либо NSAllocateCollectable/finalize.Дефицитные ресурсы, типа файлового дескриптора лучше освобождать

сразу, а не ждать сборки мусора.

Page 12: Справочник по  Objective-C

Методы объектовВ objective-c объект ассоциируется с компьютером, а его методы с

сообщениями которые ему можно послать. Поэтому методы objective-c немного сбивают с толку программистов C++/Java, по крайне мере меня. Пусть в интерфейсе объявлен метод с двумя параметрами: -(void) setNumerator: (int) n andDenominator: (int) d;Это легче воспринимать именно как новое двух составное сообщение

setNumerator:andDenominator:, а не метод setNumerator со вторым именованным аргументом.Хотя допускается создавать составные сообщение без именования

отдельных частей, это не рекомендуется. К тому же именованные сообщения легче читать. // вызов метода, или точнее отсылка сообщения объекту frac[frac setNumerator: 1 andDenominator: 5];

+ и - в методахКлассы в objective-c являются самостоятельными объектами как в джава.

Методы описанные с +, доступны объекту класса. Методы описанные с - доступны объектам экземплярам класса. Или по аналогии с джава плюсовые методы статические, а минусовые локальные.

ИнкапсуляцияДосупны следующие типы видимости членов:

• @private - член доступен только внутри класса;• @protected - член доступен внутри класса и в его потомках;• @public - член доступен всем;• @package - анлогично @public внутри исполняемого образа, и как

@private при доступе из вне;@interface Worker : NSObject{ char *name;@private char *evaluation;

@protected id job; float wage;

Page 13: Справочник по  Objective-C

@public id boss; int age;}СоответственноWorker * worker = [[Worker alloc] init];worker->age = 30; // разрешено// worker->wage = 60.23; // ошибка на стадии компиляции

СвойстваНачиная с 2.0 язык поддерживает свойства объекта. Это позволяет по

желанию автоматически генерировать сетер/гетер - методы задания и получения значения свойства. Во-вторых к свойствам можно обратиться через точку.

объявление свойстваДелается ключевым словом @property, может иметь следующие

дополнительные атрибуты:• readonly - свойство только для чтения;• readwrite - свойство для чтения и записи;• assign - просто назначить значение;• retain - увеличить ссылку (для свойств с типом указателя);• copy - назначить копию указанного значения;• nonatomic - если приложение не много-поточное, или потокобезопасность

обеспечиваете вы сами, используйте это;@interface MyObj : NSObject { @private int iProp; // член для свойства }

// определяем свойство@property (readwrite,assign) int iProp;@end

Page 14: Справочник по  Objective-C

методы доступа к свойствуПо умолчанию для чтения генерируется метода с именем свойства, в нашем

случае iProp. Для записи метод с префиксом set..., в нашем случае setIProp; @implementation MyObj @synthesize iProp;@end Синтезируемые имена методов доступа могут отличаться от имени свойства.

@implementation MyObj @synthesize anyprop = iProp;@end Можно определить собственные методы доступа через ключевое слово

@dynamic.@implementation MyObj@dynamic iProp;

-(int)iProp { NSLog(@"читаем iProp"); return 1;}

-(void)setIProp:(int)inIProp { NSLog(@"записываем в iProp");}@end

доступ к свойствамОбратите внимание, что вы можете обратиться как к члену класса, так и к

свойству. Если свойство определено с атрибутом retain, а инициализацию делаете через член класса, то счетчик ссылок не увеличится. Что может привести к крушению программы без каких-либо сообщений в консоли. (Например, я делал массив объектов для отображения списка, а элемент массива инициализировал как член класса без увеличения счетчика).

//обращаемся к члену класса iProp = anyval;

// обращаемся к свойству классаself.iProp = anyval;

// из внеMyObj * myObj = [[MyObj alloc] init];myObj.iProp=anyval;

Page 15: Справочник по  Objective-C

освобождение ресурсовПри уничтожении объекта следует освободить объекты на которые

ссылаются свойства с атрибутом retain.- (void) dealloc { [iProp release]; [super dealloc]; }

ПротоколПротокол соответствует понятию интерфейс в языке джава или классу с

одними чисто виртуальными методами в С++. То есть задает список методов, через которые можно общаться с объектом.описание протокола@protocol MyProtocolName

// объявление методов- (void) outData;

@endописание объекта с протоколомПоддерживаемые протоколы перечисляются в угловых скобках через

запятую.@interface MyClass: NSObject <MyProtocolName>...@end

реализация протоколаПросто в реализацию методов класса добавляются методы протокола.@implementation MyClass

- (void) outData {...}

...@end

протокол как переменнаяКак и в джаве можно создавать переменные типа протокола// переменная типа протоколаid<MyProtocolName> myProtocolName;

// по аналогии можно задать параметр метода - (void) doSomethingWithThisObject: (id<MyProtocolName>) aMyProtocolName;

Page 16: Справочник по  Objective-C

КатегорииВ objective-c расширить функциональность класса можно двумя способами.

Первый - создать дочерний класс с дополнительными методами. Второй - использовать категории. Категория позволяет добавить методы в уже существующий класс.Удобства:

• расширение классов других разработчиков, чьи исходники не доступны, например, классы из Cocoa библиотеки;

• внедрение нового класса сразу в несколько исходных текстов;• группировка методов;описание категорииОписание категории создается аналогично классу, но в круглых скобках

указывается имя категории. Код описания принято сохранять в файле ИмяКласса+ИмяКатегории.h (прямо со знаком +).

// включаем описание исходного класса#import "ClassName.h"1

@interface ClassName (CategoryName)

// объявление методов

@endреализация категории#import "ClassName+CategoryName.h" @implementation ClassName (CategoryName)

// реализация методов

@endМеханизм категорий чем-то схож на добавление методов в прототип класса

в JavaScript. Аналогичные возможности имеет язык Ruby.Не рекомендуется перегружать методы категорий в дочерних классах.

Page 17: Справочник по  Objective-C

Селектор Под селектором подразумевается имя метода, или сообщения в терминах

objective-c, когда оно используется в исходном коде. Тип SEL описывает скомпилированную форму селектора. Всем методам имеющие одинаковые имена компилятор назначает один и тот селектор.

NSString *str = @"Hello world";

// получаем селектор для имени lowercaseString SEL sel = @selector(lowercaseString);

// смотрим есть ли в str метод lowercaseString NSString *islower = (([str respondsToSelector:sel]) ? @"YES" : @"NO");

// выведем результат в консольNSLog (@"объект отвечает на сообщение lowercaseString: %@", islower);

// соответственно, если метод есть в объекте его можно вызватьif ([str respondsToSelector:sel]) //(islower == @"YES") NSLog(@"результат lowercaseString: %@" , [str lowercaseString]);

ИсключенияДля работы с исключениями определены следующие ключевые слова:

• @try - определяет блок кода, где может возникнуть исключение;• @catch - определяет блок обработки исключения;• @finally - определяет блок, который должен выполниться независимо

было ли исключение или нет;• @throw - бросает исключение;

@try { if(/*ошибка*/) { @throw exception; // кидаем исключение }}@catch (NSException * exception){ // как-то обрабатываем исключение [self onException: exception];}@finally{ //...}

Page 18: Справочник по  Objective-C

класс NSExceptionКласс описывающий исключение, ниже приведены некоторые методы:

• + exceptionWithName:reason:userInfo: - создает объект исключения с указанным именем, причиной и словарем пользовательской информацией об исключениях;

• – initWithName:reason:userInfo: - инициализация объекта;• – raise - вызвать исключение, вызывается всеми прочими методами

генерирующих исключение;• – name - имя исключения;• – reason - причина исключения;• – callStackSymbols - текущий массив вызовов;

// пример из офф. док.if (pDocument != nil) {

[self loadMetadata];

} else { [[NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"Could not open URL %@",

url] userInfo:nil] raise];}

@throw появилось позже и по сути аналогично методу raise. Таким образом, исключение можно вызвать двумя способами:

// создаем объект исключения;NSException* myException = [NSException exceptionWithName:@"FileNotFoundException" reason:@"File Not Found on System" userInfo:nil];

// вызываем исключение - новый способ@throw myException;

// или вызываем исключение по старому[myException raise];

Page 19: Справочник по  Objective-C

Управление памятьюОбъекты хранят в себе счетчик ссылок на себя. Когда счетчик равен 0,

объект удаляется.По соглашению, объект созданный с префиксом init или copy уже имеет

счетчик равный 1. Соответственно, если объект больше не будет использоваться, нужно этот счетчик уменьшить.

// создали объектNSString * str = [[NSString alloc] initWithFormat: @"%d" , 150];...[str release]; // уменьшили счетчикСоответственно, в методах возвращающих объект и имеющих префикс init,

new, copy счетчик уменьшать не надо.- (MyObj *) newMyObj { return [[MyObj alloc] init];}Объекты созданые другим способом являются самоуничтожающимися. Они

также уже имеют счетчик равным 1. Их можно использовать в контексте, где они были созданы. Посылать сообщение release не нужно. Но если вы планируете использовать объект позже в другом месте, то счетчик нужно увеличить, а потом уменьшить когда нужно.

// создали объектNSString * str = [NSString stringWithFormat:@"%d", 150]; ...// объект самоуничтожиться}Объекты созданные первым способом, также можно сделать

самоуничтожающимися, послав им сообщение autorelease.// возвращаем из метода объект с самоуничтоожениемreturn [obj autorelease];

пул самоуничтожающихся объектовМеханизм пулов позволяет создавать временные объекты, которые будут

уничтожены автоматически. В общих случаях нет необходимости создавать свой пул.Механизм пулов организован в виде стека. Если вы создаете новый пул, он

добавляется в вершину стека. Объекты добавляются в пул, который на вершине стека для текущего потока.

Page 20: Справочник по  Objective-C

Пул описывается классом NSAutoreleasePool и содержит в себе объекты, которым было послано сообщение autorelease. Когда пул уничтожается, уничтожаются все объекты в нем.

Cocoa всегда проверяет чтобы пул был в наличии. Если послать сообщение autorelease, когда пула нет, в логах будет выдано сообщение об ошибке. Библиотеки AppKit и UIKit автоматически создают пул вначале каждой итерации события, как клик по мыши.Таким образом, есть три случая когда нужно создавать пул самому:

• пишется консольное приложение;• ваш цикл использует слишком много временных объектов;• вы порождаете вторичный поток;Пулы не должны быть членами класса.// пример из офф док.NSArray *urls = <# какой-то массив урл #>;for (NSURL *url in urls) { NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init]; NSError *error = nil; NSString *fileContents = [[[NSString alloc]

initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error]

autorelease]; /* как-то используем наши строки */ ... [loopPool drain];}