Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective-C/Cocoa:如何设置只读属性的值?_Objective C_Cocoa_Properties - Fatal编程技术网

Objective-C/Cocoa:如何设置只读属性的值?

Objective-C/Cocoa:如何设置只读属性的值?,objective-c,cocoa,properties,Objective C,Cocoa,Properties,我发现有些对象是这样定义的:外部对象以某种方式设置只读属性。例如,在: // skview is an instance of SKView // skscene is an instance of SKScene [skview presentScene:skscene] skscene的“视图”属性(只读)设置为skview 如果属性skview.view是只读的,这怎么可能呢?如何在自定义对象中实现此行为 谢谢 如果在.h文件中声明属性并将其设置为readonly,则可以在.m文件(在c

我发现有些对象是这样定义的:外部对象以某种方式设置只读属性。例如,在:

// skview is an instance of SKView
// skscene is an instance of SKScene
[skview presentScene:skscene]
skscene的“视图”属性(只读)设置为skview

如果属性skview.view是只读的,这怎么可能呢?如何在自定义对象中实现此行为


谢谢

如果在.h文件中声明属性并将其设置为
readonly
,则可以在.m文件(在continuation类别中)中将其重新声明为
readwrite
,以便直接编辑该值

但这只是一种干净的做事方式。您还可以使用KVC作为它的后门,只需调用
setValue:forKey:
,它就可以绕过您可能已经做过的任何好事情来指定您想要公开的内容

查看KVC将如何满足您的请求的描述


然后,如果您真的感到绝望,可以使用Obj-C运行时直接访问底层实例变量。

如果您希望外部项目设置此属性,则需要声明一个setter。例如,在.h文件中:

@property (readonly) NSString *mySpecialString;

-(void)setMySpecialString:(NSString*)string;
然后,您需要在.m文件中编写实现,并且您可以在分配任务时将任何其他希望发生的操作也放在其中。但是,在这种情况下,将此属性设置为只读没有意义,因为您可以读取和写入它


使用只读属性的一种方法是使它们对外部类可读,然后修改.m文件中相应的IVAR,以便它们被私下写入

理解这一点的关键是认识到“接口”和“实现”之间的根本区别

@interface定义了特定对象想要呈现的公共可见面。对于外部世界,它可以声明“此值是只读的,您不能更改它”

但是,在内部,实现可以自由地使其读写,直接访问接口公开的备份存储,或者将只读属性实现为计算,这并不表示简单变量

例如,假设有一个名为“firstSubview”的属性,该只读属性将通过检索所有子视图的列表来实现,然后返回数组中的第一个(如果没有子视图,则返回nil)。使此属性可写将毫无意义

记住,@实现可以重新定义要读写的属性,可以创建自己的私有属性(和支持变量),等等


可以认为.h文件的内容主要针对除实际实现的.m之外的所有人。但是在.m文件中声明属性会授予对.m文件中的setter的访问权,而不是对外部对象的访问权。在我的示例中,我认为SKView对象无法看到SKScene的.m文件中声明的属性,对吗?SKView只在SKScene的.h中看到只读属性,对吗?从技术上讲,一切都是以某种方式可用的。让编译器开心只是其中的一部分。如果您在另一个类上声明了一个类别并在其中添加了一个方法,编译器会很高兴。重要的是什么在运行时起作用,这几乎是你想要的任何访问…我相信你不理解这个问题。在我所指的示例中,SKScene的“view”只读属性是由外部SKView对象而不是SKScene对象本身从外部修改的。如果您阅读了SKScene的文档,就会发现没有任何公共方法可以让您知道必须更改其“视图”的SKScene对象属性,因为它已添加到SKView。您无法看到允许您在公共API中设置视图的访问器这一事实并不意味着SceneKit中没有提供该访问的私有类别。当您调用-[SKView presentScene:]时,框架很可能使用私有API来管理您引用的信息。我重复我之前的断言-@接口只需要公开允许您使用的公共API。框架不需要向您公开其所有内部工作。谢谢,但您仍然不理解我的问题:我不是在要求解释发生了什么,因为我已经知道这一点。我想问的是如何实现它。在SKView中,您可以在SKScene上声明一个类别,将属性从readonly提升到readwrite(假设该属性实际上是通过后备存储实现的)。我已经用很多框架类完成了这项工作。有一个“framework private.h”文件,该文件导入到所有公开无人支持的“内部API”的实现中。框架内的类共享秘密知识,但这没关系。这真的很简单,一旦您了解@接口可以分布在许多文件中,包括.mOf课程中的硬编码,您就不能仅仅“声明一个属性为readwrite”,并希望管道已经准备好——您的框架源代码都必须以合作的方式编写。但是您的内部头可以公开比公共头更丰富的API。当然,这里要注意的另一件事是,你不知道“视图”是否真的是一个“简单属性”。从外部很难区分从备份存储返回值的属性和返回计算结果的属性。