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

时间:2012-06-22 11:25:10

标签: ios malloc automatic-ref-counting arrays

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

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

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

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

  3. 也就是说,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;
    

1 个答案:

答案 0 :(得分:2)

使用演员表来规避ARC通常是一个坏主意。更好的方法是将disable ARC用于map.m(或将查找部分分解为单独的类)。然后使用retain / release进行手动内存管理。你喜欢的C结构,只要你正确地执行它就可以正常工作,你可以从其他类调用它,避免嵌套NSArrays等的开销。