Книга начинается с того, что класс в Objective C - это объект, который в свою очередь является инстансом метакласса.
Где-то я такое слышал. Давайте разбираться.
Описание находится здесь:
www.cocoawithlove.com/2010/01/what-is-meta-class-in-objective-c.html
а перевод здесь:
https://habr.com/ru/post/207786/
Надо бы конечно это всё проверить, но у меня нет мака 😊 Пока качается хакинтош (
Где-то я такое слышал. Давайте разбираться.
Описание находится здесь:
www.cocoawithlove.com/2010/01/what-is-meta-class-in-objective-c.html
а перевод здесь:
https://habr.com/ru/post/207786/
Надо бы конечно это всё проверить, но у меня нет мака 😊 Пока качается хакинтош (
vagrant init https://vagrant-osx.nyc3.digitaloceanspaces.com/osx-sierra-0.3.1.box
), читаем дальше...Ожидания относительно того, что в Objective C метаклассы похожм на те, что я видел в Python, не оправдались, по этому можно сказать, что моё "где-то сслышал" здесь совсем не применимо.
Понравилось базовое определение объекта:
Пока мне кажется что это очень гибко, когда любую структуру можно превратить в объект простым указателем на класс и после этого в рантайме добавить методы.
Наверно будет грубо сравнивать это с подходом в GO, но тем не менее, на мой взгляд, тут есть некоторые сходства, хоть в го и нельзясоздавать классы в рантайме.
Понравилось базовое определение объекта:
typedef struct objc_object {
Class isa;
} *id;
Пока мне кажется что это очень гибко, когда любую структуру можно превратить в объект простым указателем на класс и после этого в рантайме добавить методы.
Наверно будет грубо сравнивать это с подходом в GO, но тем не менее, на мой взгляд, тут есть некоторые сходства, хоть в го и нельзясоздавать классы в рантайме.
Префикс
Итак, в Apple сделали API для MacOS, который называется Cocoa, который состоит из фреймворков Foundation Kit, Application Kit и Core Data.
Objective-C и Swift используются для создания приложений в Cocoa окружении. Кроме этих двух языков, можно использовать и другие, например Python, но не напрямую, а через дополнительные воркераунды и тулинги.
Основная часть Cocoa, а именно, App Kit и Foundation Kit - это продолжение фреймворков NeXTSTEP и OpenStep, которые разрабатывались для платформы NeXT, которую Apple купила в 1996м году.
Отсюда и префикс
NS
используется почти для всех системных объектов. Это связано с тем, что... ох, это оказалась длинная история.Итак, в Apple сделали API для MacOS, который называется Cocoa, который состоит из фреймворков Foundation Kit, Application Kit и Core Data.
Objective-C и Swift используются для создания приложений в Cocoa окружении. Кроме этих двух языков, можно использовать и другие, например Python, но не напрямую, а через дополнительные воркераунды и тулинги.
Основная часть Cocoa, а именно, App Kit и Foundation Kit - это продолжение фреймворков NeXTSTEP и OpenStep, которые разрабатывались для платформы NeXT, которую Apple купила в 1996м году.
Отсюда и префикс
NS
.Еще интересная особенность: в языке есть одновременно nil и Nil.
nil - эквивалент NULL в качестве указателя на объект
Nil - эквивалент nil в качестве указателя на класс (на инстанс метакласса)
Nil и nil - НЕ взаимозаменяемы!
nil - эквивалент NULL в качестве указателя на объект
Nil - эквивалент nil в качестве указателя на класс (на инстанс метакласса)
Nil и nil - НЕ взаимозаменяемы!
В Objective C методы моут быть только публичными. Обходной путь - написать реализацию, но не упомянуть в интерфейсе. А статических аттрибутов нет совсем.
В Objective C нет перегрузки параметров в зависимости от типа :-( Обходной путь: называть иначе эти самые параметры, например:
y_int и y_float - это разные лейблы. То есть перегрузка как-бы есть и основана на названиях лейблов, а не на типах.
...
- (int) g:(int) x y_int:(int) y;
- (int) g:(int) x y_float:(float) y;
...
y_int и y_float - это разные лейблы. То есть перегрузка как-бы есть и основана на названиях лейблов, а не на типах.
@selector - это новый тип, который является указателем на метод и является типом SEL.
В простом случае, вызов метода не совсем вызов, а отправка сообщения объекту, которая выглядит вот так:
Объекту
Получить селектор можно двумя способами:
Разница в том, что первый способ работает на стадии компиляции, а второй в рантайме.
Интересно, что этот второй "рантаймовый" вариант, для создания селектора передаёт aSelectorName в функцию sel_registerName в виде строки. В свою очередь, sel_registerName работает как обычная С-функция:
Вот еще интересная особенность.
Если у вас есть ДВА РАЗНЫХ объекта с одинаковым именем метода, то для его вызова будет использоваться идин и тот же селектор.
В общем случае, селектор - это обычная C-строка, которая сделана так, чтобы она не была совместима со строковыми типами и эмулирует несуществующий объект
Итого, можно вызывать метод как обычную функцию без всяких отправок сообщений:
Материалы, которые помогли разобраться:
- https://habr.com/ru/post/250955/
В простом случае, вызов метода не совсем вызов, а отправка сообщения объекту, которая выглядит вот так:
[myObject someMethod];
Объекту
myObject
отправляется сообщение someMethod
, однако эта конструкция будет преобразована компилятором в вызов функции с помощью того самого селектора:objc_msgSend(myObject, @selector(someMethod));
Получить селектор можно двумя способами:
SEL aSelector = @selector(methodName);
SEL aSelector = NSSelectorFromString(@"methodName");
Разница в том, что первый способ работает на стадии компиляции, а второй в рантайме.
Интересно, что этот второй "рантаймовый" вариант, для создания селектора передаёт aSelectorName в функцию sel_registerName в виде строки. В свою очередь, sel_registerName работает как обычная С-функция:
SEL sel_registerName ( const char *str );
Вот еще интересная особенность.
Если у вас есть ДВА РАЗНЫХ объекта с одинаковым именем метода, то для его вызова будет использоваться идин и тот же селектор.
В общем случае, селектор - это обычная C-строка, которая сделана так, чтобы она не была совместима со строковыми типами и эмулирует несуществующий объект
objc_selector
.Итого, можно вызывать метод как обычную функцию без всяких отправок сообщений:
SEL mySelector = sel_registerName("myMethod");
objc_msgSend(myObj, mySelector);
Материалы, которые помогли разобраться:
- https://habr.com/ru/post/250955/
В продолжении, давайте вызовем метод исключительно средствами языка C.
Для начала опишем класс:
Определим селектор:
Инстанцируем объект:
Как вызов метода выглядит в стиле языка C:
Как вызов метода выглядит в стиле языка Objective C:
Материалы:
- https://habr.com/ru/post/250977/
Для начала опишем класс:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface TestClass : NSObject
@end
@implementation TestClass
+ (void)someClassMethod {
NSLog(@"Hello from some class method!");
}
- (void)someInstanceMethod {
NSLog(@"Hello from some instance method!");
}
@end
Определим селектор:
typedef void (*MyMethodType)(id, SEL);
Инстанцируем объект:
TestClass * myObj = [[TestClass alloc] init];
Как вызов метода выглядит в стиле языка C:
Class myObjClassObject = object_getClass(myObj);
Class myObjMetaclassObject = object_getClass(myObjClassObject);
MyMethodType instanceMethod = class_getMethodImplementation(myObjClassObject, @selector(someInstanceMethod));
MyMethodType classMethod = class_getMethodImplementation(myObjMetaclassObject, @selector(someClassMethod));
instanceMethod(myObj, @selector(someInstanceMethod));
classMethod(myObjClassObject, @selector(someClassMethod));
Как вызов метода выглядит в стиле языка Objective C:
[TestClass someClassMethod];
[myObj someInstanceMethod];
Материалы:
- https://habr.com/ru/post/250977/
NSObject category that allows you to easily map your objects to JSON and parse it back:
https://github.com/aperechnev/APJSONMapping
https://github.com/aperechnev/APJSONMapping
Протоколы
Используются для
- обхода отсутствия множественного наследования
- обязать класс реализовать методы
Описание протокола:
Использование в интерфейсе:
Протоколы бывают формальные (formal) и неформальные (informal).
Используются для
- обхода отсутствия множественного наследования
- обязать класс реализовать методы
Описание протокола:
@protocol example
- (void) shouldBe;
@optional
- (void) canBeSkipped;
@required
- (NSInteger) shouldBeAlso;
@end
Использование в интерфейсе:
@interface MyObj: NSObject <example>
@end
Протоколы бывают формальные (formal) и неформальные (informal).
Есть такая интересная возможность в языке, как "категория", которая позволяет добавлять методы в класс без наследования.
Одной из таких категорий является
https://stackoverflow.com/questions/2183396/categories-vs-informal-protocols
Одной из таких категорий является
informal protocol
, только это категория объекта NSObject.https://stackoverflow.com/questions/2183396/categories-vs-informal-protocols
Категории
Огромный класс можно разбить на категории. Это такой удобный способ создания God-objects. Для чего это нужно:
- категории можно компилировать независимо
- методы можно разделить на логические группы
- расширение существующих классов, не имея исходников
Хорошая статья с подробным расскажи о категориях:
https://adobkin.com/2012/08/11/katieghorii-v-objective-c/
Огромный класс можно разбить на категории. Это такой удобный способ создания God-objects. Для чего это нужно:
- категории можно компилировать независимо
- методы можно разделить на логические группы
- расширение существующих классов, не имея исходников
Хорошая статья с подробным расскажи о категориях:
https://adobkin.com/2012/08/11/katieghorii-v-objective-c/