我有一个指向Objective-C实例的2D数组,用于跟踪地图网格上的游戏对象。 现在我将我的代码转换为ARC,Xcode指出了错误。我知道指向对象的指针不允许作为结构成员,但这个让我(差点)措手不及。
我理解ARC约束背后的基本原理,但是:
在网格中查找对象时,我无法承担Objective-C数组的开销,
对象本身已经由同一类中定义的NSArray
ivar拥有,该类具有作为ivar的C风格网格; c风格的数组只是一个方便的结构化快捷方式。此外,当从拥有NSArray
中移除对象时,我将相应的网格槽设置为NULL
。
也就是说,2D数组(网格)只是快速(但是愚蠢)指向安全地保留在其他地方(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;
答案 0 :(得分:2)
使用演员表来规避ARC通常是一个坏主意。更好的方法是将disable ARC用于map.m(或将查找部分分解为单独的类)。然后使用retain
/ release
进行手动内存管理。你喜欢的C结构,只要你正确地执行它就可以正常工作,你可以从其他类调用它,避免嵌套NSArrays
等的开销。