有没有一种在背景 dispatch_queue 上初始化 ObjC 对象的好方法?

Is there a good way to init an ObjC object on a background dispatch_queue?

我有一个需要大量初始化的 ObjC class RuleSet(解析一个大 JSON 文件,对多个 OS 服务进行大量查询,应用启发式,最后,它构建了一组复杂的 NSPredicates,稍后可用于快速评估。

我的程序(此对象除外)从 MacOS(EndpointSecurity 框架)接收高优先级事件,并且必须在非常短的期限内响应这些事件 - 基于我当前的快速评估 RuleSet实例。

我在我创建的特殊(最高优先级)并发 dispatch_queue 中处理这些事件。

但是......如果我收到一些外部触发器,要更改我的 RuleSet - 我需要在应用它之前构建新的 RuleSet 实例,我希望创建它的代码不了解dispatch queues的内部结构,简单调用

RuleSet *newRules = [[RuleSet alloc] initWithJSON:newJSONPath];
[myEventHandlingEngine setRuleSet:newRuleSet];

我希望 RuleSet init 能够以某种方式将工作推迟到另一个低优先级序列 dispatch_queue,也许是部分的。我不介意在我完成之前阻止调用者(这个繁重的初始化不应该超过一秒钟......)。不过,重要的是我在优先级较低的队列上执行此操作 - 以便首先处理传入的事件。

现在我试着写

- (instancetype) initWithJSON:newJSONPath:(NSString *)jsonFilePath
{
   dispatch_sync([RuleSet setupQueue], ^{
     if ( nil == (self = [super init]) ) {
        self = nil;
          return self;
     }

        // heavy work here
        });
    return self;
}        

但这当然不会编译,因为 'self' 不是 __block 变量,我不确定它是否可以...

关于如何解决这个问题有什么建议吗?

您应该尝试使用 dispatchGroup 来处理这种情况:

- (instancetype) initWithJSON:newJSONPath:(NSString *)jsonFilePath
{
    if ( nil == (self = [super init]) ) {
        self = nil; //This seems useless since self is already nil ?
        return self;
    }
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, [OITPreventionPolicy policySetupQueue], ^{
    
      // Execute your heavy work here

     });
     // Wait for the group to finish its work (you could replace 'forever' by a timeout)
     dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
     return self;
}

调用dispatch_group_wait会阻塞创建对象的线程(所以不能是主线程)