Слайд 3Что такое Objective-C?
Объектно-ориентированный язык программирования
Расширение стандартного ANSI C
Слайд 4С чем работаем?
Язык Objective-C/C++
Objective-C Runtime
Библиотеки объектов
Cocoa
Cocoa Touch
Среда разработки
XCode
Interface Builder
Слайд 5Что получаем?
Native исполняемый файл
Слайд 6Именование файлов
Заголовочный файл: *.h
Код на Objective-C: *.m
Код на Objective-C++: *.mm
Слайд 7Добавляем ООП к C
Объект связывает данные и операции, которые могут
взаимодействовать с этими данными.
Класс – структура, представляющая тип объекта. Объект
содержит скрытый указатель на свой класс.
Слайд 8Добавляем ООП к C
Сообщение – действие, которое может выполнять объект.
Метод
– код, который выполняется в ответ на сообщение.
Диспетчер методов –
механизм для определения метода, обрабатывающего сообщение.
Слайд 9Программа на Objective C
#import
int main(int argc,
const char *argv[])
{
NSLog(@”Hello, world!”);
return 0;
}
Слайд 10Строки
"string" – обычная строка в C/C++
@"string" – строка-объект NSString
Слайд 11id
Тип данных
Обозначает любой тип объекта, независимо от его класса
nil
Нулевой указатель
Слайд 12BOOL
#define signed char BOOL
#define YES (BOOL)1
#define NO (BOOL)0
Слайд 14Объявляем класс
Файл: Shape.h
@interface Shape : NSObject
@end
Слайд 15Объявляем класс:
добавляем данные
@interface Shape : NSObject
{
float width, height;
}
@end
Слайд 16Видимость данных объекта
@interface Shape : NSObject
{
@private
float width, height;
@protected
// по умолчанию
@package
@public
}
@end
Слайд 17Объявляем класс:
объявляем методы
@interface Shape : NSObject
{
float width, height;
}
+
(Shape*)createSquareShape:
(float)width;
- (float)width;
- (float)height;
- (void)draw;
- (void)setWidth:(float)width
height:(float)height;
@end
Слайд 18Объявление метода
Метод объекта
- (float)width;
- (void)setWidth:(float)width;
- (void)setWidth:(float)width
height:(float)height;
Метод класса
+ (Shape*)createSquareShape:
(float)width;
Слайд 19Специальные методы
(наследуются из NSObject)
alloc – выделение памяти
init –
инициализация объекта (конструктор без параметров)
dealloc – деструктор
Подробнее в
главе об управлении памятью
Слайд 20Реализуем класс
Файл: Shape.m
@implementation Shape
- (float)width
{
return width;
}
- (void)setWidth:(float)theWidth
height:(float)theHeight
{
width = theWidth;
height
= theHeight;
}
// другие методы
@end
Слайд 21Используем класс
Shape *shape =
[Shape createSquareShape:5.0];
[shape draw];
float h = [shape
height];
shape = [[Square alloc] init];
Слайд 22Подробнее о методах
Инфиксная форма записи:
- (void)setValue:(id)object
forKey:(NSString*)key
Имя метода:
setValue:forKey:
Слайд 23Подробнее о методах:
cелектор
Ссылка на имя метода
Имеет тип SEL
Все методы с
одинаковым именем имеют одинаковый селектор
Слайд 24Подробнее о методах:
работа с селекторами
id helper = getTheReceiver();
SEL request
= getTheSelector();
[helper performSelector:request];
Слайд 25Наследование: синтаксис
@interface Circle : Shape
{
float x, y;
}
@end
Слайд 26Наследование: особенности
Множественное наследование не поддерживается
Любой метод можно переопределить
Слайд 27Сравнение с C++
С++
Objective C
this
self
BaseClass::method();
[super method];
Видимость методов:
public, protected, private
Все методы public
Виртуальные
и
невиртуальные методы
Все методы виртуальные
Есть множественное
наследование
Нет множественного
наследования
Слайд 28NSObject
Корневой класс большинства иерархий
Содержит функции управления циклом жизни объекта
Выделение памяти
для объекта (alloc)
Инициализация объекта (init)
Уничтожение объекта (dealloc)
Управление счётчиками ссылок
Другие функции
Слайд 29Размещение в памяти
isa
NSObject
width
height
Shape
x
y
Circle
self
Слайд 30Перекрытие методов
- (void)draw
{
… // свой код
[super draw]; //
вызов базового
… // свой код
}
Слайд 31Свойства
@interface Shape : NSObject
{
int flags;
}
@property(nonatomic, copy) NSString *name;
@property(getter=isComplex)
BOOL complex;
@end
Слайд 32Атрибуты свойств
@property(attributes) Type name;
getter=getterName
setter=setterName
readwrite (default)
readonly
assign (default)
retain
copy
nonatomic
Слайд 33Реализация свойств
@implementation Shape
// автоматическая реализация
@synthesize name; // или name=variableName
// ручная
реализация
- (BOOL)isComplex
{
return flags & SHAPE_COMPLEX;
}
- (void)setComplex:(BOOL)complex
{
flags
= complex ? flags | SHAPE_COMPLEX
: flags & ~SHAPE_COMPLEX;
}
@end
Слайд 34Использование свойств
Shape *shape = …;
// Dot-syntax
BOOL complex = shape.complex;
shape.complex =
YES;
NSString *name = shape.name;
// так тоже можно
complex = [shape isComplex];
name
= [shape name];
Слайд 36Объявление протокола
@protocol Shape
- (void)draw;
@optional
- (void)fill;
@required
- (void)shift:(CGPoint)offset;
@end
Слайд 37Наследование протоколов
@protocol GraphicsPrimitive
@end
@protocol Shape
@end
Слайд 38Принятие протокола
@interface Square
@end
Слайд 39Работа с объектом
только через протокол
id obj = …;
[obj protocolMethod1];
Слайд 40Соответствует ли объект протоколу?
if ([someObject conformsToProtocol:
@protocol(Protocol)]
{
…
}
Слайд 41Реализует ли объект метод?
if ([someObject respondsToSelector:
@selector(someMethod)])
{
[someObject
someMethod];
}
Слайд 42Категории
Добавление методов в существующий класс
Слайд 43Объявление категории
Файл: Shape+Transforms.h
@interface Shape(Transforms)
- (void)offset:(CGPoint)delta;
@end
Слайд 44Реализация категории
Файл: Shape+Transforms.m
#import "Shape+Transforms.h“
@implementation Shape(Transforms)
- (void)offset:(CGPoint)delta
{
CGPoint origin =
self.origin;
origin.x += delta.x;
origin.y += delta.y;
self.origin = origin;
}
@end
Слайд 45Категории и протоколы
@interface Shape(Transforms)
- (void)offset:(CGPoint)delta;
@end
Слайд 47Объявление расширения
@interface Shape
{
}
@end
@interface Shape()
@end
Слайд 48Зачем?
Разделение объявления интерфейса
Public и private части
Компилятор проверяет наличие реализации методов
расширения в секции @implementation
Слайд 50Исключения
@try
{
NSException *exception =
[NSException
exceptionWithName:@"HotTeaException"
reason:@"The tea is too hot"
userInfo: nil];
@throw exception;
}
@catch(NSException *e)
{
@throw;
}
@finally
{
}
Слайд 51Исключения
В качестве исключения можно использовать любой Objective-C объект
Часто используется NSException
или его наследники
Слайд 53for … in
for(Type variable in expression)
{
statements
}
for(existingVariable in expression)
{
statements
}
Слайд 54Fast Enumeration
Позволяет обходить коллекции, реализующие протокол NSFastEnumeration
Модификация коллекции в процессе
обхода не допускается
Слайд 56Базовые библиотеки
Foundation framework
Строки, коллекции, файлы, потоки…
AppKit (Cocoa)
Пользовательский интерфейс Mac OS
UIKit
(Cocoa Touch)
Пользовательский инерфейс iOS
Слайд 58NSObject
- (id)alloc
выделение памяти под объект
- (id)init
инициализация объекта
- (id)dealloc
разрушение объекта
dealloc нельзя
вызывать напрямую
Слайд 59NSObject
Используется подсчёт ссылок на объект
- (id)retain
увеличить число ссылок
- (void)release
освободить ссылку
-
(id)autorelease
поместить объект в autorelease pool
Слайд 60Основное правило управления памятью
Освобождать нужно только те объекты, которыми вы
владеете
Вы становитесь владельцем объекта, если создаёте его при помощи методов
с префиксами alloc, new, copy, mutableCopy, или посылаете объекту сообщение retain.
Нужно использовать release или autorelease, чтобы «отказаться» от владения.
Слайд 61Пример
NSArray *array = [[NSArray alloc] init];
// Вы владеете объектом array
//
число ссылок на array = 1
NSArrya *arrayCopy = [array copy];
//
Вы владеете объектом arrayCopy
// число ссылок на arrayCopy = 1
[array release];
// Число ссылок на array = 0,
// объект уничтожается.
Слайд 62Ещё пример
- (NSArray*)findObjects
{
NSMutableArray *objects =
[[[NSMutableArray alloc] init]
autorelease];
// Владение объектом передаётся
// в текущий NSAutoreleasePool через
autorelease
…
return objects;
}
Слайд 63NSAutoreleasePool
Содержит объекты, которым было послано сообщение autorelease.
Отправляет сообщение release всем
добавленным объектам при вызове drain.
При создании ассоциируется с потоком
(помещается в
стек из NSAutoreleasePool)
Автоматически создаётся только в главном потоке.
Слайд 64NSAutoreleasePool: Использование
// запуск нового потока
[self performSelectorInBackground:@selector(doTask)
withObject:nil];
// Метод, запускающийся
в отдельном потоке
- (void)doTask
{
// если не создать NSAutoreleasePool
// будут утечки памяти для объектов,
// у которых вызван autorelease
NSAutoreleasePool *pool =
[[NSAutoreleasePool alloc] init];
…
[pool drain];
}
Слайд 65NSAutoreleasePool: Использование
Нужно избегать накопления объектов при выполнении длительных операций
for(int i
= 0; i < 1000000; i++)
{
NSAutoreleasePool *pool =
[[NSAutoreleasePool alloc] init];
// интенсивное использование autorelease
…
[pool drain];
}
Слайд 67@synchronized
Блокирует исполнение участка кода для выполнения только одним потоком.
Допускается повторный
захват объекта блокировки потоком.
@synchronized(lockObject)
{
// protected code
}
Слайд 69Блоки
Анонимный код (функция), который:
Имеет типизированные аргументы
Имеет тип возврата
Может захватывать состояние
из лексической области, где он определён
Слайд 71Целые типы
NSInteger
NSUInteger
32-битные целые в 32-битных приложениях
64-битные целые в 64-битных приложениях
Слайд 72NSString
NSMutableString
Работа со строками
Поддержка Unicode
NSString – неизменяемая строка
NSMutableString – изменяемая строка
NSMutableString
– наследник NSString
Слайд 73NSString:
часто используемые методы
+ (NSString*)stringWithFormat:(NSString*)format, …;
NSArray *obj = [NSArray arrayWithObjects:@”str1”,
@”str2”,
nil];
[NSString stringWithFormat:@”obj=%@, num=%d”, obj, num];
- (BOOL)isEqualToString:(NSString*)aString;
NSString *param = …;
BOOL equal = [@”string” isEqualToString:param];
- (NSUInteger)length;
Слайд 74NSArray
NSMutableArray
Упорядоченная коллекция объектов
NSArray – неизменяемая коллекция
NSMutableArray – изменяемая
коллекция
Примитивные типы нужно оборачивать при помощи NSNumber или NSValue.
Для хранения
nil – [NSNull null]
NSMutableArray – наследник NSArray
Слайд 75NSArray:
часто используемые методы
+ (NSArray*)arrayWithObjects:(id)firstObj, …
array = [NSArray arrayWithObjects:
@”123”,
[NSNumber numberWithInt:123],
[NSNull null],
nil];
(id)objectAtIndex:(NSUInteger)index
- (NSUInteger)count
Слайд 76NSDictionary
NSMutableDictionary
Ассоциация значений на ключи
Ключи должны быть уникальны
Не допускается использование nil
(но можно использовать [NSNull null]
NSMutableDictionary – наследник NSDictionary
Слайд 77NSDictionary:
часто используемые методы
+ (NSDictionary*)dictionaryWithObjectsAndKeys:(id)firstObj, …
d = [NSDictionary dictionaryWithObjectsAndKeys:
@”123”, // ключ 1
[NSNumber
numberWithInt:123],
[NSNumber numberWithBool:YES], // ключ 2
@”YES”,
nil];
- (id)valueForKey:(NSString *)key
- (NSUInteger)count
Слайд 79KVC = Key-Value Coding
Механизм косвенного доступа к свойствам объекта, через
строки, идентифицирующие свойства
[obj valueForKey:@”text”];
[obj valueForKeyPath:@”view.text”];
[obj setValue:@”Hi” forKey:@”text”];
[obj setValue:@”Hi”
forKeyPath:@”view.text”];
Слайд 80KVO = Key-Value Observing
Механизм, позволяющий объектам узнавать об изменении свойств
других объектов
[obj addObserver:self
forKeyPath:@”view.text”
options:0
context:NULL];
- (void)observeValueForKeyPath:(NSString*)keyPath
ofObject:(id)object
change:(NSDictionary*)change
context:(void *)context
{
}