2012-06-22 13 views
10

Ho una matrice 2D di puntatori alle istanze Objective-C per tenere traccia degli oggetti di gioco sulla griglia di una mappa. Ora sto passando il mio codice a ARC, e Xcode ha indicato l'errore. Sapevo che i puntatori agli oggetti non sono ammessi come membri delle strutture, ma questo mi ha colto (quasi) di sorpresa.Matrice in stile C di puntatori agli oggetti Objective-C sotto ARC

Capisco la logica alla base dei vincoli ARC, ma:

  1. Non posso permettermi il sovraccarico di array Objective-C durante la ricerca di oggetti nella griglia, e

  2. Gli oggetti essi stessi sono già di proprietà di un ivar NSArray definito nella stessa classe che ha la griglia in stile C come un ivar; l'array c-style è solo una scorciatoia opportunamente strutturata. Inoltre, quando gli oggetti vengono rimossi dal proprietario NSArray, ho impostato lo slot della griglia corrispondente su NULL.

Cioè, la matrice 2D (griglia) è solo una raccolta di veloci (ma muti) puntatori a oggetti in modo sicuro a nuovo da qualche altra parte (la NSArray IVAR).

C'è un modo per farla franca con questo cast? Ad esempio, definire e Alloc mia griglia come:

void*** _grid; 

invece di

MyMapObjectClass*** _grid 

e utilizzare (in modo appropriato a ponte) getta tra void* < ->MyMapObjectClass* durante l'impostazione o di ottenere i puntatori in ogni slot?

EDIT: Quindi, ecco come ho risolto

ho cambiato la dichiarazione Ivar come descritto sopra. Inoltre, quando si imposta una voce della mia griglia di look-up, ho fatto questo:

// (Done **Only Once** at map initialization) 
// _objectArray is an instance of NSMutableArray 

MyMapObjectClass* mapObject = [[MyMapObjectClass alloc] init]; 

// ...configure map object, etc... 

// Add to Obj-C array: 
[_objectArray addObject:mapObject]; 

// Add pointer to 2D C array: 
_grid[i][j] = (__bridge void*)mapObject; 

Quando si accede l'oggetto (x, y), io faccio il contrario:

MyMapObjectClass* object = (__bridge MyMapObjectClass*) _grid[x][y]; 

[object performSomeMethod]; 

// etc... 

Quando si rimuove l'oggetto dalla mappa, faccio questo:

MyMapObjectClass* object = (__bridge MyMapObjectClass*) _grid[x][y]; 

[_objectArray removeObject:object]; 

_grid[x][y] = NULL; 

mappa oggetti vengono creati una sola volta all'inizio del gioco, e rimossi secondo i progressi di gioco. Se ho bisogno di sostituire un oggetto della mappa per un altro, farei questo:

MyMapObjectClass* oldObject = (__bridge MyMapObjectClass*) _grid[x][y]; 
// (should mark as weak?) 

[_objectArray removeObject:oldObject];  
_grid[x][y] = NULL; 

MyMapObjectClass* newObject = [[MyMapObjectClass alloc] init]; 

[_objectArray addObject:newObject]; 

_grid[x][y] = (__bridge void*)newObject; 
+0

dov'è la riga di codice che ARC sta indicando? –

+0

Xcode non sembra indicare tutti gli errori contemporaneamente, ma in gruppi di 4-12. Se ne aggiusti alcuni, e quelli successivi appaiono nel seguente controllo. Il primo errore è apparso nella dichiarazione di ivar del C-array. E ora, ogni assegnazione o confronto tra obj-c pointer e void * viene segnalato. Lo sto sistemando proprio ora, e sembra che __bridge dovrebbe funzionare ... –

+0

È curioso, alcuni dei cast sono "suggeriti" dalla funzione di correzione automatica di Xcode, ma alcuni sono semplicemente contrassegnati come errori. –

risposta

2

eludere arco utilizzando calchi è generalmente una cattiva idea. Il modo migliore sarebbe disable ARC per la tua map.m (o scomporre solo la parte di ricerca in una classe separata). Poi fai la gestione manuale della memoria al suo interno con retain/release e le strutture C che ti piacciono, a patto che tu lo faccia correttamente funzionerà correttamente e potrai chiamarlo da altre classi, evitando il sovraccarico di nidificato NSArrays ecc.

+0

Ma i puntatori che ho funzionano come __unsafe_unretained. Non sto aggirando ARC, usando solo __bridge; non dovrebbe esserci nessun problema Sto mantenendo il NSArray e l'array C in sincronia. Gli oggetti vengono mantenuti dal NSArray (come da ARC). Non c'è pericolo che puntino i puntatori. –

+1

Per chiarire meglio: ho un NSArray ARC-friendly che possiede i miei oggetti, 100% Objective-C, 100% ARC. ** Inoltre **, ho una "tabella di consultazione" per ottenere un accesso rapido ai miei oggetti in una riga/colonna. Le voci della tabella vengono correttamente aggiornate a NULL quando rimuovo un oggetto dal NSArray (che viene deallocato), per evitare il dereferenziamento di uno zombie. –

+2

Si consiglia comunque di prenderlo in considerazione in un file separato e disabilitare ARC per quel file, poiché si tratta di una soluzione più a prova di futuro. Se Apple deciderà mai di cambiare la semantica, non si otterranno errori di compilazione per i cast abbozzati. La tua soluzione funzionerà comunque. –

Problemi correlati