NSInvocation简介
NSInvocation 继承于 NSObject 与 performSelector: withObject:方法类似,可以直接调用对象消息的方法。
NSInvocation 与 performSelector: withObject: 的区别在于: performSelector: withObject: 具有一定的局限性,当调用某对象消息需要传递2个以上的参数时,performSelector: withObject: 需要做相当麻烦的处理,才能实现。
而 NSInvocation 很方便,不限制参数。
NSInvocation的使用Demo
直接上代码:
类ABC有一个私有方法:
- (NSInteger)additionWithParaA:(NSInteger) a
ParaB:(NSInteger) b
ParaC:(NSInteger) c
{
return a + b + c;
}
其他类中想要调用类ABC中的方法就可以使用NSInvocation
//1. 初始化 invocation
ABC *myClass = [[ABC alloc] init];
SEL seletor = NSSelectorFromString(@"additionWithParaA:ParaB:ParaC:");
NSMethodSignature * method = [[myClass class]
instanceMethodSignatureForSelector: seletor];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:method];
// 2.设置 target 、 selector 和 其需要的参数
[invocation setTarget:myClass];
[invocation setSelector:seletor];
NSInteger a = 1;
NSInteger b = 2;
NSInteger c = 3;
// 此处 index从2开始,0与1 被target 和 selector 占用 并且argument 传的是地址
[invocation setArgument:&a atIndex:2];
[invocation setArgument:&b atIndex:3];
[invocation setArgument:&c atIndex:4];
// 3. 调用
[invocation invoke];
// 4. 如果需要设置返回值,或者需要接收返回值时
// 获取返回值
NSInteger result2 = nil;
[invocation getReturnValue:&result2];
// 设置返回值
NSInteger result = 100;
[invocation setReturnValue:&result];
NSInvocation的使用
我们都知道UISearchBar中的placeholder属性默认是居中显示的。
现有一需求,需要将placeholder居左显示,但是苹果并没有提供设置方法。
建一类 继承自 UISearchBar 并实现
- (instancetype)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame]))
{
self.hasCentredPlaceholder = YES;
}
return self;
}
- (void)setHasCentredPlaceholder:(BOOL)hasCentredPlaceholder
{
_hasCentredPlaceholder = hasCentredPlaceholder;
SEL centerSelector = NSSelectorFromString([NSString stringWithFormat:@"%@%@", @"setCenter", @"Placeholder:"]);
if ([self respondsToSelector:centerSelector])
{
NSMethodSignature *signature = [[UISearchBar class] instanceMethodSignatureForSelector:centerSelector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:self];
[invocation setSelector:centerSelector];
[invocation setArgument:&_hasCentredPlaceholder atIndex:2];
[invocation invoke];
}
}