Передача примитивов через executeSelectorOnMainThread - PullRequest
10 голосов
/ 25 мая 2011

Хорошо, скажем, у меня запущен второй поток, но он хочет что-то манипулировать в основном потоке, например, элемент UI.

-(void)backgroundThread
{
    [myButton performSelectorOnMainThread:@selector(setEnabled:) withObject:(BOOL)YES waitUntilDone:YES];
     // right here, how could i pass this BOOL to the function
}

Я пытался использовать NSNumber numberWithBOOL, но NSButton не принимает его.

Ответы [ 3 ]

16 голосов
/ 25 мая 2011

Вы не можете использовать performSelectorOnMainThread:withObject:waitUntilDone: с аргументом, который не является объектом Objective-C, и вы не можете использовать NSNumber, потому что нет автоматической распаковки объектов от примитивных типов.

Одно из решений состоит в том, чтобыреализовать аналогичный метод, который принимает кнопку в качестве аргумента, и вместо этого вызывать этот метод.

Например, в том же классе:

- (void)enableButton:(NSButton *)button {
    [button setEnabled:YES];
}

и

-(void)backgroundThread{
    [self performSelectorOnMainThread:@selector(enableButton:)
                           withObject:myButton
                        waitUntilDone:YES];
}

Другое решение состоит в том, чтобы реализовать категорию на NSButton с помощью альтернативного метода (например, -setEnabledWithNumber:) и использовать вместо этого метод:

@interface NSButton (MyButtonCategory)
- (void)setEnabledWithNumber:(NSNumber *)enabled;
@end

@implementation NSButton (MyButtonCategory)
- (void)setEnabledWithNumber:(NSNumber *)enabled {
    [self setEnabled:[enabled boolValue]];
}
@end

и

-(void)backgroundThread{
    [myButton performSelectorOnMainThread:@selector(setEnabledWithNumber:)
                               withObject:[NSNumber numberWithBool:YES]
                            waitUntilDone:YES];
}
3 голосов
/ 19 октября 2012

Да, performSelectorOnMainThread:withObject:waitUntilDone: больше не работает с примитивными типами.Раньше это работало до тех пор, пока у вас был только один аргумент, и это был целочисленный тип, который можно было преобразовать без потерь из / в указатель.Это было небезопасно, и это было не красиво, но это работало.

Однако Apple недавно изменила реализации этих методов, чтобы сохранить + освободить их аргументы, которые, очевидно, будут взорваны, когда этот аргумент содержитBOOL или другой необъектный тип.

Хотя в прошлом я создавал вспомогательные методы, в настоящее время мой любимый метод - использовать Сообщение более высокого порядка , например, следующее:

[[myButton onMainThread] setEnabled:YES];

NSInvocation, используемый в реализации HOM, заботится о переносе и развертывании всех примитивных типов, а синтаксис HOM упрощает ввод и очистку.

I 'мы назвали эту технику Little Message Dispatch .

3 голосов
/ 25 мая 2011

Вы можете использовать блоки:

BOOL boolValue = YES;

[self performOnMainThreadWait:YES block:^(id owner) {
    [button setEnabled:boolValue];
}];

Это использует мою реализацию отложенных блоков:

@implementation NSObject (HHBlockPerform)

- (void)performAfterDelay:(NSTimeInterval)delay block:(HHPerformBlock)block
{
    [self performSelector:@selector(runBlock:) withObject:[block copy] afterDelay:delay];
}

- (void)performOnMainThreadWait:(BOOL)wait block:(HHPerformBlock)block
{
    [self performSelectorOnMainThread:@selector(runBlock:)
                           withObject:[block copy]
                        waitUntilDone:wait
                                modes:[NSArray arrayWithObject:NSRunLoopCommonModes]];
}

- (void)runBlock:(HHPerformBlock)block
{
    block(self);

    [block release];
}

@end
...