2011-05-25 65 views
9

好吧,所以说我有第二个线程运行,但它想要操纵主线程上的东西,如UI项目。通过performSelectorOnMainThread传递原语

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

我一直在使用NSNumbernumberWithBOOL试过,但NSButton不接受它。

回答

14

您不能使用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]; 
} 
+0

雅,我已经实施了第二种方法,但类别的想法更好 – 2011-05-25 07:14:24

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 
+0

什么是一个块,它用于什么?如果你可以提供一个链接,那会很有帮助。 – 2011-05-25 08:35:51

+0

http://thirdcog.eu/pwcblocks/ – 2011-05-25 20:00:04

+0

谢谢,这很有帮助 – 2011-05-26 23:05:15

3

是的,performSelectorOnMainThread:withObject:waitUntilDone:不再适用于所有基本类型。在过去,只要你只有一个参数,它就可以工作,并且它是一个整体类型,可以无损地转换成指针。这是不安全的,它不漂亮,但它确实工作。

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

虽然我已经创建了一个过去的辅助方法,我最喜欢的技术现在是使用Higher Order Message如下列:

[[myButton onMainThread] setEnabled:YES]; 

在HOM的执行中使用的NSInvocation需要包装的关怀和解开所有的基本类型,并且HOM语法可以很容易地输入和清除。

我称这种技术为Little Message Dispatch