Да
let apiThread = DispatchQueue.global(qos: .utility)
func bridgeConnection(_ bridgeConnection: PHSBridgeConnection!, handle connectionEvent: PHSBridgeConnectionEvent) {
apiQueue.async {
...
}
}
Нет причин каждый раз получать очередь; Вы можете просто сохранить его как собственность.
Я знаю, что это не то, о чем ты думаешь, но это лучший подход. Просто отправьте, когда вам это нужно.
Можно создать нечто вроде того, о чем вы на самом деле думаете в ObjC, используя forwardInvocation:
, но это не очень хорошо переводит в Swift (базовый механизм не может быть реализован в Swift), и я не Я не рекомендую это. Батут - это объект (иногда объект NSProxy
), который может принять любое сообщение, что-то с ним сделать (например, переместить его в другую очередь), а затем повторно передать его другому объекту. Проблема в том, что трудно сказать компилятору: «Поверьте мне, он реализует каждый метод, который вам нужен во время выполнения» (потому что вы не можете этого пообещать, поэтому он может потерпеть крах). Даже в ObjC они часто оказывались более сложными, чем стоили, и единственная причина, по которой они стоили в первую очередь, это то, что ObjC не всегда имел GCD или блоки, и когда были добавлены блоки, синтаксис был Головная боль. В Swift это намного проще. Просто добавьте .async
вызов.
Просто чтобы показать, как выглядит батут, вот как выглядит очередь, использующая очередь операций (очень похожую на очередь отправки). Это написано в pre-ARC ObjC и не должно рассматриваться как пример современного ObjC.
#import <Foundation/Foundation.h>
@interface OperationQueueInvocationTrampoline : NSObject
{
@private
NSOperationQueue *myQueue;
id myTarget;
}
- (id)initWithQueue:(NSOperationQueue *)queue;
@end
#import "OperationQueueInvocationTrampoline.h"
@interface OperationQueueInvocationTrampoline ()
@property (nonatomic, readwrite, retain) NSOperationQueue *queue;
@property (nonatomic, readwrite, assign) id target;
@end
@implementation OperationQueueInvocationTrampoline
@synthesize queue = myQueue;
@synthesize target = myTarget;
- (id)initWithQueue:(NSOperationQueue *)queue
{
self = [super init];
if (self != nil)
{
self.queue = queue;
}
return self;
}
- (void)dealloc
{
[myQueue release];
myQueue = nil;
myTarget = nil;
[super dealloc];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
return [self.target methodSignatureForSelector:selector];
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
[invocation setTarget:self.target];
self.target = nil;
NSOperation *operation = [[[NSInvocationOperation alloc] initWithInvocation:invocation] autorelease];
[self.queue addOperation:operation];
}
- (id)prepareWithInvocationTarget:(id)target
{
self.target = target;
return self;
}
@end
Вы бы использовали это так:
id delegate = [[OperationQueueInvocationTrampoline alloc] initWithTarget:self];
[otherThing setDelegate:delegate];
Это сработало довольно хорошо, когда большинство протоколов были неформальными (поэтому здесь не было никакой проверки типов, и вы могли бы просто пропустить id
), но сделать эту компиляцию без предупреждений стало все более и более грязным, и это определенно быть головной болью в Swift сегодня. Это должно спасти много неприятностей, и это не так.
(Примечание: очереди - это не то же самое, что потоки. Проблема в том, к каким объектам очереди отправляются, а не в каком потоке.)