iOS如何使用块内的委托方法
我正在使用AFNetworking来处理我的应用程序的请求/响应任务。在我的一个处理程序类中,当HTTP请求成功时,我必须执行委托方法调用以更新UI(请注意,我特别不想使用NSNotificationCenter)。但是,编译器抱怨代理没有被声明。我必须以某种方式继续忽略它,并犯同样的错误。这里是我的问题的代码的简化版本:iOS如何使用块内的委托方法
//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
{
//
}
你是任何方法之外。这就像你试图做到这一点:
//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
谢谢,这对我来说就像一个魅力。 – sercancici 2014-09-02 11:37:54
你正试图从访问类的范围之外的委托变量。试试这个:
//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];
}
我不确定这是因为我第一次提出成功和失败的声明,以提高代码的可读性。另外,它们不在MYHandler实现之外,只在'doSomething'方法声明之外。有没有其他的方式可以让我们访问自我的范围? – sercancici 2014-09-01 14:39:04
添加了一些例子的答案。希望他们帮助。 – grimdox 2014-09-01 15:52:49
你的情况,你叫_delegate
的参数不在范围和不能使用的。为了解决这个问题,你可能想要声明这个参数在范围内的块本身。例如在将块传递给请求方法的方法中声明它。
因为这个过程实际上更常见,所以你在声明块实现之外的块时我可以假设你有一个理由将它移到了外面。如果这是由于某种原因必需的,您可以使用宏编译器#define successBlock ^(AFHTTPRequestOperation...
,它将在编译时为您插入代码。这样做会在您使用该块的地方插入范围。
为什么会发生这种情况,您需要考虑与C/C++函数相同的块,如果您想使用_delegate
,则还需要在其中一个案例中将其作为输入参数插入AFHTTPRequestOperation *operation, id responseObject
旁边。
为什么这个实际上没有显式参数声明是因为编译器已经为你做了这样的事情,但仍然需要该对象在范围内。
有一个误解,它们不在类的实现之外,只在'doSomething'方法声明之外。 – sercancici 2014-09-01 14:42:39
这仍然是相同的,如果一个委托是一个实例参数,它不在该类的静态部分的范围内。例如,如果你创建一个静态方法,如+(void)foo;你再次无法使用你的委托参数在该方法内...... – 2014-09-01 15:52:45
谢谢@Matic。快速课程,他们甚至不教你基本知识。我不知道这堂课的静态部分。我认为,除非我将某些东西标记为静态或类方法,否则它将是动态的并且在实例范围内。你已经为我清除了很多东西。 – sercancici 2014-09-02 11:44:34
我已经试过几乎所有和我不能管理运行到你的错误。 在你的代码中,你的协议是在一个单独的文件中声明的? – 2014-09-01 15:16:44