指针下的ARC的Objective-C对象的C数组 [英] C-style array of pointers to Objective-C objects under ARC

查看:141
本文介绍了指针下的ARC的Objective-C对象的C数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有指针Objective-C的实例的二维数组来跟踪游戏对象在地图上的坐标。
现在我转变我的code为弧形,和X code指出的错误。我知道对象指针不允许作为结构成员,但是这一次抓住了我(几乎)猝不及防。

据我所知,ARC背后的基本原理约束,但是:


  1. 查找在网格对象时我不能客观-C数组的开销,以及


  2. 本身已经在具有C风格的网格,伊娃相同的类中定义的的NSArray 伊娃拥有的对象; C风格的数组仅仅是一个方便快捷的结构。 Futhermore,当对象从所属的NSArray 去掉,我设置了相应的网格槽 NULL


也就是说,二维数组(网格)只是一个快速(但哑)三分球安全地保留在其他地方(即的NSArray 伊娃)对象的集合。

有没有办法逃脱这个使用强制转换?例如,定义和ALLOC我格为:

 无效*** _grid;

而不是

  MyMapObjectClass *** _grid

和使用(适当桥接)之间蒙上无效* < - > MyMapObjectClass *设置或获取时在每个时隙指针?

修改:因此,这里是我如何解决它。

我改变了伊娃声明如上所述。此外,设置我的查询网格的条目时,我这样做:

  //(完成**仅**一旦在地图初始化)
// _objectArray是的NSMutableArray的一个实例MyMapObjectClass * MapObject的= [[MyMapObjectClass的alloc]初始化];// ...配置地图对象,等等。//添加到的OBJ-C数组:
[_objectArray ADDOBJECT:MapObject的]。//添加指向二维数组c:
_grid [I] [J] =(__bridge无效*)MapObject的;

在访问时(X,Y)的对象,我却反其道而行之:

  MyMapObjectClass *对象=(__bridge MyMapObjectClass *)_grid [X] [Y][对象performSomeMethod]//等等...

当从地图上删除的对象,我这样做:

  MyMapObjectClass *对象=(__bridge MyMapObjectClass *)_grid [X] [Y][_objectArray的removeObject:对象]。_grid [X] [Y] = NULL;

Map对象是根据游戏进度在游戏开始创建一次,并删除。如果我需要的替换作为另一地图对象,我会做这样的:

  MyMapObjectClass *的OLDobject =(__bridge MyMapObjectClass *)_grid [X] [Y]
//(应标记为弱?)[_objectArray的removeObject:的OLDobject];
_grid [X] [Y] = NULL;MyMapObjectClass * NEWOBJECT = [[MyMapObjectClass的alloc]初始化];[_objectArray ADDOBJECT:NEWOBJECT];_grid [X] [Y] =(__bridge无效*)NEWOBJECT;


解决方案

使用ARC规避一般铸件是一个坏主意。更好的方法是<一个href=\"http://stackoverflow.com/questions/6646052/how-can-i-disable-arc-for-a-single-file-in-a-project\">disable ARC 的为您map.m(或爆发只是部分查找到一个单独的类)。然后做在里面手动内存管理,保留 / 发布和C结构你喜欢,只要你正确地做到这一点它会正常工作,你将能够从其他类调用它,避免嵌套的<$ C $的开销C> NSArrays 等

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:

  1. I can't afford the overhead of objective-C arrays when looking up objects in the grid, and

  2. 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;

解决方案

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..

这篇关于指针下的ARC的Objective-C对象的C数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆