语义问题:属性的合成getter遵循Cocoa命名约定来返回'拥有'对象

问题描述 投票:280回答:10

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

这是我的代码:.h

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

.M

@synthesize newTitle;

有没有人知道如何解决这个问题?谢谢!!

objective-c variables ios5 properties automatic-ref-counting
10个回答
601
投票

我的猜测是你正在使用的编译器版本也遵循the memory management rules来声明属性 - 更具体地说,对于声明的属性的访问器:

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

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

你可以通过以下方式解决

  1. 重命名该属性: @property (strong, nonatomic) NSString *theNewTitle;
  2. 保留属性名称并指定不以特殊方法名称前缀之一开头的getter名称: @property (strong, nonatomic, getter=theNewTitle) NSString *newTitle;
  3. 同时保存属性名称和getter名称,并告诉编译器,即使getter名称以new开头,它也属于none方法系列,而不是new方法系列: #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 请注意,即使此解决方案允许您将newTitle保留为属性名称和getter名称,但使用名为-newTitle的方法不会返回调用方拥有的对象可能会让其他人阅读您的代码时感到困惑。

为了记录,Apple发布了Transitioning to ARC Release Notes,其中声明:

您不能为属性指定以newcopy开头的名称。

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


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


-2
投票

试试这个:-

@property (nonatomic,retain) NSString *newTitle;

50
投票

Unacceptable Object Names

  • newButton
  • copyLabel
  • allocTitle

Acceptable Object Names

  • neueButton
  • mCopyLabel
  • _allocTitle

#arc #auto-synthesis#xcode-4.6.1

**编辑**

显然你也不能使用mutableCopy。


29
投票

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


7
投票

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

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

5
投票

它看起来不像Bavarious所暗示的那样是你想要做的。您要做的就是声明一个实例变量NewTitle然后合成该属性。我们以前必须声明实例变量和属性。不再。

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

。H

@interface ViewController : UIViewController

@property (nonatomic, strong) NSString *newTitle;

.M

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

合成属性newTitle的实例变量。您不希望实例变量与您的属性相同 - too easy to make mistakes

Example: Declaring Properties and Synthesizing Accessors


3
投票

在CoreData中,如果在属性中使用“new ...”(正常编译),它将随机崩溃并出现“错误访问”异常。

没有崩溃日志,显示“All Exceptions Breakpoint”的行根本无法帮助您。


2
投票

手动编写一个setter,名称与属性相同,删除了此警告。


0
投票

除了你应该/不能在你的属性名称前面使用“new”的问题之外,再说一点:尽量避免在名字前面使用“new”。 “新”取决于时间。目前它对你来说是新的,但是一段时间之后你可能想要再次实现新的东西。所以在名字中使用“new”总是很糟糕。试着这样想:在编程世界中,“新”总是在创造一些东西:一个新的事物实例。

在您要分配不同标题的情况下,当前名称为您的属性titleReplacement。

还有一件事:尝试先用动词命名函数和方法,比如setSomething或getSomething。但是在属性中首先尝试命名对象,例如heightMinimum,heightMaximum等。 - >在编码时使用检查器时,总是要查找对象。试试看。 ;-)


0
投票

NS_RETURNS_NOT_RETAINED用于解决命名问题。

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

我们可以找到它的definition如下,

#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))

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

在这里附上more details

© www.soinside.com 2019 - 2024. All rights reserved.