Передача примитивов через performSelectorOnMainThread
хорошо, скажем, у меня есть второй поток, но он хочет манипулировать чем-то в основном потоке, например UI
товар.
-(void)backgroundThread
{
[myButton performSelectorOnMainThread:@selector(setEnabled:) withObject:(BOOL)YES waitUntilDone:YES];
// right here, how could i pass this BOOL to the function
}
Я пробовал использовать NSNumber
' s numberWithBOOL
, а NSButton
не принимает его.
3 ответов
вы не можете использовать 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];
}
вы можете использовать блоки:
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
Да performSelectorOnMainThread:withObject:waitUntilDone:
больше не работает с примитивными типами. В прошлом это работало, пока у вас был только один аргумент, и это был интегральный тип, который можно было без потерь преобразовать из/в указатель. Это было небезопасно и некрасиво, но сработало.
однако Apple недавно изменила реализации этих методов, чтобы сохранить + освободить свои аргументы, которые, очевидно, взорвутся, когда этот аргумент содержит BOOL или другой не-объект тип.
хотя я создал вспомогательные методы в прошлом, мой любимый метод в настоящее время-использовать Более Того,, например:
[[myButton onMainThread] setEnabled:YES];
на NSInvocation
используется в реализации HOM заботится об обертывании и разворачивании всех примитивных типов, а синтаксис HOM позволяет легко вводить и очищать.
я назвал эту технику Небольшое Сообщение Отправка.