7

当我尝试为 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 更改文档似乎没有包含有关此问题的任何内容。

编辑

当您尝试访问该属性时发生错误,例如

NSArray *anArray = myClass.myArray;

正如我上面提到的,我找到了一个解决方法:自己编写 getter 方法,但我真正想要的是来自苹果的某种文档,解释这个变化和任何其他与 API 无关的变化。

谢谢你的帮助

4

6 回答 6

17

这是一个编译器错误。

尽管您没有完全指定它,但我希望您的代码如下所示:

@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不会为实例变量保留下划线前缀。它是为方法保留的。无论如何,如果您不喜欢下划线,请随意使用另一个前缀。

于 2009-06-23T08:28:30.967 回答
5

编辑:原始答案在同行评审后被删除,发现它缺乏。请阅读 Chris Hanson 对此事的评论。我把剩下的留在这里,因为我认为它仍然有效。


请注意,即使您将属性类型声明为NSArray,返回的对象仍然是,并且它定义NSMutableArray了可变方法。以这种方式声明属性并不能防止某人意外地改变数组。

如果您想确保返回的数组不可变,您可以像在原始示例中一样声明该属性,然后滚动您自己的访问器:

- (NSArray *)myArray { return [NSArray arrayWithArray:myArray]; }

请注意,这将返回一个未保留的NSArray. 如果对象需要持久化,则由调用者来获取对象的所有权。

于 2009-06-19T18:51:23.407 回答
4

您看到错误是因为 XCode 现在针对以前没有的内容发出警告和错误...

我会争辩说,做你正在做的事情最多应该是一个警告,我理解你试图将数组呈现为对外部世界不可变但让它在类中可变的尝试。您可能需要考虑使用不同名称的不同访问器,专门用于返回可变数组。

于 2009-06-19T18:54:30.250 回答
1

它仍然是 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 哇,还有其他人对您既不能复制消息气泡或构建结果窗口中的文本感到恼火吗?

于 2009-06-19T21:35:27.573 回答
0

所以这真的与@synthesize 调用有关,它不喜欢将 NSMutableArray 公开为 NSArray - 为什么不直接实现 getMethod。

实际上考虑它一定是不高兴的 set 方法 - 你将无法将 NSArray 设置为 NSMutableArray。

于 2009-06-19T19:05:25.270 回答
0

你的问题是:

有人知道 OS 2.2.1 和 3.0 之间的 Objective-c 的变化吗?

这些更改是否有任何文档?

确定的答案是:

1) 语言规范没有有意更改,但编译器和其他开发工具发生了变化。克里斯和他的同事是这些变化的专家。

2) 可能不是,因为任何更改都是无意的,或者是为了更好地匹配文档的行为。

您不应该这么快就将克里斯的回答视为“猜测”。Chris 致力于 Apple 的开发人员工具。你可能会得到另一个你更喜欢的答案,但你不会得到更专业的答案。

于 2009-06-28T08:58:57.600 回答