C-style array of pointers to Objective-C objects under ARC
arrays, automatic-ref-counting, ios, malloc
Solution
Circumventing ARC using casts is generally a bad idea. The better way would be to disable ARC for your map.m (or break out just the lookup part into a separate class).Then do manual memory management inside it with `retain` / `release` and the C structures you like, as long as you do it correctly it will work fine and you will be able to call it from other classes, avoiding the overhead of nested `NSArrays` etc..
Problem
I have a 2D array of pointers to Objective-C instances to keep track of game objects on a map grid. Now I am transitioning my code to ARC, and Xcode pointed the error. I knew pointers to objects aren't allowed as struct members, but this one caught me (almost) off guard. I understand the rationale behind the ARC constrains, but: I can't afford the overhead of objective-C arrays when looking up objects in the grid, and The objects themselves are already owned by an `NSArray` ivar defined in the same class that has the C-style grid as an ivar; the c-style array is only a conveniently structured shortcut. Futhermore, when objects are removed from the owning `NSArray`, I set the corresponding grid slot to `NULL`. That is, the 2D array (grid) is just a collection of fast (but dumb) pointers to objects safely retained somewhere else (the `NSArray` ivar). Is there a way to get away with this using casts? For example, define and alloc my grid as: ``` void*** _grid; ``` instead of ``` MyMapObjectClass*** _grid ``` and use (appropriately bridged) casts between `void*` <-> `MyMapObjectClass*` when setting or getting the pointers in each slot? EDIT: So here is how I solved it I changed the ivar declaration as described above. In addition, when setting an entry of my look-up grid, I did this: ``` // (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; ``` When accessing the object at (x,y), I do the opposite: ``` MyMapObjectClass* object = (__bridge MyMapObjectClass*) _grid[x][y]; [object performSomeMethod]; // etc... ``` When removing the object from the map, I do this: ``` MyMapObjectClass* object = (__bridge MyMapObjectClass*) _grid[x][y]; [_objectArray removeObject:object]; _grid[x][y] = NULL; ``` Map objects are created once at the beginning of the game, and removed according to game progress. If I need to replace a map object for another, I would do this: ``` 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; ```