Массив указателей на объекты Objective-C в ARC в стиле C

У меня есть двумерный массив указателей на экземпляры Objective-C, чтобы отслеживать игровые объекты на сетке карты. Теперь я перевожу свой код на ARC, и Xcode указал на ошибку. Я знал, что указатели на объекты не разрешены в качестве членов структуры, но это застало меня (почти) врасплох.

Я понимаю причину ограничений ARC, но:

  1. Я не могу позволить себе накладные расходы на массивы Objective-C при поиске объектов в сетке, и

  2. Сами объекты уже принадлежат NSArrayivar, определенный в том же классе, который имеет сетку в стиле C в качестве ivar; массив c-style — это всего лишь удобно структурированный ярлык. Более того, когда объекты удаляются из владеющего NSArray, я устанавливаю соответствующий слот сетки в NULL.

То есть двумерный массив (сетка) — это просто набор быстрых (но тупых) указателей на объекты, безопасно сохраненные где-то еще (NSArrayivar).

Есть ли способ обойти это с помощью приведения типов? Например, определите и разместите мою сетку как:

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;
10
задан Brad Larson 26 June 2012 в 02:23
поделиться