2011-05-25 16 views
9

Ok, supongamos que tengo un segundo hilo ejecutándose, pero quiere manipular algo en el hilo principal, como un elemento UI.Al pasar primitivas a través de performSelectorOnMainThread

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

He intentado usar NSNumber 's numberWithBOOL, pero el NSButton no lo acepta.

Respuesta

14

No puede usar performSelectorOnMainThread:withObject:waitUntilDone: con un argumento que no es un objeto Objective-C, y no puede usar NSNumber porque no hay unboxing automático de objetos a tipos primitivos.

Una solución es implementar un método similar que acepte un botón como argumento y llame a ese método en su lugar.

Por ejemplo, en la misma clase:

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

y

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

Otra solución es poner en práctica una categoría en NSButton con un método alternativo (por ejemplo -setEnabledWithNumber:), y el uso ese método en su lugar:

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

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

y

-(void)backgroundThread{ 
    [myButton performSelectorOnMainThread:@selector(setEnabledWithNumber:) 
           withObject:[NSNumber numberWithBool:YES] 
          waitUntilDone:YES]; 
} 
+0

Ya, ya había implementado un segundo método, pero la idea de categoría es mucho mejor –

3

Usted podría utilizar bloques:

BOOL boolValue = YES; 

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

Este utiliza el mi implementación de bloques retardados:

@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

¿Qué es exactamente un bloque y para qué se utiliza? Si pudieras proporcionar un enlace, sería útil. –

+0

http://thirdcog.eu/pwcblocks/ –

+0

Gracias, esto es útil –

3

Sí, performSelectorOnMainThread:withObject:waitUntilDone: ya no funciona en absoluto con los tipos primitivos . En el pasado, funcionó un poco, siempre y cuando solo tuvieras un argumento y fuera un tipo integral que se pudiera convertir sin pérdidas de/a un puntero. No era seguro, y no era bonito, pero funcionó.

Sin embargo, Apple cambió recientemente las implementaciones de estos métodos para retener + liberar sus argumentos, que obviamente explotarán cuando ese argumento contenga un BOOL u otro tipo de no objeto.

Aunque he creado métodos de ayuda en el pasado, mi técnica favorita hoy en día es el uso de un Higher Order Message tales como los siguientes:

[[myButton onMainThread] setEnabled:YES]; 

El NSInvocation utilizado en la aplicación de la HOM se encarga de envolver y desenvolver todos los tipos primitivos, y la sintaxis HOM hace que sea fácil de escribir y borrar.

He llamado esta técnica Little Message Dispatch.

Cuestiones relacionadas