SEL выполняет выбор и аргументы
Кажется, должен быть простой способ вызвать селектор с некоторыми аргументами, когда все, что у вас есть, - это объект SEL. Я не могу найти правильный синтаксис.
-(MyClass*) init: (SEL)sel owner:(NSObject*) parent
{
int i =10;
[parent performSelector:sel:i ];
}
Ответы
Ответ 1
Взгляните на документацию NSObject
. В этом случае:
[parent performSelector:sel withObject:[NSNumber numberWithInt:i]];
(обратите внимание, что этот метод фактически указан в документации NSObject
). Поскольку -[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
от этого вызова, и вы должны вернуть себя из метода инициализатора. Во всех случаях ваши методы инициализации Objective-C должны выглядеть так:
-(id)myInitMethod {
self = [super init];
if(self != nil) {
//perform initialization of self
}
return self;
}
Ваш метод (если это метод init) будет выглядеть так:
-(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:owner:
.
Ответ 2
то, что сказал Барри Уорк, замечательно.. я только что изменил обсуждение для ленивых программистов
-(void)myMethodWith:(int)number andBOOL:(BOOL) someBool andStr:(NSString *)str{
NSLog(@"%d %d %@",number,someBool,str);
}
-(void) testMethod{
SEL sel = @selector(myMethodWith:andBOOL:andStr:);
int i = 10;
BOOL bol = YES;
NSString *str = @"hey baby !";
NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:sel]];
[inv setSelector:sel];
[inv setTarget:self];
[inv setArgument:&i atIndex:2]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
[inv setArgument:&bol atIndex:3];
[inv setArgument:&str atIndex:4];
[inv invoke];
}
Ответ 3
Вы хотите использовать performSelector:withObject:
Сложная часть преобразует int
в NSObject. Вы не можете использовать performSelector
с сообщениями, которые принимают параметры int
, вместо этого он должен принимать id
.
Из Ссылка на протокол NSObject:
aSelector должен идентифицировать метод, который принимает один аргумент идентификатора типа. Для методов с другими типами аргументов и возвращаемыми значениями используйте NSInvocation.
Как только это изменение будет сделано, вы можете сделать:
id arg = [NSNumber numberWithInt:10];
[parent performSelector:sel withObject:arg];
Ответ 4
Для методов, которые принимают один или два объекта типа id
в качестве аргументов, вы можете использовать:
[parent performSelector:sel withObject:argument1];
или
[parent performSelector:sel withObject:argument1 withObject:argument2];
Для методов с другими типами аргументов создайте NSInvocation
, который может инкапсулировать произвольные вызовы методов.
Ответ 5
Вы можете использовать:
- (id)performSelector:(SEL)aSelector withObject:(id)anObject
- (id)performSelector:(SEL)aSelector withObject:(id)anObject withObject:(id)anotherObject
Или, если вам нужно использовать более сложный метод, используйте NSInvocation
class