У меня есть 2D массив указателей на экземпляры Objective-C для отслеживания игровых объектов на сетке карт. Теперь я переношу свой код в ARC, и Xcode указал на ошибку. Я знал, что указатели на объекты не допускаются как члены структуры, но этот меня поймал (почти) от страха.
Я понимаю обоснование ограничений ARC, но:
-
Я не могу позволить себе накладные расходы массивов Objective-C при поиске объектов в сетке и
-
Сами объекты уже принадлежат
NSArray
ivar, определенным в том же классе, который имеет сетку C-стиля в качестве ivar; массив c-style - это только удобно структурированный ярлык. Более того, когда объекты удаляются из владельца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;
При доступе к объекту at (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;