2012-06-22 30 views
10

Tôi có một mảng con trỏ 2D cho các cá thể Objective-C để theo dõi các đối tượng trò chơi trên lưới bản đồ. Bây giờ tôi đang chuyển mã của tôi sang ARC và Xcode đã chỉ ra lỗi. Tôi biết con trỏ đến các đối tượng không được phép làm thành viên cấu trúc, nhưng điều này đã khiến tôi (gần như) mất cảnh giác.Mảng con trỏ kiểu C cho các đối tượng Objective-C trong ARC

Tôi hiểu lý do đằng sau sự ép ARC, nhưng:

  1. Tôi không có khả năng chi phí của mảng khách quan-C khi nhìn lên các đối tượng trong lưới, và

  2. Đối tượng bản thân chúng đã thuộc sở hữu của một thanh vectơ NSArray được định nghĩa trong cùng một lớp có lưới kiểu C làm ngà; mảng kiểu c chỉ là một lối tắt có cấu trúc thuận tiện. Hơn nữa, khi các đối tượng được lấy ra khỏi việc sở hữu NSArray, tôi đặt khe lưới tương ứng thành NULL.

Đó là, các mảng 2D (lưới) chỉ là một tập hợp các nhanh (nhưng câm) các đối tượng một cách an toàn giữ lại ở một nơi khác con trỏ (các NSArray Ivar).

Có cách nào để loại bỏ điều này bằng cách sử dụng phôi không? Ví dụ, xác định và alloc lưới của tôi là:

void*** _grid; 

thay vì

MyMapObjectClass*** _grid 

và sử dụng (một cách thích hợp bắc cầu) phôi giữa void* < ->MyMapObjectClass* khi đặt hoặc nhận các con trỏ trong mỗi khe?

EDIT: Vì vậy, đây là cách tôi giải quyết nó

tôi đã thay đổi tờ khai Ivar như đã mô tả ở trên. Ngoài ra, khi thiết lập một mục của lưới nhìn lên tôi, tôi đã làm điều này:

// (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; 

Khi truy cập vào các đối tượng tại (x, y), tôi làm ngược lại:

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

[object performSomeMethod]; 

// etc... 

Khi tháo đối tượng từ bản đồ, tôi làm điều này:

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

[_objectArray removeObject:object]; 

_grid[x][y] = NULL; 

Đối tượng bản đồ được tạo một lần vào đầu trò chơi và bị xóa theo tiến trình trò chơi. Nếu tôi cần phải thay thế một đối tượng bản đồ cho người khác, tôi sẽ làm điều này:

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; 
+0

mà dòng mã mà ARC đang chỉ ra ở đâu? –

+0

Xcode dường như không chỉ ra tất cả các lỗi cùng một lúc, mà thay vào đó là các lô 4-12. Bạn sửa chữa một số, và những cái tiếp theo xuất hiện trong kiểm tra sau đây. Lỗi đầu tiên xuất hiện trong khai báo ivar của mảng C. Và bây giờ, mọi phép gán hoặc so sánh giữa con trỏ obj-c và void * đang được báo hiệu. Tôi đang sửa chữa nó ngay bây giờ, và có vẻ như __bridge sẽ hoạt động ... –

+0

Thật lạ lùng, một số phôi được 'đề xuất' bởi tính năng tự động sửa lỗi của Xcode, nhưng một số chỉ được đánh dấu là lỗi. –

Trả lời

2

phá vỡ ARC sử dụng dàn diễn viên nói chung là một ý tưởng tồi. Cách tốt hơn sẽ là disable ARC cho bản đồ của bạn.m (hoặc chỉ chia nhỏ phần tra cứu thành một lớp riêng biệt) .Sau đó, hãy quản lý bộ nhớ thủ công bên trong nó với retain/release và các cấu trúc C mà bạn thích, miễn là bạn làm điều đó chính xác nó sẽ hoạt động tốt và bạn sẽ có thể gọi nó từ các lớp khác, tránh chi phí của lồng nhau vv ..

+0

Nhưng các con trỏ tôi làm việc như __unsafe_unretained. Tôi không phá vỡ ARC, chỉ sử dụng __bridge; không có vấn đề gì cả. Tôi đang giữ cho mảng NSArray và C đồng bộ. Các đối tượng được giữ lại bởi NSArray (theo ARC). Không có mối nguy hiểm của con trỏ lơ lửng. –

+1

Để làm cho nó rõ ràng hơn: Tôi có một NSArray thân thiện với ARC sở hữu các đối tượng của tôi, 100% Objective-C, 100% ARC. ** Ngoài ra **, tôi có một bảng 'tra cứu' để truy cập nhanh các đối tượng của tôi theo kiểu hàng/cột. Các mục bảng được cập nhật đúng thành NULL khi tôi xóa một đối tượng khỏi NSArray (được deallocated), để tránh dereferencing một zombie. –

+2

Tôi vẫn khuyên bạn nên tính toán nó vào một tệp riêng biệt và vô hiệu hóa ARC cho tệp đó, vì đó là giải pháp tương thích hơn trong tương lai. Nếu Apple từng quyết định thay đổi ngữ nghĩa, bạn sẽ không kết thúc với các lỗi biên dịch cho các phôi sơ sài. Giải pháp của bạn sẽ hoạt động. –

Các vấn đề liên quan