lỗi: thuộc tính nguyên tử có thể ghi không thể ghép một setter / getter tổng hợp với setter / getter do người dùng định nghĩa


128

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 biểu mẫu này:

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

Mẫu mã gây ra 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 tại sao lỗi được tạo ra. Tôi nói với trình biên dịch tổng hợp các bộ truy cập thuộc tính của tôi (cả getter và setter), và sau đó ngay lập tức sau đó tôi ghi đè setter bằng tay. Mã đó luôn luôn có một chút mùi.

Vì vậy, cách thích hợp để làm điều này là gì? Nếu tôi sử dụng @dynamicthay vì @synthesize, tôi cũng sẽ phải viết getter. Có phải đó là cách duy nhất?


Điều này chỉ xảy ra với atomictài sản? Trong trường hợp thuộc tính nguyên tử, có thể nên giữ cặp getter / setter đồng bộ với 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 phần kia là mã tùy chỉnh.
Nikolai Ruhe

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

Tôi đã truy cập chủ đề này để tìm một 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à setter một mình. Oh well,
Constantino Tsarouhas

Theo mặc định, mọi thuộc tính đều là nguyên tử và chúng ta cần làm cho chúng không biến đổi một cách rõ ràng. Các thuộc tính nguyên tử là an toàn cho luồng, vì vậy chúng tôi không thể triển khai setter và getter cho chúng vì nó sẽ thay đổi chức năng an toàn của luồng. Tôi hy vọng bạn có được lý do tại sao bạn nhận được lỗi này.
Mohd Haider

Câu trả lời:


218

Tôi đã có cùng một vấn đề và sau khi thực hiện 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 @propertycái mà bạn đã khai báo là nguyên tử (nghĩa là bằng cách bỏ qua nonatomictừ khóa), 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 đó.

Để làm cho cảnh báo đó biến mất:

Nếu bạn tuyên bố a @propertylà nguyên tử thì hãy thực hiện một trong các cách sau:

  • sử dụng @dynamichoặc;
  • sử dụng @synthesizevà giữ setter tổng hợp và getter hoặc;
  • cung cấp một triển khai thủ công của cả setter và getter (không sử dụng một trong các chỉ thị trên).

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

Cập nhật: Lưu ý về Tổng hợp tài sản

Kể từ LLVM 4.0, CLang cung cấp tổng hợp tự động cho các thuộc tính được khai báo không @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 giống nhau: Hoặc để trình biên dịch cung cấp cả getter và setter, HOẶC tự thực hiện cả hai !


Cảm ơn! "tuyên bố @property với (nonatomic)"
Nianliang

14

Bạn cần phải thực hiện getter cũng. Thí 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;
}

12

Câu hỏi này, trong số các lượt 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 khách quan", không được cập nhật với 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 cuộc gọi @property bằng phương thức của riêng bạn bằng cách viết

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

Lưu ý dấu hai chấm cho phương thức setter được cung cấp.

Tài liệu tham khảo của Apple

EDIT: Tôi không chắc chắn những thay đổi mới đối với các thuộc tính của Objective-C (hiện tại chúng thông minh hơn nhiều) 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.


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 :) đại biểu id;" 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 mình hoặc thêm thuộc tính không gây dị ứng, điều mà tôi không chắc là tôi có nên không, nếu tôi tự đặt đại biểu là 'nguyên tử', thì không có vấn đề gì về tính chất không gây dị ứng , hoặc để tôi hiểu.
David van Dugteren

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

0

Đối với những người khác đang gặp phải lỗi này không phải vì lý do OP mô tả, bạn có thể gặp vấn đề tương tự như tôi:

Bạn có một @property có cùng tên với phương thức - ().

Một cái gì đó như thế này:

@property UIView *mainView;

-(UIView *)mainView;
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.