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

时间:2011-06-13 07:00:41

标签: objective-c variables ios5 properties automatic-ref-counting

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

这是我的代码: .H

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

的.m

@synthesize newTitle;

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

10 个答案:

答案 0 :(得分: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且不返回调用方拥有的对象,则可以让阅读代码的其他人感到困惑。


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

      

    您无法为商家提供以newcopy开头的名称。

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


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

答案 1 :(得分:50)

不可接受的对象名称

  • newButton
  • copyLabel
  • allocTitle

可接受的对象名称

  • neueButton
  • mCopyLabel
  • _allocTitle

#arc#自动合成#xcode-4.6.1

**编辑**

显然你不能使用 mutableCopy

答案 2 :(得分:29)

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

答案 3 :(得分:7)

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

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

答案 4 :(得分:5)

看起来巴伐利亚的建议并不像你想要做的那样。您要做的只是声明一个实例变量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

答案 5 :(得分:3)

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

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

答案 6 :(得分:2)

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

答案 7 :(得分:0)

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

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

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

答案 8 :(得分: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

答案 9 :(得分:-2)

试试这个: -

@property (nonatomic,retain) NSString *newTitle;