Vấn đề ngữ nghĩa: Trình thu thập tổng hợp của tài sản tuân theo quy ước đặt tên ca cao để trả về các đối tượng 'sở hữu'


283

Tôi hiện đang sử dụng SDK iOS 5 đang cố gắng phát triển ứng dụng của mình. Tôi đang cố gắng tạo một NSString một thuộc tính và sau đó tổng hợp nó trong tệp .m (Tôi đã làm điều này trước đây mà không gặp vấn đề gì). Bây giờ, tôi đã bắt gặp điều này: "Vấn đề ngữ nghĩa: Trình thu thập tổng hợp của tài sản tuân theo quy ước đặt tên ca cao để trả lại các đối tượng 'sở hữu'."

Đây là mã của tôi: .h

@interface ViewController : UIViewController {
     NSString *newTitle;
}
@property (strong, nonatomic) NSString *newTitle;

.m

@synthesize newTitle;

Có ai có manh mối làm thế nào tôi có thể sửa lỗi này? Cảm ơn!!


Tôi đã có một lỗi rất giống nhau "Tài sản tuân theo các quy ước đặt tên ca cao để trả lại các đối tượng 'thuộc sở hữu'" Câu trả lời dưới đây của Bavarious dường như cũng giải quyết điều này.
TMin

Câu trả lời:


606

Tôi đoán là phiên bản trình biên dịch bạn đang sử dụng tuân theo các quy tắc quản lý bộ nhớ cho các thuộc tính được khai báo - cụ thể hơn, đối với các trình truy cập thuộc tính được khai báo:

Bạn có quyền sở hữu một đối tượng nếu bạn tạo nó bằng một phương thức có tên bắt đầu bằng cách phân bổ, phân phối mới, một bản sao, hay sao chép, hoặc mutableCopy.

Một thuộc tính có tên newTitle, khi được tổng hợp, mang lại một phương thức được gọi -newTitle, do đó cảnh báo / lỗi. -newTitleđược coi là một phương thức getter cho thuộc newTitletính, tuy nhiên các quy ước đặt tên cho biết một phương thức có tên bắt đầu bằng newtrả về một đối tượng thuộc sở hữu của người gọi, không phải là trường hợp của các phương thức getter.

Bạn có thể giải quyết điều này bằng cách:

  1. Đổi tên tài sản đó:

    @property (strong, nonatomic) NSString *theNewTitle;
  2. Giữ tên thuộc tính và chỉ định tên getter không bắt đầu bằng một trong các tiền tố tên phương thức đặc biệt:

    @property (strong, nonatomic, getter=theNewTitle) NSString *newTitle;
  3. Giữ cả tên thuộc tính và tên getter và nói với trình biên dịch rằng, mặc dù tên getter bắt đầu bằng new, nó thuộc về họ nonephương thức chứ không phải là họ newphương thức:

    #ifndef __has_attribute
    #define __has_attribute(x) 0  // Compatibility with non-clang compilers
    #endif
    
    #if __has_attribute(objc_method_family)
    #define BV_OBJC_METHOD_FAMILY_NONE __attribute__((objc_method_family(none)))
    #else
    #define BV_OBJC_METHOD_FAMILY_NONE
    #endif
    
    @interface ViewController : UIViewController
    @property (strong, nonatomic) NSString *newTitle;
    - (NSString *)newTitle BV_OBJC_METHOD_FAMILY_NONE;
    @end
    

    Lưu ý rằng mặc dù giải pháp này cho phép bạn giữ newTitlecả tên thuộc tính và tên getter, nhưng có một phương thức được gọi là -newTitlekhông trả về một đối tượng thuộc sở hữu của người gọi có thể gây nhầm lẫn cho người khác đọc mã của bạn.


Đối với hồ sơ, Apple đã xuất bản Chuyển đổi sang Ghi chú phát hành ARC , trong đó họ nêu:

Bạn không thể đặt tên một thuộc tính bắt đầu bằng newhoặc copy.

Họ đã được thông báo rằng tuyên bố của họ không hoàn toàn chính xác: thủ phạm là tên phương thức getter, không phải tên thuộc tính.


Chỉnh sửa 17 tháng 1 năm 2015: Tôi vừa nhận thấy một cam kết gần đây với Clang gợi ý tùy chọn 3 ở trên (sử dụng objc_method_family(none)), bao gồm cả sửa lỗi, trong trường hợp chung trong đó tên thuộc tính khớp với một trong các tiền tố gia đình phương thức đặc biệt. Xcode có thể sẽ kết hợp thay đổi này cuối cùng.


6
Làm việc như một người đàn ông quyến rũ !! Cảm ơn!!! Để tham khảo trong tương lai - Tôi đã sử dụng "@property (mạnh, không biến đổi, getter = theNewTitle) NSString * newTitle;"
Noam

8
Câu trả lời tuyệt vời. Tôi đã có các biến có tiền tố "mới."

Tôi cũng gặp vấn đề này và nó lãng phí nhiều thời gian của tôi! Bạn thực sự là một thiên tài ~ Cảm ơn bạn!
H Lai

NS_RETURNS_NOT_RETAINEDlà những gì bạn cần, quá.
DawnSong

55

Tên đối tượng không được chấp nhận

  • nút mới
  • sao chép nhãn
  • cấp phát

Tên đối tượng được chấp nhận

  • neueButton
  • nhãn hiệu
  • _allocTitle

#arc # tự động tổng hợp # xcode-4.6.1

** BIÊN TẬP **

Rõ ràng bạn cũng không thể sử dụng mutableCopy .


1
Tôi cũng nhận thấy rằng "bản sao" không thể được sử dụng cho đến bây giờ.
Rishab

30

Tên của thành viên bắt đầu bằng mới là những gì gây ra cảnh báo. Thay đổi tên thành editTitle và cảnh báo sẽ biến mất. Tôi không thể tìm thấy tài liệu xác nhận điều này nhưng qua thử nghiệm đã có thể xác định rằng các biến thành viên bắt đầu bằng 'mới' làm nặng thêm trình biên dịch.


8

ARC không cho phép sử dụng "Mới ...." trong tên thuộc tính. nhưng bạn có thể sử dụng "newTitle" bằng cách thay đổi tên getter.

@property (nonatomic, strong, getter=theNewTitle) NSString *newTitle;

6

Nó không giống như những gì mà Bavaria đề xuất là những gì bạn muốn làm. Tất cả những gì bạn muốn làm là khai báo một biến thể hiện NewTitlevà sau đó tổng hợp thuộc tính. Chúng ta đã từng phải khai báo biến thể hiện và thuộc tính. Không còn nữa.

Bây giờ, tôi tin rằng cách làm đúng này là như sau:

.h

@interface ViewController : UIViewController

@property (nonatomic, strong) NSString *newTitle;

.m

@synthesize newTitle = _newTitle; // Use instance variable _newTitle for storage

Biến đối tượng cho thuộc tính newTitleđược tổng hợp. Bạn không muốn biến cá thể của bạn giống với tài sản của bạn - quá dễ mắc lỗi .

Xem ví dụ: Khai báo thuộc tính và tổng hợp các bộ truy cập


Điều đó phụ thuộc vào phiên bản trình biên dịch. Các phiên bản gần đây của clang phát ra cảnh báo trong trường hợp này, đó là lý do tại sao tôi đã đề cập đến phiên bản trình biên dịch trong câu trả lời của mình.

Tôi không nghĩ bạn đã giải quyết vấn đề. Đối với Xcode 9, đó là lỗi, không phải cảnh báo. NS_RETURNS_NOT_RETAINEDlà những gì bạn cần.
DawnSong

4

Trong CoreData nếu bạn sử dụng thuộc tính "mới ..." (biên dịch bình thường), nó sẽ bị sập ngẫu nhiên với ngoại lệ "truy cập xấu".

Không có nhật ký sự cố và dòng hiển thị với "Điểm dừng ngoại lệ" sẽ không giúp bạn chút nào.


3

Viết một setter bằng tay với tên giống như thuộc tính đã xóa cảnh báo này.


Trong Xcode 7.3, điều này không giúp được gì. Một lỗi vẫn xuất hiện trên dòng định nghĩa thuộc tính.
arlomedia

1

Bên cạnh vấn đề bạn không nên / không thể sử dụng "mới" trước tên tài sản của mình, hãy nói thêm một điều nữa: Cố gắng tránh "mới" trước tên nói chung. "Mới" phụ thuộc vào thời gian. Hiện tại nó là mới cho bạn, nhưng một thời gian sau bạn có thể muốn thực hiện một cái gì đó mới một lần nữa. Vì vậy, sử dụng "mới" trong tên luôn xấu. Hãy thử nghĩ theo cách này: Trong thế giới lập trình, "mới" luôn tạo ra một cái gì đó: một ví dụ mới của một cái gì đó.

Trong trường hợp của bạn khi bạn muốn gán một tiêu đề khác thì tên hiện tại của bạn title title.

Một điều nữa: Hãy thử đặt tên cho các hàm và phương thức bằng động từ trước, như setS Something hoặc getS Something. Nhưng trong các thuộc tính hãy thử đặt tên cho đối tượng trước, như heightMinimum, heightMaximum, v.v. -> khi bạn sử dụng trình kiểm tra của mình khi bạn đang mã hóa, bạn luôn tìm kiếm các đối tượng. Hãy thử nó. ;-)


1

NS_RETURNS_NOT_RETAINED được sử dụng để giải quyết vấn đề đặt tên.

@property (nonatomic, copy) NSString *newTitle NS_RETURNS_NOT_RETAINED;

Chúng ta có thể tìm thấy định nghĩa của nó như sau,

#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))

Thuộc tính 'ns_returns_not_retained' là phần bổ sung của 'ns_returns_retained'. Trong trường hợp một chức năng hoặc phương thức có thể tuân theo các quy ước về Cacao và trả về một đối tượng Cacao được giữ lại, thuộc tính này có thể được sử dụng để chỉ ra rằng tham chiếu đối tượng được trả về không nên được coi là tham chiếu "sở hữu" được trả về cho người gọi. Khung nền tảng xác định một macro NS_RETURNS_NOT_RETAINED tương đương về mặt chức năng với cái được hiển thị bên dưới.

Đính kèm thêm chi tiết tại đây.


-2

thử cái này:-

@property (nonatomic,retain) NSString *newTitle;

1
Tuy nhiên, cùng một vấn đề chính xác. FYI, dòng lỗi nằm trên dòng @synthesize.
Noam
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.