gpt4 book ai didi

objective-c - Objective-C API 中只读属性值的安全突变和使用

转载 作者:行者123 更新时间:2023-12-03 17:01:54 26 4
gpt4 key购买 nike

考虑一个 C++ API,例如 const T* foo()。这清楚地记录了 API 支持的可变性和使用:好的,我们会让您查看 T,但请不要更改它。您仍然可以改变它,但是您必须显式使用const_cast来表明您不遵循API的意图。

Objective-C API 的很大一部分是由属性声明组成的。 API 用户应该如何解释:@property(只读)T foo? (假设 T 不是不可变类型)

  • 由于 setter 不是合成的,显然 foo 并不意味着被替换
  • 但是,getter 仍然给我一个指向 foo 的指针。改变 foo 安全吗? (显然我可以)

注意:我不是在询问语言规范。我问的是 Objective-C 社区中对此类 API 的传统解释是什么。

最佳答案

matt said ,您拥有指向该对象的指针这一事实并不意味着该对象本身是可变的。 Objective-C 使用类的行为而不是指针来强制不变性。因此,一般来说,您应该看到返回的只读属性,例如 NSString 而不是 NSMutableString

我查看了 Apple 的 iOS 框架 header 来验证这一点:

grep -rn "@property.*readonly.*Mutable" /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/*.h

(Cocoa 中类名的模式是调用类的可变“版本”$PREFIXMutable$CLASSNAME:NSString/NSMutableString, NSDictionary/NSMutableDictionary.)

./System/Library/Frameworks/AVFoundation.framework/Headers/AVComposition.h:133:@property (nonatomic, readonly) NSArray<AVMutableCompositionTrack *> *tracks; ./System/Library/Frameworks/CoreData.framework/Headers/NSManagedObjectContext.h:149:@property (nonatomic, readonly, strong) NSMutableDictionary *userInfo NS_AVAILABLE(10_7, 5_0); ./System/Library/Frameworks/Foundation.framework/Headers/NSAttributedString.h:54:@property (readonly, retain) NSMutableString *mutableString; ./System/Library/Frameworks/Foundation.framework/Headers/NSExpression.h:127:@property (readonly, copy) id (^expressionBlock)(id __nullable, NSArray *, NSMutableDictionary * __nullable) NS_AVAILABLE(10_6, 4_0); ./System/Library/Frameworks/Foundation.framework/Headers/NSThread.h:24:@property (readonly, retain) NSMutableDictionary *threadDictionary; ./System/Library/Frameworks/GameplayKit.framework/Headers/GKRuleSystem.h:54:@property (nonatomic, retain, readonly) NSMutableDictionary *state; ./System/Library/Frameworks/ModelIO.framework/Headers/MDLMesh.h:137:@property (nonatomic, readonly, retain) NSMutableArray *submeshes;

只有 7 个结果,并且 NSExpression 中的结果不算在内,因为搜索找到的“Mutable”是 Block 的一个参数,实际上是属性的值。

对于其他人,我认为您会发现适当的类引用文档告诉您可以使用这些值做什么和不能做什么。

例如,documentation for threadDictionary有这样说:

You can use the returned dictionary to store thread-specific data.[...]You may define your own keys for the dictionary.

精确返回可变字典,以便您可以改变它。但是,线程对象不允许您设置它,因此它也可以在那里存储内容。

NSAttributedString.h 中的命中实际上是在 NSMutableAttributedString 类中,并且 those docs note :

The receiver tracks changes to this string and keeps its attribute mappings up to date.

由于 NSAttributedString 非常明确*只是一个与一堆属性打包在一起的 NSString,因此该类的设计直接公开了包装的字符串;可变版本也随之而来。

注释中提到了

UIButton ,因为那里有一个只读标签,其自身的属性是可修改的。又来了,the docs are explicit :

Although this property is read-only, its own properties are read/write. Use these properties primarily to configure the text of the button.

Do not use the label object to set the text color or the shadow color.

总之,Objective-C 无法在语言级别创建或强制执行可变性限制。正如您所注意到的,标记为“readonly”的属性仅意味着您无法将值设置为其他值。**并且没有与对该值进行“const_cast”的等效操作是可变的,以便您可以更改它:您最终将得到一个供应商对象一无所知的新值。

Cocoa 约定是通过使用不可变类来次要强制属性的状态。 (在某些情况下,您甚至可能会获得该类内部保留为可变的数据的不可变副本。)如果 API 为您提供了一个可变对象,您可以假设您可能会改变它,但是文档应该告诉您具体如何使用它。

<小时/>

*其 class description says :“NSAttributedString 对象管理字符串以及应用于字符串中单个字符或字符范围的关联属性集(例如,字体和字距调整)。”

**有 KVC,但这又是在框架级别,框架约定表明您这样做会遇到麻烦。

关于objective-c - Objective-C API 中只读属性值的安全突变和使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35330271/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com