通过performSelectorOnMainThread传递基元

时间:2011-05-25 06:51:38

标签: objective-c macos nsthread

好的,所以说我有第二个线程正在运行,但它想在主线程上操作一些东西,比如UI项。

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

我已尝试使用NSNumber的{​​{1}},但numberWithBOOL不接受。{/ p>

3 个答案:

答案 0 :(得分:16)

您不能将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];
}

答案 1 :(得分:3)

您可以使用块:

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

答案 2 :(得分:3)

是的,performSelectorOnMainThread:withObject:waitUntilDone:根本不再适用于原始类型。在过去,只要你只有一个参数并且它是一个可以从/向指针无损转换的整数类型,它就有用了。它不安全,并不漂亮,但确实有效。

然而,Apple最近更改了这些方法的实现以保留+释放它们的参数,当该参数包含BOOL或其他非对象类型时,这显然会爆炸。

虽然我过去曾创建过辅助方法,但现在我最喜欢的技术是使用Higher Order Message,如下所示:

[[myButton onMainThread] setEnabled:YES];

HOM实现中使用的NSInvocation负责包装和解包所有基本类型,而HOM语法使得输入和清除变得容易。

我称这种技术为Little Message Dispatch