Кажется, что должен быть простой способ назвать селектор с некоторыми аргументами, когда все, что Вы имеете, является объектом SEL. Я, может казаться, не нахожу правильный синтаксис.
-(MyClass*) init: (SEL)sel owner:(NSObject*) parent
{
int i =10;
[parent performSelector:sel:i ];
}
Взгляните на документацию NSObject
. В этом случае:
[parent performSelector:sel withObject:[NSNumber numberWithInt:i]];
(обратите внимание, что этот метод фактически указан в документации NSObject
protocol ). Поскольку - [NSObject performSelector: withObject:]
требует аргумента объекта, вам нужно будет написать оболочку в родительском классе, например
-(void)myMethodForNumber:(NSNumber*)number {
[self myMethod:[number intValue]];
}
, чтобы распаковать NSNumber
.
Если вы действительно хотите вызвать метод, который принимает аргументы, не являющиеся объектами, напрямую (например, у вас нет контроля над источником вызываемого объекта и вы не хотите добавлять категорию), вы можете использовать NSInvocation
:
NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[parent methodSignatureForSelector:sel]];
[inv setSelector:sel];
[inv setTarget:parent];
[inv setArgument:&i atIndex:2]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
[inv invoke];
Кстати, ваш метод похож на метод init
, но не соответствует правильному шаблону инициализатора для Objective-C. Вам нужно вызвать инициализатор суперклассов, и вам нужно проверить результат этого вызова nil
, и вы должны вернуть self из метода инициализатора. Во всех случаях ваши методы инициализатора Objective-C должны выглядеть так:
-(id)myInitMethod {
self = [super init];
if(self != nil) {
//perform initialization of self
}
return self;
}
Ваш метод (если это метод инициализации) будет выглядеть так:
-(id) init: (SEL)sel owner:(NSObject*) parent
{
self = [super init];
if(self != nil) {
int i = 10;
NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[parent methodSignatureForSelector:sel]];
[inv setSelector:sel];
[inv setTarget:parent];
[inv setArgument:&i atIndex:2]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
[inv invoke];
}
return self;
}
Чтобы быть более стилистически Objective-C, я бы переименовал инициализатор - (id) initWithSelector: также владелец:
.
Вы можете использовать:
- (id)performSelector:(SEL)aSelector withObject:(id)anObject
- (id)performSelector:(SEL)aSelector withObject:(id)anObject withObject:(id)anotherObject
Или, если вам нужно использовать более сложный метод, используйте NSInvocation
class
Для методы, которые принимают один или два объекта типа id
в качестве аргументов, вы можете использовать:
[parent performSelector:sel withObject:argument1];
или
[parent performSelector:sel withObject:argument1 withObject:argument2];
Для методов с другими типами аргументов создайте NSInvocation
, который может инкапсулировать произвольные вызовы методов.
Вы хотите использовать performSelector: withObject:
Сложная часть - это преобразование int
в NSObject . Вы не можете использовать performSelector
с сообщениями, которые принимают int
params, вместо этого он должен принимать id
.
Из Справочника по протоколу NSObject :
aSelector должен идентифицировать метод, который принимает единственный аргумент типа id. Для методов с другими типами аргументов и возвращаемыми значениями используйте NSInvocation .
После внесения этого изменения вы можете сделать:
id arg = [NSNumber numberWithInt:10];
[parent performSelector:sel withObject:arg];