将同步转换为异步Objective-C

时间:2018-06-21 19:15:25

标签: objective-c asynchronous objective-c-blocks

我正在使用新的代码库,但了解它的人并不多,所以希望能得到一些帮助。我正在更新接口,现在一些同步方法是异步的,这使得它很难适应当前架构来解析数据。

当前,我们有一个存储这些同步方法的功能图,然后,当我们想要数据时,我们执行“调用”,执行块/方法并返回值。

下面的一些代码显示了当前情况。

fnMap[@“vid”] = [[Callback alloc] initWithBlock:^id(id param) {
    return @([services getVisitorID]);
}];

… later, to resolve the data 

id fnMapVal = [fnMap[key] call:nil];

这是定义回调和回调块的方式。

typedef id (^CallbackBlock)(id);

@interface Callback : NSObject

@property(copy, nonatomic, readonly) CallbackBlock block;

- (instancetype)initWithBlock:(CallbackBlock)block


- (id)call:(id)param
{
    return self.block(param);
}

现在,该服务需要调用异步方法来获取ID,因此我不得不将其更改为:

- (void)getVisitorID: (nullable void (^) (NSString* __nullable visitorIdentifier)) callback
{
    [SDK getUserIdentifier:^(NSString * _Nullable userIdentifier) {
        callback(userIdentifier);
    }];
}

所以电话是:

  [services getVisitorID:^(NSString * _Nullable visitorIdentifier) {

    }];

我一直无法找到一种方法来适应当前的架构。我探索过的一些选项是使用运行循环来等待异步方法完成并保持我的界面同步,但这听起来是个坏主意。我想就如何适应这个问题提供一些建议,因为我从未见过这样的事情。

2 个答案:

答案 0 :(得分:0)

您需要使用dispatch_queues或NSOperationQueue在主线程之外运行代码。调度队列的级别很低,可以触发异步任务:

// we're going to run the getVisitorID method on a background queue
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [services getVisitorID:^(NSString * _Nullable visitorIdentifier) {
        dispatch_async(dispatch_get_main_queue(), ^(void){
            // update the user interface on the main queue
        });
    }];
});

我更喜欢使用NSOperationQueue,因为该API更清洁,并且它们允许您执行更高级的操作,例如使异步任务可取消:

// create a background queue
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperationWithBlock:^{
    [services getVisitorID:^(NSString * _Nullable visitorIdentifier) {
        // get the main queue and add your UI update code to it
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            // update the UI from here
        }];
    }];
}];

比弄乱运行循环更容易管理队列。有关更多信息,请参见此处:https://developer.apple.com/library/archive/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

答案 1 :(得分:0)

您需要的是Future / Promise概念。请不要重新发明轮子,您将不得不覆盖马拉松距离,以实现请求价值和异步消耗价值的相同功能。 作为收藏夹之一,请考虑PromiseKit。不过,不要害羞探索alternatives

您将很快发现它是异步任务的超级令人愉悦的构建链,将它们的结果映射到不同的值,将期货组合在一起以得到多个已解析的值的元组(一旦全部可用)—简洁,精心设计的形式可以实时使用在数百万个应用程序中进行了测试。