iOS如何在块内使用委托方法

时间:2014-09-01 14:14:04

标签: ios delegates scope objective-c-blocks

我正在将AFNetworking用于我的应用程序的请求/响应任务。在我的一个处理程序类中,当HTTP请求成功时,我必须执行委托方法的调用以更新UI(请注意,我特别不想使用NSNotificationCenter)。但是,编译器抱怨没有声明委托。我必须以某种方式忽视它并犯同样的错误。这是我有问题的代码的简单版本:

//MYHandler.h
@protocol MYDelegate <NSObject>
-(void) myDelegateMethod;
@end

@interface MYHandler : NSObject
@property (strong, nonatomic) id<MYDelegate> delegate;
@end

//MYHandler.m
@implementation MYHandler
    -(void) doSomething
    {
        //Create and configure request
        AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
        operation.responseSerializer = [AFJSONResponseSerializer serializer];
        [operation setCompletionBlockWithSuccess: successBlock failure:failureBlock];
        [operation start];
    }

    //Success and Failure
    typedef void(^SuccessBlock)(AFHTTPRequestOperation *operation, id responseObject);
    typedef void(^FailureBlock)(AFHTTPRequestOperation *operation, NSError *error);

    SuccessBlock successBlock = ^(AFHTTPRequestOperation *operation, id responseObject) {
        [_delegate myDelegateMethod];
        //^this says _delegate is an undeclared identifier
    };
    FailureBlock failureBlock = ^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"%@", error);
    };
@end

//MyViewController.h
@interface MyViewController : UIViewController <MYDelegate>

@end

//MyViewController.m
-(void) myDelegateMethod
{
    //
}

3 个答案:

答案 0 :(得分:0)

您正尝试从类的范围之外访问委托变量。试试这个:

//MYHandler.m
-(void) doSomething
{
    //Success and Failure
    typedef void(^SuccessBlock)(AFHTTPRequestOperation *operation, id responseObject);
    typedef void(^FailureBlock)(AFHTTPRequestOperation *operation, NSError *error);

    SuccessBlock successBlock = ^(AFHTTPRequestOperation *operation, id responseObject) {
        [_delegate myDelegateMethod];
        //^this says _delegate is an undeclared identifier
    };
    FailureBlock failureBlock = ^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"%@", error);
    };

    //Create and configure request
    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    operation.responseSerializer = [AFJSONResponseSerializer serializer];
    [operation setCompletionBlockWithSuccess: successBlock failure:failureBlock];
    [operation start];
}

答案 1 :(得分:0)

在您的情况下,您调用_delegate的参数不在范围内,根本无法使用。要解决此问题,您可能需要声明此块参数在范围内的块本身。例如,在将块传递给请求方法的方法中声明它。

由于这个过程实际上比你在类实现之外声明块的地方更常见,我可以假设有一个原因你把它移到了外面。如果由于某种原因这是强制性的,您可以使用宏#define successBlock ^(AFHTTPRequestOperation...,它将在编译时为您插入代码。这样做也会插入使用块的范围。

为什么会发生这种情况,你需要将块视为与C / C ++函数相同,如果你想使用_delegate,你还需要将它作为输入参数插入AFHTTPRequestOperation *operation, id responseObject旁边在你的一个案件中。

为什么没有显式的参数声明实际上这是有效的,因为编译器已经为你做了那样但是,它确实需要该对象在范围内。

答案 2 :(得分:0)

你不在任何方法之内。它就像你试图这样做:

//MYHandler.m
@implementation MYHandler
    -(void) doSomething
    {
        //Create and configure request
        AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
        operation.responseSerializer = [AFJSONResponseSerializer serializer];
        [operation setCompletionBlockWithSuccess: successBlock failure:failureBlock];
        [operation start];
    }

    [_delegate myDelegateMethod];

@end

显然,这不会奏效。

您可以改为创建返回这些块的方法:

@implementation MYHandler

typedef void(^SuccessBlock)(AFHTTPRequestOperation *operation, id responseObject);
typedef void(^FailureBlock)(AFHTTPRequestOperation *operation, NSError *error);

- (void(^)(AFHTTPRequestOperation *operation, id responseObject))success
{
    return ^(AFHTTPRequestOperation *operation, id responseObject) {
        [_delegate myDelegateMethod];
    };
}

- (void(^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
    return ^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"%@", error);
    };
}

-(void) doSomething
{
    SuccessBlock successBlock = [self success];
    FailureBlock failureBlock = [self failure];
    //Create and configure request
    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    operation.responseSerializer = [AFJSONResponseSerializer serializer];
    [operation setCompletionBlockWithSuccess: successBlock failure:failureBlock];
    [operation start];
}

@end