Làm cách nào để thay thế các tham chiếu yếu khi sử dụng ARC và nhắm mục tiêu iOS 4.0?


87

Tôi đã bắt đầu phát triển ứng dụng iOS đầu tiên của mình với Xcode 4.2 và đang nhắm mục tiêu iOS 5.0 với mẫu "ứng dụng tiện ích" (mẫu đi kèm với FlipsideViewController).

Tôi đọc rằng vì ARC là một tính năng thời gian biên dịch, nó cũng phải tương thích với iOS 4, vì vậy tôi đã cố gắng nhắm mục tiêu ứng dụng của mình thành 4.3 và thử biên dịch nó. Khi tôi làm như vậy, tôi gặp lỗi này:

FlipsideViewController.m: error: Sự cố đếm tham chiếu tự động: Mục tiêu triển khai hiện tại không hỗ trợ tham chiếu __weak tự động

Nó đang tham chiếu đến dòng này:

@synthesize delegate = _delegate;

Biến đó được khai báo là:

@property (weak, nonatomic) IBOutlet id <FlipsideViewControllerDelegate> delegate;

Tôi hiểu rằng "tham chiếu yếu" không được hỗ trợ trong iOS 4, nhưng tôi không thực sự hiểu tại sao tôi lại muốn sử dụng tham chiếu yếu để bắt đầu và cũng không thể tìm ra cách tôi sẽ viết lại những thứ để tránh sử dụng nó, trong khi vẫn tận dụng lợi thế của ARC (sau tất cả, nó phải hoạt động với iOS 4 VÀ 5 phải không?)

Câu trả lời:


149

Để nhắm mục tiêu hệ điều hành cũ hơn, bạn có thể sử dụng unsafe_unretainedthay vì weaktrong khai báo thuộc tính của mình và hầu hết nó sẽ hoạt động theo cùng một cách. weakbản thân các tham chiếu không có khi mục tiêu của chúng biến mất, nhưng vẫn unsafe_unretainedđể ngỏ khả năng đối tượng mà bạn đang liên kết đến có thể biến thành một con trỏ lơ lửng khi nó được định vị. Sau đó là hành vi tương tự như thể bạn đã sử dụng assignnhư một khai báo thuộc tính trong quản lý bộ nhớ thủ công.

Bạn làm điều này để tránh các chu kỳ lưu giữ, mà tôi đề cập trong câu trả lời của tôi ở đây . Bạn không muốn có một con trỏ mạnh đến một thứ gì đó mà có thể có một con trỏ mạnh quay lại đối tượng ban đầu. Sau đó, không có gì sẽ được phát hành đúng cách.


Cảm ơn vì lời khuyên. Bạn nói "để nhắm mục tiêu hệ điều hành cũ hơn ...". Điều này có nghĩa là tôi chỉ nên sử dụng secure_unretained trong các bản dựng của ứng dụng cũ hơn 5.0? Hay tôi có thể chỉ sử dụng secure_unretained trong mã của mình và xây dựng nó để nhắm mục tiêu cả 4.x và 5.x?
Mason G. Zhwiti

1
@Mason - unsafe_unretainedđược hỗ trợ trong cả iOS 4.x và 5.0, vì vậy nó mang lại cho bạn khả năng tương thích ngược. Nếu bạn đang thực hiện một bản dựng chỉ 5.0, bạn có thể chuyển sang weakđể tận dụng sự an toàn bổ sung mà nó mang lại cho bạn.
Brad Larson

Tôi đã thử không an toàn_unretained, nó vẫn hoạt động. Tuy nhiên, tôi đã nhận được rất nhiều cảnh báo như '"** __NSAutoreleaseNoPool (): Object 0x564bd90 của lớp __NSArrayM được autoreleased mà không có pool tại chỗ - chỉ rò rỉ" * ", điều đó có bình thường không?
thứ năm

1
@fifth - Đó là một vấn đề hoàn toàn không liên quan. Bạn đang chạy một cái gì đó trên một chuỗi nền mà không có một nhóm tự động khôi phục tại chỗ. Các chuỗi được tạo theo cách thủ công không có nhóm tự động phát hành riêng, vì vậy bạn cần tự tạo một nhóm bằng cách sử dụng @autoreleasepool(trong ARC, NSAutoreleasePool cho các triển khai được tính tham chiếu thủ công cũ hơn).
Brad Larson

@Brad, điều đó hữu ích, cảnh báo đã biến mất, tôi nhận được một số lệnh gọi performanceSelectorInBackground.
thứ năm

11

Nếu chỉ sử dụng các tham chiếu yếu để đảm bảo an toàn hơn, hãy gọi thủ công các hàm thời gian chạy mới nếu chúng có sẵn và dự phòng cho phép gán đơn giản trên __unsafe_unretainedcác biến nếu không.

ZWRCompatibility.h sẽ đơn giản hóa điều này phần nào.


10

Nhờ thư viện tương thích PLWeakCompatibilty của Mike Ash , giờ đây bạn có thể chỉ cần sử dụng __weak trên iOS 4.x.

Nó cực kỳ dễ dàng để cấu hình và không cần cân nhắc hoặc nỗ lực thêm trên 5.x.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.