Обеспечение того, что методы выполняются только основным потоком - PullRequest
2 голосов
/ 11 апреля 2009

У меня есть классjective-c, методы которого я только хочу вызывать из основного потока.

Я мог бы добиться этого, добавив что-то вроде этого к каждому селектору:

- (void) exampleSelector: (id) param {
    if (![NSThread isMainThread]) {
        [self peformSelectorOnMainThread:@selector(exampleSelector:) withObject:param waitUntilDone:YES];
        return;
    }
    // Do stuff it's not safe to do outside the main thread
}

Тем не менее, кажется немного трудным добавить это к каждому отдельному селектору. Есть ли способ, которым я могу автоматически перехватить все вызовы объектов этого класса, проверить, в каком потоке он находится, и использовать executeSelectorOnMainThread, если это не основной поток?

Ответы [ 2 ]

1 голос
/ 11 апреля 2009

Хм. Я не уверен, возможно ли это сделать; Я не могу придумать, как это сделать. Вместо этого я бы хотел заменить объект прокси-сервером. Прокси будет отвечать за переадресацию вызовов на объект в правильном потоке.

@interface Forwarder : NSObject
{
    id recipient;
}

- (Forwarder *)initWithRecipient:(id)inRecipient;

@end

@implementation Forwarder

- (Forwarder *)initWithRecipient:(id)inRecipient {
    [inRecipient retain];
    recipient = inRecipient;
    return self;
}

- (void)dealloc {
    [recipient release];
    [super dealloc];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    if ([recipient respondsToSelector: [anInvocation selector]]) {
        if (![NSThread isMainThread]) {
            // Note: only works with methods that take one argument. Should add
            // error handling for other methods
            id argument;
            [invocation getArgument: &argument atIndex: 2];
            [recipient performSelectorOnMainThread: [anInvocation selector] withObject: argument waitUntilDone: YES];
        } else {
            [anInvocation invokeWithTarget:recipient];
        }
    } else {
        [super forwardInvocation:anInvocation];
    }
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    if ([recipient respondsToSelector: aSelector])
        return [recipient methodSignatureForSelector: aSelector];
    else
        return [super methodSignatureForSelector: aSelector];
}

@end
0 голосов
/ 22 мая 2009

Возможно, вместо этого вы должны наложить ограничение на вызывающих метод, чтобы не вызывать его из произвольного потока. Если основной поток заблокирован в ожидании результата от потока B, а поток B вызывает метод, подобный тому, что был в вашем примере, у вас будет тупик.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...