objective-c - 使用 Objection 时,自定义协议(protocol)的实现因无法识别的选择器而崩溃

标签 objective-c objective-c-runtime

我正在定义一个自定义协议(protocol):

@protocol NGSAuthProvider <NSObject>
- (BOOL)isReady;
- (BOOL)isSessionValid;
- (void)login;
- (void)logout;
- (NSString *)accessToken;
- (BOOL)handleOpenURL:(NSURL *)url;
@end

我想要不同的供应商。所以一个是 Facebook 提供商:

@interface NGSFacebookAuthProvider : NSObject <NGSAuthProvider>
@end

@interface NGSFacebookAuthProvider () <FBSessionDelegate>
@property BOOL ready;
@property(nonatomic, retain) Facebook *facebook;
@property(nonatomic, retain) NSArray *permissions;
@end

@implementation NGSFacebookAuthProvider
//Implementation of fbLogin, fbLogout and the methods in NGSAuthProvider that forward calls to self.facebook
- (NSString *)accessToken
{
  return [self.facebook accessToken];
}

@end

我设置 Objection从我的类绑定(bind)到协议(protocol)。

@interface NGSObjectionModule : ObjectionModule
@end

@implementation NGSObjectionModule

- (void)configure 
{
   self bind:[NGSFacebookAuthProvider class] toProtocol:@protocol(NGSAuthProvider)];
}
@end

我设置了全局注入(inject)器:

@implementation NGSAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  ObjectionModule *module = [[NGSObjectionModule alloc] init];
  ObjectionInjector *injector = [Objection createInjector:module];
  [module release];

  [Objection setGlobalInjector:injector];
}

我在我的 RootViewController 中使用它是这样的:

@interface RootViewController : UITableViewController
@end

@interface RootViewController ()
@property(nonatomic, retain) id<NGSAuthProvider> authProvider;
@end

@implementation RootViewController
- (void)viewDidLoad {
  [super viewDidLoad];
  self.authProvider = [[Objection globalInjector] getObject:@protocol(NGSAuthProvider)];
}

- (void)processConfig {
  NSString *token = [self.authProvider accessToken];
  // use the access token
}
@end

当我运行它时,出现以下错误:

2011-07-26 21:46:10.544 ngs[6133:b603] +[NGSFacebookAuthProvider accessToken]: unrecognized selector sent to class 0x30c7c
2011-07-26 21:46:10.546 ngs[6133:b603] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NGSFacebookAuthProvider accessToken]: unrecognized selector sent to class 0x30c7c'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x00e825a9 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x00fd6313 objc_exception_throw + 44
    2   CoreFoundation                      0x00e8417b +[NSObject(NSObject) doesNotRecognizeSelector:] + 187
    3   CoreFoundation                      0x00df3966 ___forwarding___ + 966
    4   CoreFoundation                      0x00df3522 _CF_forwarding_prep_0 + 50
    5   ngs                                 0x0000324b -[RootViewController processConfig] + 731
    6   ngs                                 0x000041a2 __33-[RootViewController viewDidLoad]_block_invoke_0 + 50

所以我的类实现了协议(protocol)。成功分配给id<NGSAuthProvider> .我尝试构建 [[NGSFacebookAuthProvider alloc] init]明确地而不是使用 Objection它仍然崩溃。

我尝试使用 objc/runtime.h 遍历选择器查看那里有哪些选择器的方法,但它唯一找到的是 initialize :

- (void)logSelectors:(id)obj
{
    int i=0;
    unsigned int mc = 0;
    Method * mlist = class_copyMethodList(object_getClass([obj class]), &mc);
    NSLog(@"%d methods", mc);
    for(i=0;i<mc;i++)
        NSLog(@"Method no #%d: %s", i, sel_getName(method_getName(mlist[i])));

    free(mlist);
}

这必须是我所缺少的简单内容。我使用 Cocoa 定义的协议(protocol),没有这个问题。我已经为 UIViewController 定义了自定义协议(protocol)没有问题的基于代表。

我很困惑为什么 Obj-C 运行时找不到我的方法!如果我改变 id<NGSAuthProvider>NGSFacebookAuthProvider并显式构建它然后一切正常。

解决方案:

问题是我误解了如何绑定(bind)到协议(protocol)。一种可行的方法是:

@implementation NGSObjectionModule

- (void)configure 
{
  [self bind:[[[NGSFacebookAuthProvider alloc] init] autorelease] toProtocol:@protocol(NGSAuthProvider)];
}
@end

我想做的是将一个类绑定(bind)到一个协议(protocol),但 Objection 可能不知道要调用的初始化程序?

最佳答案

问题是您正在尝试使用静态类方法(表示是因为您有一个 +),而不是在您的对象实例上运行的方法(这就是您编写的,带有-)

关于objective-c - 使用 Objection 时,自定义协议(protocol)的实现因无法识别的选择器而崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6838685/

相关文章:

ios - 点击 UITableViewCell 的自定义按钮?

objective-c - NSCopying 和 copyWithZone : - should they return [self retain] or something else?

ios - NSString decimalValue 方法

cocoa - Cocoa 中的 @dynamic 属性访问器

iphone - 在 arc 下使用 objc_getClassList

objective-c - 如何使用 Cocoa 创建一个有阴影且没有奇怪标题栏的模态表?

ios - 从代码中获取 xcconfig 配置文件名

ios - 添加对象到 NSMutableArray

ios - 什么是 objc_selector 实现?

ios - objc_getAssociatedObject 返回 null