[英]passing data from async callback
由於某些原因,我需要從異步回調傳遞數據,
如果目標是全局變量,那沒什么大不了的,
但是變量僅在方法中使用,所以我希望可以在方法中使用。
- (void)login
{
dispatch_group_t login_group = dispatch_group_create();
NSString* secureToken = nil;
NSString* loginSeed = nil;
[self getSecureToken:&secureToken group:login_group];
[self getLoginSeed:&loginSeed group:login_group];
dispatch_group_notify(login_group, dispatch_get_main_queue(), ^{
NSLog(@"token: %@", secureToken);
});
}
- (void)getSecureToken:(NSString **)token group:(dispatch_group_t)group
{
dispatch_group_enter(group);
[_manager setResponseSerializer:[AFHTTPResponseSerializer serializer]];
[_manager GET:@"/secure_token" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
//get secure token
NSDictionary* result = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
*token = [result objectForKey:@"SECURE_TOKEN"];
dispatch_group_leave(group);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
dispatch_group_leave(group);
}];
}
如果我這樣做,那么它將打印null
無論如何,我可以從異步回調訪問數據,但不能通過全局變量或委托訪問數據?
因為我只需要這些數據作為登錄方法。
由於您似乎具有JavaScript背景,因此您可能對promises很熟悉。
在Objective-C中,有一些實現諾言的庫。 利用承諾庫的方法可能看起來像這樣:
您的login
將變為異步(不可避免):
- (Promise*)promiseLogin {
return [self promiseSecureToken]
.then(^id(NSString* secureToken){
return [self promiseLoginWithToken:secureToken seed:seed];
}, nil);
}
您的方法promiseSecureToken
可以按以下方式實現:
- (Promise*) promiseSecureToken
{
Promise* promise = [[Promise alloc] init];
[_manager setResponseSerializer:[AFHTTPResponseSerializer serializer]];
[_manager GET:@"/secure_token" parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
//get secure token
NSError* error;
NSDictionary* result =
[NSJSONSerialization JSONObjectWithData:responseObject
options:NSJSONReadingMutableContainers
error:&error];
if (result) {
NSString* token = [result objectForKey:@"SECURE_TOKEN"];
[promise fulfillWithValue:token];
}
else {
[promise rejectWithReason:error];
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[promise rejectWithReason:error];
}];
return promise;
}
您可以這樣使用它:
[self promiseLogin]
.then(^id(id result){
// "result" is whatever promiseLoginWithToken:seed: returns
return something;
},nil)
.then(nil, ^id(NSError*error){
// catch ANY error, no matter where it occurred in the previous tasks:
NSLog(@"ERROR: %@", error);
return nil;
});
有關庫列表和更多有用信息,請在此處查看: https : //softwareengineering.stackexchange.com/questions/184597/success-failure-blocks-vs-completion-block/219929#219929
您可以定義這樣的類變量,並在類中的任何位置使用它:
喜歡:
@interface MyViewController()
{
NSString *token;
}
@end
@implementation MyViewController()
...
否則,您還可以嘗試對getSecureToken方法使用完成塊嗎?
像這樣:
- (void)getSecureToken:(NSString **)token group:(dispatch_group_t)group onComplete:(void(^)(AFHTTPRequestOperation *operation, id responseObject))success onFail:(void(^)(AFHTTPRequestOperation *operation, NSError *error))fail
{
dispatch_group_enter(group);
[_manager setResponseSerializer:[AFHTTPResponseSerializer serializer]];
[_manager GET:@"/secure_token" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
//get secure token
NSDictionary* result = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
*token = [result objectForKey:@"SECURE_TOKEN"];
dispatch_group_leave(group);
// ---------------------------------------------------------
// Check completion block param exists before executing it
// ---------------------------------------------------------
if(success)
{
success(operation, result);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
dispatch_group_leave(group);
if(fail)
{
fail(operation, error);
}
}];
}
然后您可以去:
- (void)login
{
dispatch_group_t login_group = dispatch_group_create();
NSString* secureToken = nil;
NSString* loginSeed = nil;
[self getSecureToken:&secureToken group:login_group onSuccess:^(AFHTTPRequestOperation *operation, id responseObject){
NSLog(@"token is = %@", [responseObj valueForKey:@"token"]);
} onFail:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Failed to get token?");
}];
...
}
我找到了一個不錯的異步控制流庫Sequencer ,我喜歡這個解決方案,就像Node.js中的async一樣:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.