Выбор метода основан на классе экземпляра объекта, поэтому метод swizzling влияет на все экземпляры того же класса - как вы обнаружили.
Но вы можете изменить классНапример, но вы должны быть осторожны!Вот схема, предположим, что у вас есть класс:
@instance MyPlainObject : NSObject
- (void) doSomething;
@end
Теперь, если для некоторых экземпляров MyPlainObject
вы хотите изменить поведение doSomething
, сначала определите подкласс:
@instance MyFancyObject: MyPlainObject
- (void) doSomething;
@end
Теперь вы можете явно создавать экземпляры MyFancyObject
, но нам нужно взять существующий экземпляр MyPlainObject
и превратить его в MyFancyObject
так мы получаем новое поведение.Для этого мы можем изменить класс, добавив следующее к MyFancyObject
:
static Class myPlainObjectClass;
static Class myFancyObjectClass;
+ (void)initialize
{
myPlainObjectClass = objc_getClass("MyPlainObject");
myFancyObjectClass = objc_getClass("MyFancyObject");
}
+ (void)changeKind:(MyPlainObject *)control fancy:(BOOL)fancy
{
object_setClass(control, fancy ? myFancyObjectClass : myPlainObjectClass);
}
Теперь для любого оригинального экземпляра MyPlainClass
вы можете переключиться, чтобы вести себя как MyFancyClass
и наоборот:
MyPlainClass *mpc = [MyPlainClass new];
...
// masquerade as MyFancyClass
[MyFancyClass changeKind:mpc fancy:YES]
... // mpc behaves as a MyFancyClass
// revert to true nature
[MyFancyClass changeKind:mpc: fancy:NO];
(Некоторые) из предостережений:
Вы можете только сделать это, если подкласс переопределяет или добавляет методы и добавляет static
(класс) переменные.
Вам также нужен подкласс для любого класса, для которого вы хотите изменить поведение, у вас не может быть одного класса, который может изменить поведение многих различных классов.