OS 2.2.1 和 OS 3 之间的 Objective-C 变化?
Posted
技术标签:
【中文标题】OS 2.2.1 和 OS 3 之间的 Objective-C 变化?【英文标题】:Objective-C changes between OS 2.2.1 and OS 3? 【发布时间】:2009-06-19 18:21:11 【问题描述】:当我尝试为 OS 3 编译我的应用程序时,我遇到了以下错误:
错误:访问器类型与属性类型不匹配
错误是针对我尝试访问的属性定义如下:
NSMutableArray *myArray
@property (readonly,nonatomic) NSArray* myArray;
该属性在实现文件中为@synthesized。
这在 OS 2.2.1 中工作得很好,但在 OS 3.0 中却不行
自己编写getter方法解决了这个问题。
有人知道 OS 2.2.1 和 3.0 之间的 Objective-c 变化吗? 这些更改是否有任何文档?
API changes document 似乎没有包含有关此问题的任何内容。
编辑
当您尝试访问该属性时会发生错误,例如
NSArray *anArray = myClass.myArray;
正如我在上面提到的,我找到了一个解决方法:自己编写 getter 方法,但我真正想要的是来自苹果的某种文档,解释此更改以及与 API 无关的任何其他更改。
感谢您的帮助
【问题讨论】:
【参考方案1】:这是一个编译器错误。
虽然您没有完全指定它,但我希望您的代码如下所示:
@interface Foo : NSObject
NSMutableArray *objects;
@property (readonly, copy) NSArray *objects;
@end
@implementation Foo
@synthesize objects;
@end
不幸的是,编译器混淆了objects
属性的声明和objects
实例变量的声明。请记住,属性和实例变量在 Objective-C 中是不同的东西;属性可以由实例变量支持,但它实际上是类的公共接口的一部分。
您可以通过更改代码来解决此问题,以清楚地将实例变量的定义与属性的定义分开,例如通过为实例变量的名称添加前缀:
@interface Foo : NSObject
NSMutableArray *_objects;
@property (readonly, copy) NSArray *objects;
@end
@implementation Foo
@synthesize objects = _objects;
@end
这样编译器就不会混淆 self.objects
等表达式中的属性与实例变量(无论如何它不应该,但显然会)。
只是为了避免不可避免的反应:Apple 不为实例变量保留下划线前缀。它是为方法保留的。无论如何,如果您不喜欢下划线,请随意使用其他前缀。
【讨论】:
嗨,克里斯。实际上我确实指定了整个相关代码,而且您对只读、复制属性的建议没有任何意义,我怀疑编译器会放手。我一直感觉到她人们实际上并没有阅读这些问题,这很遗憾,因为我对这个网站兴奋了大约三天。而且您没有回答我的问题,这就是为什么它曾经有效而现在无效的原因,并指出了苹果的一些有关它的文档。 Ron,你只是有一个裸变量声明,而不是 @interface 中的 ivar 声明。此外, (readonly, copy) 将起作用并且非常合理:它表示该属性使用内存管理的“复制”样式,并且在此类中是只读的。 (子类可以覆盖它。)最后,我重申它在 iPhone OS 3.0 SDK 之前工作,并且由于编译器错误而在 iPhone OS 3.0 SDK 中不起作用。您可以自己阅读“Objective-C 2.0 编程语言”以了解该语言的行为应该是什么。 Ron,您在问题中发布的内容绝对不是您正在使用的实际代码,因为其中存在语法错误会阻止其编译(第一行需要分号)。 Chris 的猜测是唯一明智的做法,如果您正在做一些真正奇特的事情,您需要发布实际代码。 顺便说一句——相信我,克里斯知道他在说什么。 这是一个错误 (编辑: 原始答案在同行评审后被删除,发现它缺乏。请阅读 Chris Hanson 关于此事的 cmets。我把剩下的留在这里,因为我认为它仍然有效。
请注意,即使您将属性类型声明为NSArray
,返回的对象仍然是NSMutableArray
,并且为它定义了可变方法。以这种方式声明属性不会防止有人意外改变数组。
如果你想确保返回的数组不可变,你可以像原来的例子一样声明属性,然后滚动你自己的访问器:
- (NSArray *)myArray return [NSArray arrayWithArray:myArray];
请注意,这将返回未保留的NSArray
。如果对象需要持久化,则由调用者来获取对象的所有权。
【讨论】:
正如我所提到的,我确实自己编写了 getter 方法,并且成功了。谢谢 好吧,我很确定这就是答案,罗恩。 实际上这不是答案,而是一种解决方法,正如我在问题中提到的那样,我已经找到了一种解决方法。我正在寻找的是解释为什么这在 2.2.1 中有效并且不再有效,最好是记录在哪里。 @Ron Srebro:我同意你的看法。我绝对没有回答您关于在哪里可以找到文档的问题。我有一种感觉,您的原始代码(在 2.2.1 中有效)仍然会在 2.2.1 中引发警告,您可能没有注意到它,因为它不是一个全面错误(请参阅 Kendall Helmstetter Geln 的回答)。如果您的旧代码没有引发警告,我会称其为 Objective-C 的 2.2.1 实现中的错误,因为属性类型与 ivar 的类型不匹配。如果是这样,它解释了为什么没有更改文档。他们只是修复了 3.0 中的错误 @eJames:你错了,拥有类型为 (NSArray *) 的属性由类型 (NSMutableArray *) 的实例变量支持是完全有效的。这只是一个错误。【参考方案3】:您看到错误是因为 XCode 现在针对以前没有的内容发出警告和错误...
我会争辩说,做你正在做的事情最多应该是一个警告,我理解你试图将数组呈现为对外界不可变但让它在类内可变的尝试。您可能需要考虑使用不同名称的不同访问器,专门用于返回可变数组。
【讨论】:
【参考方案4】:仍然是Objective-C 2.0;考虑到这种类型会改变错误,编译器可能只是稍微更新了一点。这几乎应该是一个错误。至少它应该警告您,您可能不是故意写的。然后你可以投射一些东西让它不警告你,这是你不能用 @synthesize
语句做的。
我刚刚将您的代码和一个综合语句完全粘贴到我的控制器中,我没有收到任何错误或警告。它建得很好。现在我将基础 SDK 设置为“Simulator 3.0”,并将构建设置为“Simulator 3.0 Debug”。这个项目是在 2.2.1 SDK 开始的,我昨天刚安装了 3.0 SDK; Xcode 是 3.1.3 版本。
更新:哦,我知道实际上是在尝试设置该属性是你得到你提到的错误的地方。
self.myArray = [NSArray arrayWithObject:@"foo"];
显然你不能@synthesize
这种行为,必须编写你自己的访问器。
- (NSArray*)myArray
return [NSArray arrayWithArray:myArray];
- (void)setMyArray:(NSArray*) pMyArray
myArray = [NSMutableArray arrayWithArray:pMyArray];
填写这些访问器,并没有让消息消失,所以我不得不将访问权限更改为:
[self setMyArray:[NSArray arrayWithObject:@"foo"]];
在没有自定义访问器的情况下使用上述语法也不起作用。
PS 哇,还有其他人因为你不能复制消息气泡或构建结果窗口中的文本而烦恼吗?
【讨论】:
我对无法复制消息或文本感到非常恼火。如果有人能找到解决方案,那就太好了。无论如何,正如我所说,我的情况下的属性是只读的,因此将其表示为 NSArray 没有问题,并且当我编写自己的 getter 方法时,它可以正常工作。 构建结果窗口的水平滑块(在顶部的底部)有带有文本行的图标(在复选标记和警告标志旁边)。如果你点击它,你会得到原始的、可复制的日志。【参考方案5】:所以这实际上与 @synthesize 调用有关,它不喜欢将 NSMutableArray 公开为 NSArray - 为什么不直接实现 getMethod。
其实想想肯定是set方法不爽——你不能把一个NSArray设置成一个NSMutableArray。
【讨论】:
虽然问题可能来自@synthesize,但快速枚举调用的是getter,而不是setter,所以错误看起来还是有点不合适。 此外,该属性被标记为只读,因此实际上根本没有setter方法。 是的,我忘记了——所以问题出在@synthesized getter【参考方案6】:您的问题是:
有人知道 OS 2.2.1 和 3.0 之间的 Objective-c 变化吗?
这些更改是否有任何文档?
确定的答案是:
1) 语言规范没有有意更改,但编译器和其他开发工具发生了变化。 Chris 和他的同事是这些变化的专家。
2) 可能不会,因为任何更改都是无意的,或者是为了更好地匹配文档的行为。
您不应该这么快就将 Chris 的回答视为“猜测”而忽略。 Chris 致力于 Apple 的开发人员工具。你可能会得到另一个你更喜欢的答案,但你不会得到更专业的答案。
【讨论】:
以上是关于OS 2.2.1 和 OS 3 之间的 Objective-C 变化?的主要内容,如果未能解决你的问题,请参考以下文章