我目前正在使用iOS 5 SDK开发我的应用程序。 我试图使一个NSString属性,然后合成它在.m文件(我已经这样做之前没有问题)。现在,我遇到了这样的问题:“语义问题:属性的合成getter遵循Cocoa命名约定,用于返回‘拥有的’对象。”

这是我的代码: . h

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

.m

@synthesize newTitle;

有人知道我该怎么补救吗? 谢谢! !


当前回答

手动编写与属性名称相同的setter可以消除此警告。

其他回答

我的猜测是,你使用的编译器版本也遵循了声明属性的内存管理规则——更具体地说,对于声明属性的访问器:

如果创建对象时使用的方法名称以“alloc”、“new”、“copy”或“mutableCopy”开头,则获得对象的所有权。

一个名为newTitle的属性在合成时产生一个名为-newTitle的方法,因此会出现警告/错误。-newTitle应该是newTitle属性的getter方法,然而命名约定规定,名称以new开头的方法将返回一个由调用者拥有的对象,而getter方法则不是这样。

你可以通过以下方法解决:

Renaming that property: @property (strong, nonatomic) NSString *theNewTitle; Keeping the property name and specifying a getter name that doesn’t begin with one of the special method name prefixes: @property (strong, nonatomic, getter=theNewTitle) NSString *newTitle; Keeping both the property name and the getter name, and telling the compiler that, even though the getter name starts with new, it belongs to the none method family as opposed to the new method family: #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 Note that even though this solution allows you to keep newTitle as both the property name and the getter name, having a method called -newTitle that doesn’t return an object owned by the caller can be confusing for other people reading your code.


为了记录,苹果已经发布了过渡到ARC的发布说明,其中他们说:

不能为属性指定以new或copy开头的名称。

他们已经被告知他们的语句不太准确:罪魁祸首是getter方法名,而不是属性名。


编辑2015年1月17日:我刚刚注意到最近提交Clang建议选项3以上(使用objc_method_family(none)),包括修复它,一般情况下,一个属性名匹配一个特殊的方法族前缀。Xcode最终可能会包含这个变化。

ARC不允许在属性名称中使用“New....”。但是你可以通过改变getter名称来使用"newTitle"。

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

以new开头的成员的名称将触发警告。将名称更改为editedTitle,警告将消失。我无法找到文档确认这一点,但通过测试能够确定,以'new'开始的成员变量加重编译器。

NS_RETURNS_NOT_RETAINED用于解决命名问题。

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

我们可以找到它的定义如下:

#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))

'ns_returns_not_retained'属性是'ns_returns_retained'的补充。当一个函数或方法似乎遵循Cocoa约定并返回一个保留的Cocoa对象时,此属性可用于指示返回的对象引用不应被视为返回给调用者的“拥有”引用。Foundation框架定义了一个宏NS_RETURNS_NOT_RETAINED,它在功能上与下面所示的宏相同。

看起来巴伐利亚的建议并不是你想做的。你所要做的就是声明一个实例变量NewTitle,然后合成属性。我们过去必须声明实例变量和属性。没有更多的。

现在,我认为正确的做法是:

.h

@interface ViewController : UIViewController

@property (nonatomic, strong) NSString *newTitle;

.m

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

属性newTitle的实例变量是合成的。你不希望你的实例变量和你的属性一样——太容易出错了。

参见示例:声明属性和合成访问器