2008-10-30 23 views
12

Estoy escribiendo una aplicación que carga de forma asíncrona las imágenes en la pantalla. Lo tengo configurado para que NO sea concurrente (es decir, genera un hilo y lo ejecuta uno a la vez), así que solo he reemplazado la función [NSOperation main] en mi subclase NSOperation.- [NSOperationQueue operations] devuelve una matriz vacía cuando no debería?

De todas formas, cuando agrego todas estas operaciones, deseo poder acceder más adelante a las operaciones en cola para cambiar sus prioridades. Desafortunadamente, cada vez que llamo al -[NSOperationQueue operations], todo lo que obtengo es una matriz vacía. La mejor parte es que después de colocar algunas instrucciones de impresión de consola, los hilos aún están en la cola y se están ejecutando (indicados por impresiones) a pesar de que la matriz está vacía.

¿Qué ofrece? También eché un vistazo a la cuenta solo para asegurarme de que no todos se están ejecutando de inmediato y ese no parece ser el caso.

¿Alguna idea? Tirando de mi cabello en este.

EDIT: También es importante mencionar que el mismo código ofrece una gama completa cuando se ejecuta en el simulador :(

Respuesta

0

Ni idea de por qué usted está viendo este comportamiento, sino como una solución pura se podía mantener sus propias referencias al individuo operaciones a medida que se agregan a la cola

1

Simplemente no creo que haya suficiente contexto aquí para decir lo que está pasando. Claramente algo está mal, pero no dice cómo está limitando la concurrencia, cómo está probando para ver los objetos que se están ejecutando, etc.

En cuanto al simulador frente al iPhone, NSOpe las raciones pueden actuar de forma muy diferente entre los dos, ya que todos los Macs basados ​​en Intel son multiprocesador, y no hay iPhones. Dependiendo de cómo intente limitar la concurrencia, podría encontrarse en una situación en la que no poder ejecutar en un segundo núcleo impida que se ejecuten cosas, etc. Pero sin más detalles es imposible saberlo.

0

He visto un comportamiento similar en situaciones de poca memoria. ¿Cuánta memoria estás usando? ¿Está borrando correctamente los cachés y otros datos temporales cuando recibe un mensaje didReceiveMemoryWarning?

8

que entramos por -operations, y hallaron que está haciendo básicamente:

[self->data->lock lock]; 
NSString* copy = [[self->data->operations copy] autorelease]; 
[self->data->lock unlock]; 
return copy; 

excepción, después de llamar -autorelease, las instrucciones subsiguientes sobrescribir el registro que contiene el único puntero a la nueva copia de la cola de operaciones. La persona que llama luego obtiene un valor de retorno de nil. El campo "data" es una instancia de una clase interna denominada _NSOperationQueueData que tiene campos:

NSRecursiveLock* lock; 
NSArray* operations; 

Mi solución fue subclase y anular -operations, siguiendo la misma lógica, pero en realidad devolver la copia de matriz. Agregué algunos controles de cordura para rescatar si las partes internas de NSOperationQueue no son compatibles con esta corrección. Esta reimplementación solo se invoca si, de hecho, una llamada al [super operations] devuelve nil.

Esto podría fallar en futuras versiones del sistema operativo si Apple cambiara la estructura interna, pero de alguna manera evitara arreglar este error.

#if TARGET_OS_IPHONE 

#import <objc/runtime.h> 

@interface _DLOperationQueueData : NSObject { 
@public 
    id lock; // <NSLocking> 
    NSArray* operations; 
} 
@end 
@implementation _DLOperationQueueData; @end 

@interface _DLOperationQueueFix : NSObject { 
@public 
    _DLOperationQueueData* data; 
} 
@end 
@implementation _DLOperationQueueFix; @end 

#endif 


@implementation DLOperationQueue 

#if TARGET_OS_IPHONE 

-(NSArray*) operations 
{ 
    NSArray* operations = [super operations]; 
    if (operations != nil) { 
     return operations; 
    } 

    _DLOperationQueueFix* fix = (_DLOperationQueueFix*) self; 
    _DLOperationQueueData* data = fix->data; 

    if (strcmp(class_getName([data class]), "_NSOperationQueueData") != 0) { 
     // this hack knows only the structure of _NSOperationQueueData 
     // anything else, bail 
     return operations; 
    } 
    if ([data->lock conformsToProtocol: @protocol(NSLocking)] == NO) { 
     return operations; // not a lock, bail 
    } 

    [data->lock lock]; 
    operations = [[data->operations copy] autorelease]; 
    [data->lock unlock]; 
    return operations; // you forgot something, Apple. 
} 

#endif 

@end 

El archivo de cabecera es:

@interface DLOperationQueue : NSOperationQueue {} 
#if TARGET_OS_IPHONE 
-(NSArray*) operations; 
#endif 
@end 
+0

¿Reportó esto en http://bugreport.apple.com y si es así, ¿cuál es el número de error? –

+0

No había enviado uno, pero lo hice ahora. ID de error # 6643022. –

0

Me acabo de encontrar con el mismo problema. Código más simple que el que uso en una aplicación OS X, y sin embargo [operaciones de operación de mi operación] siempre devuelve nulo. Estaba planeando usar eso para evitar duplicar las consultas. Esto está en iPhone OS 2.2.1. Claro parece un error. Gracias por el código, puedo usarlo, o simplemente usar mi propio espejo de la cola.

Esto no está en el simulador, y confirmo que agregué 20 o exactamente las mismas copias del trabajo, ¡que se alinean muy bien y hacen el trabajo 19 veces más!

Es un código bastante simple. No estoy usando casi ningún recuerdo, esto es en el lanzamiento de una aplicación que aún no tiene ninguna interfaz de usuario.

--Tom

Cuestiones relacionadas