8

我有类A,它公开了一种获取和设置类型对象的方法Foo。用属性的说法,我通常在接口中声明:

@property (nonatomic, strong) Foo * foo;

这(在现代 ObjC 中)生成访问器和 ivar,_foo用于存储。

如果我想在访问器中进行自定义工作,我可以自己实现其中一个或两个。但是如果我不仅想做定制工作,我实际上不想要 ivar 怎么办?换句话说,我正在用 Foo 对象做其他事情,比如将它来回传递给我组成的另一个内部对象。foo我实际上根本不需要保留存储空间A

看来我有两个选择:

  1. 声明该属性,实现两个访问器,并忽略编译器为 创建存储的事实_foo,并且永远不要使用它。
  2. 明确声明我的访问器:- (Foo *)foo- (void)setFoo:(Foo *)foo界面中,就像我在前现代 ObjC 中使用的那样。

第一个在运行时似乎不优雅,第二个在声明中似乎不优雅(我现在可能混合了属性和类似属性的访问器)。

有没有办法声明一个属性并将其作为纯粹的声明?

4

3 回答 3

9

在实现文件中使用@dynamic关键字。通常的讨论将其描述为在编译时@dynamic不创建访问器。通常没有提到的是,它也具有无所作为来为属性创建存储的效果,这正是在这种情况下所需要的。

@implementation A
@dynamic foo;

- (Foo *)foo 
{
   // get a Foo from somewhere and return it.
}

- (void)setFoo:(Foo *)foo
{
   // do something with foo
}

@end

(注意:回答了我自己的问题,因为我在写这个问题时发现了这个问题,而且看起来很有趣且不明显。)

于 2013-10-27T23:55:32.337 回答
5

如果同时覆盖 setter 和 getter,并且不使用 setter 和 getter 中的变量,则不会创建变量。

例如,如果你有一个你想要一个and属性firstNamelastName类,但也可能需要一个setterand ),而您的getter 只是串联的+并且从不使用变量,永远不会创建一个变量。getterfullNamefullNamefirstNamelastNamefullNamefullNamereturnsfirstNamelastNamefullName

这是根据Apple的官方文档。 向下滚动到“您可以实现自定义访问器方法”

于 2013-10-28T00:02:24.043 回答
2

@dynamic可能是要走的路。

但是,您也可以通过其他两种方式执行此操作:

  1. 未实现的类别

    您可以使用未实现的类别来声明属性,但不能获取后备存储:

    @interface Foo : NSObject
    @end
    
    @interface Foo (UnimplementedProperties)
    @property (strong) id bar;
    @end
    
    @implementation Foo
    @end
    

    通过不声明类别 ( @implementation Foo (UnimplementedProperties)) 的实现,将不会合成属性。

  2. 协议

    您可以在协议上声明属性,然后使您的类符合该协议。这与未实现的类别具有相同的效果:声明了方法,但不合成属性。

    @protocol FooProperties <NSObject>
    @property (strong) id bar;
    @end
    
    @interface Foo : NSObject <FooProperties>
    
    @end
    
于 2013-10-28T00:08:22.840 回答