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:
Non posso permettermi il sovraccarico di array Objective-C durante la ricerca di oggetti nella griglia, e
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 proprietarioNSArray
, ho impostato lo slot della griglia corrispondente suNULL
.
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;
dov'è la riga di codice che ARC sta indicando? –
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 ... –
È curioso, alcuni dei cast sono "suggeriti" dalla funzione di correzione automatica di Xcode, ma alcuni sono semplicemente contrassegnati come errori. –