运行 私有队列上的任务并返回回调
Running a task on private queue and returning callback
我的方法 运行 将其代码放在私有队列中,完成后将调用传入的回调。是否需要检查传入的回调是否旨在 运行来自主队列?
例如
- (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();
}
}
});
}
您应该指定您的 API 方法 -doSomethingWithCallback:
在执行回调时将使用哪个队列,或者允许您的方法的使用者传入他们希望在其上执行的队列,就像这样:
/// callback will be executed on the queue passed in to onQueueOrNil.
/// If onQueueOrNil is nil, it will be executed on the main queue
- (void)doSomethingWithCallback:(void(^)())callback onQueue:(dispatch_queue_t)onQueueOrNil {
dispatch_async(self.privateQueue, ^{
if (callback){
if(!onQueueOrNil) {
onQueueOrNil = dispatch_get_main_queue();
}
dispatch_async(onQueueOrNil, callback);
}
});
}
虽然这在任何地方都没有规定,但如果您查看 Cocoa API,您会看到三种常见模式:
主线程: 明确指定将使用主 queue 的完成处理程序。例如参考CLGeocoder
asynchronous query methods,其中"Your completion handler block will be executed on the main thread."
任意 queue: 无法保证 queue 代码将是 运行 的完成处理程序.例如,如果您使用 requestAccessForEntityType
of CNContactStore
、the documentation says "The completion handler is called on an arbitrary queue."
指定 queue: 完成处理程序,您可以在其中指定要使用的 queue。例如,如果您使用 [NSURLSession sessionWithConfiguration:delegate:queue:]
,您可以指定哪个 queue 将用于委托方法和回调 blocks/closures。 (但是,顺便说一句,如果您不指定 queue,它会使用自己的设计之一,而不是默认使用主 queue。)
不过,您提出的模式不遵循任何这些非正式约定,而是有时使用主线程(如果您碰巧从主线程调用它),但有时使用一些任意的 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
请注意,无论您使用哪种约定,我都建议您在 headers 中使用 ///
注释或 /** ... */
注释,这样当您在代码中使用该方法时,您可以在右侧的快速帮助面板中看到 queue 行为。
我的方法 运行 将其代码放在私有队列中,完成后将调用传入的回调。是否需要检查传入的回调是否旨在 运行来自主队列?
例如
- (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();
}
}
});
}
您应该指定您的 API 方法 -doSomethingWithCallback:
在执行回调时将使用哪个队列,或者允许您的方法的使用者传入他们希望在其上执行的队列,就像这样:
/// callback will be executed on the queue passed in to onQueueOrNil.
/// If onQueueOrNil is nil, it will be executed on the main queue
- (void)doSomethingWithCallback:(void(^)())callback onQueue:(dispatch_queue_t)onQueueOrNil {
dispatch_async(self.privateQueue, ^{
if (callback){
if(!onQueueOrNil) {
onQueueOrNil = dispatch_get_main_queue();
}
dispatch_async(onQueueOrNil, callback);
}
});
}
虽然这在任何地方都没有规定,但如果您查看 Cocoa API,您会看到三种常见模式:
主线程: 明确指定将使用主 queue 的完成处理程序。例如参考
CLGeocoder
asynchronous query methods,其中"Your completion handler block will be executed on the main thread."任意 queue: 无法保证 queue 代码将是 运行 的完成处理程序.例如,如果您使用
requestAccessForEntityType
ofCNContactStore
、the documentation says "The completion handler is called on an arbitrary queue."指定 queue: 完成处理程序,您可以在其中指定要使用的 queue。例如,如果您使用
[NSURLSession sessionWithConfiguration:delegate:queue:]
,您可以指定哪个 queue 将用于委托方法和回调 blocks/closures。 (但是,顺便说一句,如果您不指定 queue,它会使用自己的设计之一,而不是默认使用主 queue。)
不过,您提出的模式不遵循任何这些非正式约定,而是有时使用主线程(如果您碰巧从主线程调用它),但有时使用一些任意的 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
请注意,无论您使用哪种约定,我都建议您在 headers 中使用 ///
注释或 /** ... */
注释,这样当您在代码中使用该方法时,您可以在右侧的快速帮助面板中看到 queue 行为。