我的方法在专用队列中运行其代码,完成后将调用传入的回调。是否需要检查传入的回调是否打算从主队列运行?

例如

- (void)doSomethingWithCalback:(void(^)())callback {
    dispatch_async(self.privateQueue, ^{
    // Should I make sure this gets dispatched
    // to a main thread if it was passed in from a main thread?
        if (callback) callback();
    });
}

我是否应该执行以下操作:
    - (void)doSomethingWithCalback:(void(^)())callback {
        BOOL isMainThread = [NSThread isMainThread];
        dispatch_async(self.privateQueue, ^{
            if (callback) {
               if (isMainThread) {
                 dispatch_async(dispatch_get_main_thread, callback);
               }
               else {
                 callback();
               }
            }
        });
    }

最佳答案

尽管没有在任何地方对此进行规定,但是如果您查看Cocoa API,则会看到三种常见的模式:

  • 主线程:完成处理程序,该处理程序明确指定将使用主队列。例如,请参考CLGeocoder asynchronous query methods,其中“您的完成处理程序块将在主线程上执行”。
  • 任意队列:完成处理程序,您无法确定将在哪个队列中运行代码。例如,如果使用requestAccessForEntityTypeCNContactStorethe documentation says“在任意队列上调用完成处理程序。”
  • 指定的队列:完成处理程序,您可以在其中指定要使用的队列。例如,如果使用[NSURLSession sessionWithConfiguration:delegate:queue:],则可以指定将哪个队列用于委托方法和回调块/关闭。 (但是,顺便说一句,如果您不指定队列,它会使用自己的设计方法,而不是默认使用主队列。)

  • 但是,您提出的模式没有遵循任何这些非正式约定,而是有时使用主线程(如果您碰巧从主线程调用它),但有时则使用一些任意队列。在这种情况下,我认为没有必要引入新的约定。

    我建议选择以上方法之一,然后在已发布的API中明确说明。例如,如果您要使用privateQueue:
    @interface MyAPI : NSObject
    
    /// Private queue for callback methods
    
    @property (nonatomic, strong, readonly) dispatch_queue_t privateQueue;
    
    /// Do something asynchronously
    ///
    /// @param callback  The block that will be called asynchronously.
    ///                  This will be called on the privateQueue.
    
    - (void)doSomethingWithCallback:(void(^)())callback;
    
    @end
    
    @implementation MyAPI
    
    - (void)doSomethingWithCallback:(void(^)())callback {
        dispatch_async(self.privateQueue, ^{
            if (callback) callback();
        });
    }
    
    @end
    

    要么
    @interface MyAPI : NSObject
    
    /// Private queue used internally for background processing
    
    @property (nonatomic, strong, readonly) dispatch_queue_t privateQueue;
    
    /// Do something asynchronously
    ///
    /// @param callback  The block that will be called asynchronously.
    ///                  This will be called on the main thread.
    
    - (void)doSomethingWithCallback:(void(^)())callback;
    
    @end
    
    @implementation MyAPI
    
    - (void)doSomethingWithCallback:(void(^)())callback {
        dispatch_async(self.privateQueue, ^{
            if (callback) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    callback();
                });
            }
        });
    }
    
    @end
    

    请注意,无论使用哪种约定,我建议在标题中使用///注释或/** ... */注释,以便在代码中使用该方法时,可以在右侧的快速帮助面板中看到队列行为。

    关于ios - 在专用队列上运行任务并返回回调,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35256182/

    10-12 14:30
    查看更多