阻止作为块的参数

时间:2015-08-21 17:19:37

标签: ios objective-c objective-c-blocks

我在Objective-C中实现了一个库,它试图依赖块并减少委托调用的使用。

此lib将在需要时提示应用程序提供用户凭据,应用程序应为其提供调用块。由于库将检查凭据,因此我希望应用程序提供另一个块以获取通知凭据是否正确。通过这个我可以保持UI显示HUD,直到我得到回复。

我为主应用程序提供了一个协议来实现:

@protocol LibProtocol <NSObject>
- (void) needsUserCredentials:(void (^)(NSString *username,
                                    NSString *password,
                                    void (^authResult)(Result result, NSError *error) ))gotCredentials;
@end

应用程序应按如下方式实施协议:

- (void) needsUserCredentials:(void (^)(NSString *username,
                                    NSString *password,
                                    void (^)(Result result, NSError *error) ))gotCredentials{
    // get credentials from UI
    gotCredentials(@"username",@"password", ^(Result result, NSError *error){
    if(result == ResultAuthorized) NSLog(@"ResultAuthorized");
    else NSLog(@"ResultDenied"); 
});

}

在图书馆,方法使用如下:

[self.delegate needsUserCredentials:^(NSString *username,
                                      NSString *password,
                                      void (^)(Result result, NSError *error)) {
    if([authorizeUser:username password:password]) authResult(AuthResultAuthorized)
    else authResult(AuthResultDenied)    
})];

这样我只需要一个委托调用,进一步的通信就是使用块。

问题是我无法获得authResult块的正确语法,该块在gotCredentials中作为参数传递。我尝试了很多组合,但大部分时间我都收到了Xcode的警告,当我能提供无错误的语法时,它会在simulador / device上运行时崩溃。

有人知道我应该用于authResult块的语法吗?

提前感谢任何暗示!

1 个答案:

答案 0 :(得分:4)

使用函数指针和块时,使用typedef来简化语法并使代码更具可读性通常是个好主意。

例如:

typedef void (^UserResponseBlock)(Result result, NSError* error);

typedef void (^UserRequestBlock)(NSString* username, 
                                 NSString* password, 
                                 UserResponseBlock authResult);

您现在有两种类型,UserResponseBlockUserRequestBlock可以像任何其他类型一样使用:

- (void)needsUserCredentials:(UserRequestBlock)gotCredentials
{
    gotCredentials(@"username", @"password", ^(Result result, NSError* error) {
        if (result == ResultAuthorized)
        {
            NSLog(@"Result Authorized");
        }
        else
        {
            NSLog(@"Result Denied");
        }
    });
}