Objective-C Callback方法作为另一个类的参数

时间:2014-02-24 14:43:40

标签: ios objective-c

我正在为iOS 7制作程序,但因为我在几个视图中使用了几乎相同的方法,所以我想创建一个覆盖大部分方法的公共类,并使用回调方法进行画龙点睛,这是每个视图分开。我在视图中有以下代码:

// On top of the view .m
#import "Common.h"

// Method which will be called.
-(void)doSomething
{
  NSLog(@"doSomething...");

  [Common target:self method:@selector(callbackMethod)];
}

// Method I want to be called.
+(void)callbackMethod
{
  NSLog(@"Should come here...");
}

Common.h如下:

#import <Foundation/Foundation.h>

@interface Common : NSObject

+(void)target:(Class)object method:(SEL)selector;

@end

Common.m如下:

+(void)target:(Class)object method:(SEL)selector
{
    NSLog(@"target...");
    if ([object respondsToSelector:@selector(selector)])
    {
        [object performSelector:@selector(selector)];
    } else {
        NSLog(@"%@", object);
    }
}

在运行时,它只输出: 做一点事..., 目标..., &lt; ParentViewController:0x8d24bb0&gt;

这里的问题是调用回调方法。程序将到达Common.m中的方法,但无法从父级调用该方法。

1 个答案:

答案 0 :(得分:2)

问题在于

@selector(selector)

搜索名为“selector”的方法。 @selector()检索名称包含在括号内的选择器。

你想要的是使用传入的选择器,而不是检索不同的选择器。你可以像传入任何其他变量一样将它传递给选择器方法:

+(void)target:(Class)object method:(SEL)selector
{
    NSLog(@"target...");
    if ([object respondsToSelector:selector])
    {
        [object performSelector:selector];
    } else {
        NSLog(@"%@", object);
    }
}

使用ARC时,这会引发警告,因为ARC系统无法分辨出发生了什么。要通知编译器您故意调用performSelector:并且确定没有泄漏,您可以关闭这一行的警告。 只有在您完全确定没有泄漏时才这样做。

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
            [object performSelector:selector];
#pragma clang diagnostic pop

最后,让我们看一下您的选择callbackMethod

+(void)callbackMethod
{
  NSLog(@"Should come here...");
}

这是一个类方法,而不是实例方法,因此您的类的实例不响应选择器,而本身也是如此。将它从类方法更改为实例方法(通过将'+'替换为' - ')将解决此问题:

-(void)callbackMethod
{
  NSLog(@"Should come here...");
}