Objective-C如何声明类别的私有财产?

Posted

技术标签:

【中文标题】Objective-C如何声明类别的私有财产?【英文标题】:objective-C how to declare private property for category? 【发布时间】:2014-10-19 01:13:32 【问题描述】:

我是 Objective-C 的新手,如果在某处重复,我深表歉意。我有一个类别(?),类似于:

SomeClass.h内:

@interface SomeClass (SomeCategory) <SomeDelegate>
@property (nonatomic, retain) id somePublicProperty;
@property (nonatomic, retain) id someProperty; // <-- i want to move this to "private"
@end

现在在我的SomeClass.m 中,我只有:

@implementation SomeClass (SomeCategory)

// dynamic setters/getters here for someProperty.

@end

我认为someProperty 是公开的。我如何使这个“私人”? (换句话说,我如何在语法上把它放在.m 文件中?我尝试使用

@interface SomeClass (SomeCategory) 
    @property (nonatomic, retain) somePrivateProperty;
 
@end

但它只是抱怨我有重复的类别定义。我该如何正确地做到这一点?

【问题讨论】:

【参考方案1】:

在您的.h 文件中,您不应提供类别。只需使用:

@interface SomeClass : SomeBaseClass < SomeDelegate>
    @property (nonatomic, retain) id somePublicProperty;
@end

在您的 .m 文件中,在 class extension 中定义您的私有属性:

@interface SomeClass ()
    @property (nonatomic, retain) id somePrivateProperty;
@end

类扩展与类扩展不同,因为它允许您扩展接口以及为类添加新存储。

在一个类类别中,you can define new properties, but no storage will be allocated for it,所以你必须手动完成:

@interface SomeClass (SomeBaseCategory)
    @property (nonatomic, retain) id somePrivateProperty;
@end

@implementation SomeClass 
    id _somePrivateProperty;


    - (void)setSomePrivateProperty:(id)property 

        _somePrivateProperty = property;
    

    - (id)somePrivateProperty 
         return _somePrivateProperty;
    

@end

否则你的应用会崩溃。

无论如何,请记住,鉴于 Objective-C 的动态特性,您的属性永远不会完全私有,因为您始终可以通过 objc_msgsend 向 Objective-C 对象发送消息,从而设置或读取属性值。

编辑:

如果您没有类实现的源代码,则无法定义类扩展(根据上面链接的源代码)。

在这种情况下,you could use object association to define properties。

【讨论】:

这不会使属性私有化。如果你想要一个私有属性,m 文件中的一个类别是要走的路 嗯...所以在我的代码中,SomeClassUIWindow。每当我尝试按照您的建议进行操作时,我都会收到“UIWindow 类的重复接口定义”。我该如何避免这种情况? 您无法为没有源代码的类创建类扩展。我链接的文档中也说明了这一点。检查我的编辑以获取替代方法。 啊。说得通。谢谢+1【参考方案2】:

只需在 .m 文件中的实现块之外添加类别定义

像这样:

@interface MyClass (MyCategory)
@property (assign) BOOL myPrivateProperty;
@end

@implementation MyClass
...
@end

【讨论】:

塞尔吉奥,你是对的。我进行了编辑,使其成为一个类别。看起来大卫只是想要一个私有属性......所以它是类扩展还是命名类别并不重要,只要它在 m 文件中 我已经尝试过了,但我收到警告:“接口SomeClass 上的类别SomeCategory 的重复定义”。我该如何避免这种情况? @DavidT。只需使用不同的类别名称——例如SomeCategoryUnpublished。无论如何,这些名称不用于其他任何用途。 这不是类扩展。它是一个类别;类扩展名是@interface MyClass ()【参考方案3】:

类别最适合用于向您不拥有且无法更改的代码添加功能。通过类别添加属性并非不可能,但要困难得多。

类扩展最适合用于保留对象所需的属性,但不打算公开。

如果您确实需要向该对象添加属性,则可以使用 Objective-C 运行时的关联对象

有一篇关于何时/如何使用它们的精彩文章here

【讨论】:

以上是关于Objective-C如何声明类别的私有财产?的主要内容,如果未能解决你的问题,请参考以下文章

数据隐藏和 Objective-C 合成器 [重复]

如何在命名类别中声明私有属性?

是否可以在 Objective-C 中创建私有属性?

Xcode:声明它抱怨的私有@property(Objective-C)

是否可以在 Objective-C 中将方法声明为私有?

什么是开放式财产?为什么我不能将其设置为私有?