2010-04-07 10 views
9

Este pedazo de código me falla, ¿por qué? allButtons es una NSMutableArray, que contiene 3 objetos, a=0, b=1, ayb son int tipoCómo intercambiar valores en NSMutableArray?

if(a != -1 && b!= -1){ 
    //Swap index in "allButtons" 
    id tempA = [allButtons objectAtIndex:a]; 
    id tempB = [allButtons objectAtIndex:b]; 
    [allButtons replaceObjectAtIndex:a withObject:tempB]; //Seg fault here????? 
    [allButtons replaceObjectAtIndex:b withObject:tempA]; 
    needLoad = false; 
    [self setUpButtons]; 
} 

EDIT:

NSMutableArray *allButtons = //fetch the array from Coredata. This work since I display the data onto the screen, plus, [allButtons count] return 3, and a=0, b=1 
f(a != -1 && b!= -1){ 
    //Swap index in "allButtons" 
    [allButtons exchangeObjectAtIndex:a withObjectAtIndex:b]; 
    needLoad = false; 
    [self setUpButtons]; 
} 
+0

Puede ser útil para enviar el mensaje de error real, si es posible. Probablemente también sea útil publicar la declaración de clase para que podamos ver si allButtons es una propiedad, y si es así, cuál es su semántica de gestión de memoria, etc. – jlehr

Respuesta

11

El hecho de que usted ha dicho

NSMutableArray *allbuttons = // something 

no quiere decir que es sin duda un NSMutableArray, sólo significa que el compilador piensa que va a ser un NSMutableArray.

Si es de CoreData, es probable que sea solo un NSArray, por lo que las llamadas a los métodos que está intentando no funcionarán: obtendrá un selector no reconocido o algo así.

Usted tendrá que convertirlo en una matriz mutable primera

NSArray *coreData = // core data call 

// Create a mutable copy 
// NB This means that you are now working on a copy, not the original :) 
NSMutableArray *allButtons = [coreData mutableCopy]; 
+0

ty que soluciona el problema. –

+1

O simplemente NSMutableArray * allButtons = [coreData mutablecopy]; –

2

tempA va a ser puesto en libertad cuando se llama a la primera replaceObjectAtIndex. Téngalo en cuenta cuando llame a esto ... No tengo idea de por qué liberar tempA sería un error para usted, examine lo que hace su dealloc quizás.

Comprobar la cuenta de tempA retener para verificar que efectivamente es dealloc-ed (no simplemente liberado) por la llamada a replaceObjectAtIndex así:

id tempA = [allButtons objectAtIndex:a]; 
NSLog(@"retain count for tempA: %i", [tempA retainCount]); 

Si ve una cuenta de retención de 1 a este nivel , entonces su objetivo es ser tempA dealloc de opinión de la llamada a replaceObjectAtIndex

+0

'recountCount' return back 3. –

+0

¿Está llamando esto desde el hilo principal o un hilo secundario? Si lo está llamando desde un hilo secundario, ¿creó un grupo de autoinformación? –

22

la primera llamada a replaceObjectAtIndex: dará a conocer el objeto de edad (tempA), pero eso no debería causar una falla seg. Como @Zoran mencionó, intenta registrar el retainCount para tempA y verifica su recuento.

También para intercambiar elementos en una matriz, debe usar exchangeObjectAtIndex:withObjectAtIndex en lugar de replaceObjectAtIndex:withObject. Es compatible con iPhone 2.0.

+0

Intento 'exchangeObjectAtIndex: withObjectAtIndex' y esto es lo que obtuve' Aplicación de terminación debido a una excepción no detectada 'NSInvalidArgumentException', razón: '*** - [_ PFArray exchangeObjectAtIndex: withObjectAtIndex:]: selector no reconocido enviado a la instancia 0x3a35a30''. Por cierto, 'recountCount' devuelve 3. –

+0

¿Qué versión del SDK de iPhone está usando? Además, publique el código donde está creando 'NSMutableArray', y usando' exchangeObject..' – Anurag

+0

Solo edito mi código. TYVM –

0

Lea y comprenda las reglas de Cocoa en object ownership. Tenga en cuenta que usted no ha reclamado la propiedad sobre los objetos referenciados por tempa y tempB y por lo tanto se debe prestar atención a lo siguiente: objeto normalmente se garantiza para permanecer válida dentro del método que se recibió en ...

A recibió (aunque también debe tener cuidado si modifica un objeto del que recibió otro objeto). Ese método también puede devolver el objeto de forma segura a su invocador.

Básicamente, la línea:

[allButtons replaceObjectAtIndex:a withObject:tempB]; 

Puede causar tempa a cancelar la asignación. Esto significa que la línea subsiguiente hará que allButtons envíe un mensaje retener a un objeto inválido, de ahí el fallo seg. Para solucionar el problema, debe conservar tempA antes del intercambio y liberarlo o liberarlo automáticamente después.

Nota: es aconsejable olvidarse de los conteos. A menos que esté completamente al tanto de la implementación de todos los objetos que tocan sus objetos, no puede hacer suposiciones sobre cuál es el recuento retenido de un objeto. Por ejemplo, no existe una regla que diga que la implementación de NSMutableArray solo retendrá sus elementos una vez.

0

Utilice este método pasar el índice appropritate

exchangeObjectAtIndex:withObjectAtIndex: 
Cuestiones relacionadas