Objective C разрешает класс к [1 111] полностью замена другой класс в рамках приложения. Класс замены, как говорят, "изображает из себя" целевой класс. Все сообщения, отправленные в целевой класс, тогда вместо этого получены классом изложения. Существуют некоторые ограничения, на которых могут позировать классы:
Изложение, так же к категориям, позволяет глобально увеличивающиеся существующие классы . Изложение разрешает две функции, отсутствующие в категориях:
пример:
@interface CustomNSApplication : NSApplication
@end
@implementation CustomNSApplication
- (void) setMainMenu: (NSMenu*) menu
{
// do something with menu
}
@end
class_poseAs ([CustomNSApplication class], [NSApplication class]);
Это прерывает каждый вызов setMainMenu к NSApplication.
В основном, во времени выполнения можно выгрузить одну реализацию метода с другим.
Один умный вариант использования для ленивой загрузки совместно используемого ресурса: обычно Вы реализовывали бы sharedFoo
метод путем получения блокировки, создания foo
в случае необходимости, получения ее адреса, выпуска блокировки, затем возврата foo
. Это гарантирует, что эти foo
только создается однажды, но каждый последующий доступ напрасно тратит время с блокировкой, которая больше не необходима.
С методом swizzling, можно сделать, то же как прежде, кроме однажды эти foo
было создано, используйте swizzling для выгрузки начального внедрения sharedFoo
со вторым, которое не делает никаких проверок и просто возвращается foo
, что мы теперь знаем, был создан!
, Конечно, метод swizzling может получить Вас в проблему, и могут быть ситуации, где вышеупомянутым примером является плохая идея, но эй... вот почему это скрытое функция.
Объектная Передача/Метод, отсутствующая
, Когда объект отправляется сообщение, для которого это не имеет никакого метода, система во время выполнения дает ему другой шанс обработать вызов перед отказом. Если поддержка объектов - вперед:: метод, время выполнения называет этот метод, передавая его информация о необработанном вызове. Возвращаемое значение от переадресованного вызова распространено назад исходной вызывающей стороне метода.
-(retval_t)forward:(SEL)sel :(arglist_t)args {
if ([myDelegate respondsTo:sel])
return [myDelegate performv:sel :args]
else
return [super forward:sel :args];
}
Содержание от Ссылка Кармана Objective C
Это очень мощно и используется в большой степени в сообществе Ruby для различного DSLs и направляющих, и т.д. Порожденных в Smalltalk, который влиял и на Objective C и на Ruby.
Должен переопределить все поведения объекта? Можно на самом деле изменить класс активного объекта с одной строкой кода:
obj->isa = [NewClass class];
Это только изменяет класс, который получает вызовы метода того объекта; это не изменяет расположение объекта в памяти. Таким образом это только действительно полезно, когда у Вас есть ряд классов с тем же ivars (или один с подмножеством других), и Вы хотите переключиться между ними.
Одна часть кода я записал использование это для ленивой загрузки: это выделяет объект класса A
, заливки пара критического ivars (в этом случае, главным образом рекордное число) и переключатели isa
указатель для указания на LazyA
. Когда любой метод кроме очень маленького набора как release
и retain
назван, LazyA
загрузки все данные из диска, заканчивают заполнять ivars, переключаются isa
указатель назад на A
, и переводит вызов к реальному классу.
#include <Foundation/Debug.h>
Партии инструментов для попытки разыскать утечки памяти, преждевременный deallocs, и больше в том заголовочном файле.
Категории
Используя Категории, можно добавить методы к встроенным классам без разделения на подклассы. Полная ссылка.
Хорошо добавить удобные методы для наиболее часто используемых классов, таких как NSString или NSData.
Ссылка Времени выполнения Objective C
легко забыть, что синтаксический сахар Objective C преобразовывается в нормальные вызовы функции C, которые являются Объектным-C Временем выполнения. Вероятно, что Вы никогда не должны будете на самом деле копаться в и использовать что-либо во времени выполнения. Именно поэтому я считал бы это 'скрытой функцией'.
Позволяют мне дать способ, которым можно было бы использовать систему во время выполнения.
Скажем, что кто-то разрабатывает внешний API платформы, который будет использоваться третьими лицами. И это, кто-то разрабатывает класс в платформе, которая абстрактно представляет пакет данных, мы назовем их MLAbstractDataPacket
. Теперь это до приложения, кто связывается в платформе, чтобы разделить на подклассы MLAbstractDataPacket
и определить пакеты данных подкласса. Каждый подкласс должен переопределить метод +(BOOL)isMyKindOfDataPacket:(NSData *)data
.
С той информацией в памяти...
было бы хорошо, если бы MLAbstractDataPacket
обеспечил удобный метод, который возвратил корректный инициализированный класс для пакета данных, которые прибывают в форму +(id)initWithDataPacket:(NSData *)data
.
здесь существует только одна проблема. Суперкласс не знает ни об одном из своих подклассов. Таким образом, здесь Вы могли использовать метод во время выполнения objc_getClassList()
наряду с objc_getSuperclass()
для нахождения классов, которые являются подклассами MLAbstractDataPacket. Как только у Вас есть список подклассов, можно тогда попробовать +isMyKindOfDataPacket:
на каждом, пока каждый не найден или не найден.
справочная информация об этом может быть найдена в http://developer.apple.com/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html .
Мне нравится подробный метод, называющий как [myArray writeToFile:myPath atomically:YES]
, где каждый аргумент имеет маркировку.