ARC下的Objective-C对象的C风格指针数组

Nic*_*ari 10 arrays malloc ios automatic-ref-counting

我有一个指向Objective-C实例的2D数组,以跟踪地图网格上的游戏对象.现在我将我的代码转换为ARC,Xcode指出了错误.我知道指向对象的指针不允许作为结构成员,但这个让我(差点)措手不及.

我理解ARC约束背后的基本原理,但是:

  1. 在网格中查找对象时,我无法负担Objective-C数组的开销

  2. 对象本身已经由NSArray同一类中定义的ivar 拥有,该类具有作为ivar的C风格网格; c风格的数组只是一个方便的结构化快捷方式.此外,当从拥有对象中删除对象时NSArray,我将相应的网格槽设置为NULL.

也就是说,2D数组(网格)只是快速(但是愚蠢)指向安全保留在其他地方(NSArrayivar)的对象的集合.

有没有办法摆脱使用演员阵容?例如,将我的网格定义并分配为:

void*** _grid;
Run Code Online (Sandbox Code Playgroud)

代替

MyMapObjectClass*** _grid
Run Code Online (Sandbox Code Playgroud)

在每个插槽中设置或获取指针时,在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;
Run Code Online (Sandbox Code Playgroud)

在(x,y)访问对象时,我做了相反的事情:

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

[object performSomeMethod];

// etc...
Run Code Online (Sandbox Code Playgroud)

从地图中删除对象时,我这样做:

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

[_objectArray removeObject:object];

_grid[x][y] = NULL;
Run Code Online (Sandbox Code Playgroud)

地图对象在游戏开始时创建一次,并根据游戏进度删除.如果我需要替换另一个地图对象,我会这样做:

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;
Run Code Online (Sandbox Code Playgroud)

Ham*_*son 2

使用强制类型转换来规避 ARC 通常是一个坏主意。更好的方法是为你的map.m禁用ARC(或者将查找部分分解为一个单独的类)。然后使用retain/release和你喜欢的C结构在其中进行手动内存管理,只要你做得正确它将正常工作,您将能够从其他类调用它,避免嵌套NSArrays等的开销。

  • 我仍然建议将其分解为一个单独的文件,并为该文件禁用 ARC,因为这是一个更面向未来的解决方案。如果 Apple 决定更改语义,您将不会因粗略的转换而出现编译错误。不过你的解决方案会起作用。 (2认同)