我將一個塊傳遞給稍後執行此塊的異步方法。我的應用程序崩潰,如果我沒有複製該塊,然後傳遞給someMethod:成功:失敗:將塊傳遞給異步方法
有沒有方法來複制forwardInvocation中的塊:而不是在將它傳遞給someMethod之前將其複製:success:failure: ?
流是的someMethod:成功:故障: - > forwardInvocation: - > HTTPGET:成功:失敗
HTTPGET:成功:失敗:執行的成功或根據HTTP狀態代碼故障塊。
// AppDelegate.h
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) id response;
@property (strong, nonatomic) NSError *error;
@end
// AppDelegate.m
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// The app crashes if the blocks are not copied here!
[[MyController new] someMethod:[^(NSString *response) {
self.response = response;
NSLog(@"response = %@", response);
} copy] failure:[^(NSError *error) {
self.error = error;
} copy]];
return YES;
}
@end
// MyController.h
@protocol MyControllerProtocol <NSObject>
@optional
- (void)someMethod:(void (^)(NSString *response))success
failure:(void (^)(NSError *error))failure;
@end
@interface MyController : NSObject <MyControllerProtocol>
@end
// MyController.m
#import "MyController.h"
#import "HTTPClient.h"
@implementation MyController
- (void)forwardInvocation:(NSInvocation *)invocation {
[invocation retainArguments];
NSUInteger numberOfArguments = [[invocation methodSignature] numberOfArguments];
typedef void(^SuccessBlock)(id object);
typedef void(^FailureBlock)(NSError *error);
__unsafe_unretained SuccessBlock successBlock1;
__unsafe_unretained SuccessBlock failureBlock1;
[invocation getArgument:&successBlock1 atIndex:(numberOfArguments - 2)]; // success block is always the second to last argument (penultimate)
SuccessBlock successBlock = [successBlock1 copy];
[invocation getArgument:&failureBlock1 atIndex:(numberOfArguments - 1)]; // failure block is always the last argument
FailureBlock failureBlock = [failureBlock1 copy];
NSLog(@"successBlock copy = %@", successBlock);
NSLog(@"failureBlock copy = %@", failureBlock);
// Simulates a HTTP request and calls the success block later!
[HTTPClient httpGet:@"somerequest" success:successBlock failure:failureBlock];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
NSMethodSignature *methodSignature = [super methodSignatureForSelector:sel];
return methodSignature;
}
@end
// HTTPClient.h
@interface HTTPClient : NSObject
+ (void)httpGet:(NSString *)path
success:(void (^)(id object))success
failure:(void (^)(NSError *error))failure;
@end
// HTTPClient.m
#import "HTTPClient.h"
@implementation HTTPClient
+ (void)httpGet:(NSString *)path
success:(void (^)(id object))success
failure:(void (^)(NSError *error))failure
{
// Invoke the method.
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(),
^{
success(@"foo");
});
}
@end
完整的源代碼可以在這裏找到:https://github.com/priteshshah1983/BlocksWithNSInvocation
能否請你幫忙嗎?
我們需要看到someMethod:失敗:我沒有看到你的代碼中的任何地方。 – kball
@kball someMethod:成功:失敗:未實現。因此,將調用methodSignatureForSelector:然後forwardInvocation:。 – pshah
@kball我修復了一些錯別字,很抱歉!它應該是一些方法:成功:失敗: – pshah