如何从异步属性的getter返回?

Kis*_*dan 7 objective-c grand-central-dispatch getter-setter ios

我已经过度使用了一个请求在线服务获取结果的getter.如何强制getter仅从同步块返回结果?

@interface MyClass ()

@property (nonatomic, strong) NSMutableDictionary* myDictionary;
@end 

@implementation MyClass

-(NSMutableDictionary*) myDictionary {

    dispatch_async(queue, ^{
         /* perform online request */
         dispatch_sync(dispatch_get_main_queue(), ^{
             // I need to obtain lock until this line gets executed and only then return
         });
    });
}
@end
Run Code Online (Sandbox Code Playgroud)

有一个非常好的谷歌搜索至少3小时我遇到了dispatch_group_async,dispatch_semaphore__block.我不知道我是否错误地使用它们但是没有达到目的.

更新1:

myDictionary是一个异步属性.我想看看这是否可以通过getter本身来实现.

aLe*_*ion 4

@Kishor 当请求真正异步时,UI 不会阻塞。您的“异步”请求阻止 UI 的原因是,事实上它们不是异步的。以下是伪代码中的原因:

- (double) notTruelyAsyncValue 
{
    __block double someExpensiveDoubleToCompute = 0.0;

    // One of the many ways that we can coordinate concurrent threads.
    dispatch_semaphore_t sema_done = dispatch_semaphore_create(0);

    dispatch_async(not_the_main_queue, ^(void) {
       // Simulate long processing time.
       sleep(5); 
       someExpensiveDoubleToCompute = 3.1415926535;
       dispatch_semaphore_signal(sema_done);
    });

    // We can't return until the async block has returned.
    // So we wait until it's done. If we wait on the main queue
    // then our UI will be "frozen". 
    dispatch_semaphore_wait(sema_done, DISPATCH_TIME_FOREVER);

    // Now we have our result we free the resources and return
    dispatch_release(sema_done);

    return someExpensiveDoubleToCompute;
}
Run Code Online (Sandbox Code Playgroud)

如果您从异步线程调用此方法,它不会阻塞 UI,但如果您从主队列/线程调用它,那么它将阻塞 UI,因为您正在主线程上等待信号量。不管你如何实现等待,它总是会阻塞UI,因为主线程是一个串行队列。这意味着在异步块完成之前,主队列上的其他块或事件都不会运行。

如果您不想阻塞 UI,则不要调用任何可能阻塞主线程的内容。一个好的模式是使用 @Collin 建议的完成块。模式如下:

- (void) computeAnyncValueWithCompletionBlock:((void)^(double value))completionBlock 
{
     dispatch_async(not_the_main_queue, ^(void) {
          // do some expensive computation.
          double value = 3.1415926535;
          completionBlock(value);
     });
}
Run Code Online (Sandbox Code Playgroud)

这可以从任何地方调用并且永远不会阻塞。