gpt4 book ai didi

objective-c - 具有读写和只读属性的 'property' 、 '_property' 、 'self.property' 和 'self._property' 之间有什么区别?

转载 作者:搜寻专家 更新时间:2023-10-30 19:56:05 26 4
gpt4 key购买 nike

我想很好地理解它,但到目前为止,我没有找到在一个地方考虑​​所有可能性的复杂答案。我知道在现代 objective-c 中,我们不会在 { } 之间的 @implementation Album 之后创建 ivars。

只是为了测试我创建了Album.h:

@interface Album : NSObject

@property (nonatomic, copy, readonly) NSString *title, *artist;
@property (nonatomic, copy) NSString *title2, *artist2;

- (id)initWithTitle:(NSString*)title;

@end

Album.m:

@implementation Album

- (id)initWithTitle:(NSString*)title {
self = [super init];
if (self) {

//READ-ONLY
title = title; //1, still nil after compile
_title = title; //2,
self.title = title; //3, "assignment to readonly property"
self._title = title; //4, "property '_title' not found"

artist = @"Shakira"; //5, "use of undeclared identifier 'artist'"
_artist = @"Shakira"; //6
self.artist = @"Shakira"; //7, "assignment to readonly property"
self._artist = @"Shakira"; //8, "property '_artist' not found"

//READ-WRITE
title2 = title; //9, "use of undeclared identifier 'title2'"
_title2 = title; //10
self.title2 = title; //11
self._title2 = title; //12, "property '_title2' not found"

artist2 = @"Shakira"; //13, "use of undeclared identifier 'artist2'"
_artist2 = @"Shakira"; //14
self.artist2 = @"Shakira"; //15
self._artist2 = @"Shakira"; //16, "property '_artist2' not found"

}
return self;
}

@end

现在我使用它:

Album *album = [[Album alloc] initWithTitle:@"Live from Paris"];

问题是:

  1. 为什么找不到 4、8、12、16 个属性,而 2、6、10、14 存在?
  2. 10 和 11 或 14 和 15 有什么区别?
  3. 我在 1 中实际做了什么?
  4. 我在哪里声明属性 2、6、10、14?
  5. 为什么我可以在 2、6 中分配只读属性,但在 3、7 中不能分配?

最佳答案

开头的一些解释

一个。 @property 声明 方法 名称为 -property 并且,如果它不是只读的,-设置属性:@property 本身没有做任何事情!

B. @property 合成一个 ivar。什么?再说一遍! @property 合成一个 ivar。 (我可以重复多次。)

Ivars 是合成的,当你使用显式的 @synthesize 或 - 这使得它有点难以理解 - 当你有自动合成时。但是仍然有一个(隐含的,未显示的)综合!

要进行隐式综合,必须满足以下条件:

  • 你需要一个@property。
  • 没有手动实现访问器。

由于您在源代码中可以看到第一个条件而看不到第二个条件,因此很容易假设@property 合成了ivar。但事实并非如此。让我们试试看:

@interface Foo : NSObject
@property NSString *foo;
@end

@implementation Foo
// Both accessors are implemented -> no auto synthesize -> no ivar
- (NSString*)foo
{
return _foo; // Error: No ivar _foo
}

- (NSString*)setFoo:(NSString*)foo
{
_foo=foo; // Error: No ivar _foo
}
@end

原因是:如果 @property 本身会合成 ivar,则不可能拥有没有 ivar 支持的已声明属性。

(此外,如果您已有合适的伊娃,则不会合成伊娃。但我们这里不需要。)

C.合成的 ivar 具有标识符 _property,而不是 property。 (在某些情况下,不带下划线的现有 ivar 将被视为已经存在的 ivar,但我们在这里也确实需要它。)

D.点符号访问ivar。它发送一条消息。如果语句是左值,则使用 setter,如果它是右值,则使用 getter。你可以简单地翻译一下:

self.property = …; // [self setProperty:…];
… = self.property; // … = [self property];

Why 4, 8, 12, 16 properties not found while 2, 6, 10, 14 exists?

在第 4 步,...您使用点表示法,使用选择器 set_Property 发送消息。没有这个方法,因为合成的方法是-setProperty:: Error

在 2,...您直接访问 ivars。它的标识符是 _property。一切都很好。

What is the difference between 10 and 11 or 14 and 15?

在第 11、15 步,您使用 setter 设置属性的值。在 10、14 直接设置 ivar。 setter的代码没有执行。

举个例子:

@interface Foo : NSObject
@property NSString *foo;
@end

@implementation Foo
// ivar _foo is (auto) synthsized, because there is no getter.
- (void)setFoo:(NSString*)foo
{
NSLog( @"Setter executed");
_foo = foo;
}
@end

在第 10、14 行你将看不到任何日志,因为没有执行 setter。在第 11、15 行,您将看到一条日志。

如果您在仅设置 ivar 的 setter(或 getter)accept 中有额外的事情要做,结果会有所不同。

What I actually do in 1?

title不是一个ivar(ivar的标识符是_title),而是一个参数var。 (看方法定义的head。)你把参数var的值赋给自己,什么意思啊。

您没有为 ivar 分配任何内容,因为您没有使用 ivar。

Where did I declare properties 2, 6, 10, 14?

参见上面的 A. 和 B.

Why I can assign to readonly properties in 2, 6 but not in 3, 7?

ivar 永远不是只读的。 readonlyreadwrite 选项用于方法声明。 (见上文 A. - C.)

在2、6中你直接设置了ivar。它不能是只读的,所以一切都很好。

在 3、7 中,您向不存在的方法发送消息,因为属性 是只读的。

关于objective-c - 具有读写和只读属性的 'property' 、 '_property' 、 'self.property' 和 'self._property' 之间有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27982615/

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