gpt4 book ai didi

iphone - 在 iOS 中进行异步调用同步的最佳实践?

转载 作者:行者123 更新时间:2023-11-28 22:38:21 26 4
gpt4 key购买 nike

我有一个单例类 APIClient,它需要先设置 userId 和 authToken,然后才能调用我的后端。

我们目前将 userId 和 authToken 存储在 NSUserDefaults 中。对于全新安装,这些值不存在,我们向服务器查询它们。

目前,如果这些值不存在,我们在 ViewController 的 viewDidLoad 方法中有代码手动查询服务器。

我有兴趣让这门课“正常工作”。通过这个,我的意思是让客户端检查它是否已经初始化,如果没有调用服务器并设置适当的 userId 和 authToken - 所有这些都没有人工干预。

这已被证明是一个相当棘手的原因:

  1. 我无法使 asyncObtainCredentials 同步,因为 #iphonedev 的人告诉我,如果我必须卡住主线程以进行网络操作,操作系统将终止我的应用程序
  2. 对于我们现在所拥有的,由于 asyncObtainCredential 的异步特性,第一次调用总是会失败。将返回 Nil,第一次调用总是会失败。

有人知道解决这个问题的好方法吗?

`

@interface APIClient ()
@property (atomic) BOOL initialized;
@property (atomic) NSLock *lock;
@end

@implementation APIClient

#pragma mark - Methods

- (void)setUserId:(NSNumber *)userId andAuthToken:(NSString *)authToken;
{
self.initialized = YES;
[self clearAuthorizationHeader];
[self setAuthorizationHeaderWithUsername:[userId stringValue] password:authToken];
}

#pragma mark - Singleton Methods

+ (APIClient *)sharedManager {
static dispatch_once_t pred;
static APIClient *_s = nil;

dispatch_once(&pred, ^{
_s = [[self alloc] initWithBaseURL:[NSURL URLWithString:SERVER_ADDR]];
_s.lock =[NSLock new] ;
});

[_s.lock lock];
if (!(_s.initialized)) {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSNumber *userId = @([prefs integerForKey:KEY_USER_ID]);
NSString *authToken = [prefs stringForKey:KEY_AUTH_TOKEN];

// If still doesn't exist, we need to fetch
if (userId && authToken) {
[_s setUserId:userId andAuthToken:authToken];
} else {
/*
* We can't have obtainCredentials to be a sync operation the OS will kill the thread
* Hence we will have to return nil right now.
* This means that subsequent calls after asyncObtainCredentials has finished
* will have the right credentials.
*/
[_s asyncObtainCredentials:^(NSNumber *userId, NSString *authToken){
[_s setUserId:userId andAuthToken:authToken];
}];
[_s.lock unlock];
return nil;
}
}
[_s.lock unlock];

return _s;
}

- (void)asyncObtainCredentials:(void (^)(NSNumber *, NSString *))successBlock {

AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:SERVER_ADDR]];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:[OpenUDID value], @"open_udid", nil];
NSMutableURLRequest *request = [client requestWithMethod:@"GET" path:@"/get_user" parameters:params];

AFJSONRequestOperation *operation = \
[AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
...

// Do not use sharedManager here cause you can end up in a deadlock
successBlock(userId, authToken);

} failure:^(NSURLRequest *request , NSURLResponse *response , NSError *error , id JSON) {
NSLog(@"obtain Credential failed. error:%@ response:%@ JSON:%@",
[error localizedDescription], response, JSON);
}];

[operation start];
[operation waitUntilFinished];
}

最佳答案

您应该在应用程序启动期间检查这些值是否存在于 NSUserDefaults 中。如果它们不存在,请调用以从服务器获取它并在屏幕上显示加载覆盖图。获取它后,您可以继续下一步。

如果您不想使用加载覆盖,您可以在 APIClient 类中设置一些 isLoading 标志并检查它以了解 asyn 是否仍在获取。因此,无论何时进行服务调用并且需要这些值,您都知道如何根据此标志处理它。一旦您获得了所需的值并将其存储在 NSUserDefaults 中,您就可以继续下一步了。你可以使用 Notifications/Blocks/KVO 来通知你的 View Controller 让他们知道你已经获取了这些值。

关于iphone - 在 iOS 中进行异步调用同步的最佳实践?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15285244/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com