2010-07-12 34 views
119

Gần đây tôi đã cố gắng biên dịch một dự án Xcode cũ hơn (được sử dụng để biên dịch tốt) và bây giờ tôi thấy rất nhiều lỗi của mẫu này:lỗi: thuộc tính nguyên tử có thể ghi được không thể ghép nối bộ setter/getter tổng hợp với người dùng đã xác định setter/getter

error: writable atomic property 'someProperty' cannot pair a synthesized setter/getter with a user defined setter/getter

các mẫu mã gây các lỗi này luôn trông như thế này:

// Interface: 

@property (retain) NSObject * someProperty; 

// Implementation: 

@synthesize someProperty; // to provide the getter 
- (void)setSomeProperty:(NSObject *)newValue 
{ 
    //.. 
} 

tôi có thể thấy lý do tại sao các lỗi đã được tạo ra. Tôi nói với trình biên dịch để tổng hợp accessors tài sản của tôi (cả getter và setter), và sau đó ngay lập tức sau đó tôi ghi đè lên setter bằng tay. Mã đó luôn có mùi một chút.

Vì vậy, cách thích hợp để thực hiện việc này là gì? Nếu tôi sử dụng @dynamic thay vì @synthesize, tôi cũng sẽ phải viết trình khởi động. Có phải đó là cách duy nhất?

+0

Điều này chỉ xảy ra với thuộc tính 'nguyên tử 'không? Trong trường hợp các thuộc tính nguyên tử, bạn nên giữ cặp getter/setter đồng bộ về chiến lược khóa. Điều này là khó khăn nếu một phần được tổng hợp trong khi một phần khác là mã tùy chỉnh. –

+0

Nó chắc chắn sẽ biến mất nếu tôi làm cho tài sản nonatomic. Hấp dẫn. Tôi thậm chí không nghĩ về vấn đề đồng bộ hóa. –

+0

Tôi đã truy cập chủ đề này để tìm giải pháp cho vấn đề chính xác đó. Tôi không thực sự muốn viết một getter và một setter của bản thân mình. Oh well… –

Trả lời

208

tôi đã cùng một vấn đề và sau khi làm một chút nghiên cứu, đây là kết luận của tôi về vấn đề này:

Trình biên dịch cảnh báo bạn về một @property mà bạn khai báo là nguyên tử (tức là bằng cách bỏ qua các từ khóa nonatomic), nhưng bạn cung cấp một triển khai không đầy đủ về cách đồng bộ hóa quyền truy cập vào thuộc tính đó.

Để thực hiện cảnh báo rằng biến mất:

Nếu bạn khai báo một @property được nguyên tử rồi thực hiện một trong các cách sau:

  • sử dụng @dynamic hoặc;
  • sử dụng @synthesize và giữ bộ lọc tổng hợp và getter hoặc;
  • cung cấp triển khai thủ công cả hai số trình thiết lập và trình lấy (không sử dụng một trong các chỉ thị ở trên).

Nếu bạn khai báo @property với thì bạn có thể kết hợp cài đặt thủ công và tổng hợp của getters và setters.

Cập nhật: Lưu ý về tài sản Auto-Synthesis

Tính đến LLVM 4.0, Clang cung cấp tính năng tự động tổng hợp đối với tài sản đã tuyên bố rằng không phải là @dynamic. Theo mặc định, ngay cả khi bạn rời khỏi @synthesize, trình biên dịch sẽ cung cấp các phương thức getter và setter cho bạn. Tuy nhiên, quy tắc cho các thuộc tính nguyên tử vẫn như cũ: Hoặc cho phép trình biên dịch cung cấp cả hai trình khởi động và trình cài đặt, HOẶC thực hiện chúng cả hai chính bạn!

+0

Tôi xin lỗi vì mất quá nhiều thời gian để đánh dấu điều này là được chấp nhận. Hóa ra là chính xác 100% và rất hữu ích. –

+0

Cảm ơn bạn rất nhiều! –

+0

Cảm ơn! "khai báo @property với (nonatomic)" – Nianliang

12

Câu hỏi này, trong số các lần truy cập hàng đầu khác mà bạn nhận được từ việc tìm kiếm "thuộc tính tùy chỉnh C mục tiêu", không được cập nhật thông tin về "setter =" hoặc "getter =".

Vì vậy, để cung cấp thêm thông tin về câu hỏi này:

Bạn có thể cung cấp các cuộc gọi @property với phương pháp riêng của bạn bằng cách viết

@property(setter = MySetterMethod:, getter = MyGetterMethod) 

Thông báo đại tràng đối với phương pháp setter cung cấp.

Reference Apple documentation

EDIT: Tôi không khá chắc chắn như thế nào những thay đổi mới để tính Objective-C (họ có nhiều thông minh bây giờ) thay đổi câu trả lời cho câu hỏi này. Có lẽ tất cả nên được đánh dấu là lỗi thời.

+0

+1 Cảm ơn bạn đã thêm thông tin xuất sắc này ':)' –

+0

Tôi thấy rằng việc thiết lập phương thức setter đã không thực sự loại bỏ cảnh báo. ví dụ. -> "@property (gán, setter = setDelegate :) id ủy nhiệm;" Trong trường hợp này, tất cả những gì tôi có thể làm là thêm getter của riêng tôi hoặc thêm thuộc tính nonatomic, mà tôi không chắc chắn nếu tôi nên, cho rằng tôi đang thiết lập các đại biểu bản thân mình 'nguyên tử', nó không quan trọng có tài sản nonatomic hoặc tôi hiểu. –

+0

Thú vị, David. "Phiên bản" của Objective-C là gì trong (Tôi cho rằng phiên bản XCode sẽ hữu ích hơn)? Tôi không chắc chắn những thay đổi gần đây đối với Mục tiêu-C, cụ thể với iOS 6 ảnh hưởng đến điều này. –

12

Bạn cũng cần triển khai trình khởi động. Ví dụ:

// Interface: 

@property (retain) NSObject * someProperty; 

// Implementation: 

- (void)setSomeProperty:(NSObject *)newValue 
{ 
    @synchronized (self) 
    { 
     // ... 
    } 
} 

- (NSObject *)someProperty 
{ 
    NSObject *ret = nil; 

    @synchronized (self) 
    { 
     ret = [[someProperty retain] autorelease]; 
    } 

    return ret; 
} 
Các vấn đề liên quan