我有一个指向 Objective-C 实例的 2D 指针数组,以跟踪地图网格上的游戏对象。现在我正在将我的代码转换为 ARC,Xcode 指出了错误。我知道不允许将指向对象的指针作为结构成员,但是这个让我(几乎)措手不及。
我理解 ARC 约束背后的基本原理,但是:
在网格中查找对象时,我无法承受 Objective-C 数组的开销,并且
对象本身已经由
NSArray
定义在同一类中的 ivar 拥有,该类将 C 样式网格作为 ivar;c 风格的数组只是一种结构方便的快捷方式。此外,当从拥有的对象中删除对象时NSArray
,我将相应的网格槽设置为NULL
。
也就是说,二维数组(网格)只是快速(但愚蠢)指针的集合,指向安全地保留在其他地方(NSArray
ivar)的对象。
有没有办法使用演员来摆脱这种情况?例如,将我的网格定义和分配为:
void*** _grid;
代替
MyMapObjectClass*** _grid
并在设置或获取每个插槽中的指针时在void*
<->之间使用(适当桥接)强制转换?MyMapObjectClass*
编辑:所以这就是我解决它的方法
我如上所述更改了 ivar 声明。此外,在设置我的查找网格的条目时,我这样做了:
// (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;
当访问 (x,y) 处的对象时,我会做相反的事情:
MyMapObjectClass* object = (__bridge MyMapObjectClass*) _grid[x][y];
[object performSomeMethod];
// etc...
从地图中删除对象时,我这样做:
MyMapObjectClass* object = (__bridge MyMapObjectClass*) _grid[x][y];
[_objectArray removeObject:object];
_grid[x][y] = NULL;
地图对象在游戏开始时创建一次,并根据游戏进度移除。如果我需要替换另一个地图对象,我会这样做:
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;