来自另一个类的 Objective-C 设置属性返回 Null
Posted
技术标签:
【中文标题】来自另一个类的 Objective-C 设置属性返回 Null【英文标题】:Objective-C Set Property from Another Class Returns Null 【发布时间】:2021-01-21 06:08:35 【问题描述】:我正在尝试从我的int main()
以不同的方式在XYZPerson
中初始化属性firstName
和lastName
。 (我正在学习 OC 并探索不同的初始化值的方法)
但是,NSLog
始终为 firstName
返回 null
。我知道有很多与我类似的问题,但几乎所有问题都倾向于特定问题,而不是语言语法本身。
#import <Foundation/Foundation.h>
#import "XYZShoutingPerson.h"
int main(int argc, const char * argv[])
@autoreleasepool
XYZPerson *somePerson = [[XYZPerson alloc] init];
NSString *firstName = [somePerson firstName];
[somePerson setFirstName:@"Jonny"];
[somePerson setLastName:@"Appleseed"];
NSLog(@"%@ %@", firstName, [somePerson lastName]); // prints ```(null) Appleseed```
return 0;
@interface XYZPerson : NSObject
@property NSString *firstName;
@property NSString *lastName;
- (id)init;
- (id)initWithFirstName:(NSString *)aFirstName lastName:(NSString *)aLastName;
- (void)saySomething:(NSString *)greeting;
@end
我刚刚开始学习 Objective-C。我知道这很可能是一个非常愚蠢的错误,所以请不要对我太苛刻......谢谢!
【问题讨论】:
您访问firstName
属性并将其存储在一个局部变量中,然后再设置该属性。所以firstName
局部变量是null
。
是的,成功了!但我想知道为什么在设置它不起作用之前将它存储为本地属性? firstName
指向的地址不还是一样吗?
【参考方案1】:
是的,成功了!但我想知道为什么在设置它之前将它存储为本地属性不起作用?
firstName
指向的地址不还是一样吗?
确实如此,这就是您的代码不起作用的原因...
接下来的几轮是一些优势,但希望能够让概念得到理解。
让我们从属性退一步,看看变量,你拥有的属性只是变量,它们周围有一些代码,对这里发生的事情没有影响。
变量只是一个命名的框,而该框能够存储具有特定类型的东西的(计算机)表示,也就是值 。例如声明:
int height;
是使用可用[1] 框的指令,该框能够保存类型为int
的事物的表示,并将该框命名为height
。
当你给一个变量赋值时,盒子里已经存在的东西都会被扔掉[2],然后被赋值的值的副本放在盒子里。
当您从变量中读取时,将生成框中内容的副本并返回给您。
现在不管box中存储的是什么类型的值,以上描述的过程依然成立。
在您的情况下,存储在您的盒子中的是 NSString *
类型的值,这是一个 reference 或 pointer 指向代表(以计算机的任何方式这样做)一个字符串,本质上,引用是字符串的表示。
现在考虑分配:
height = 42;
这总是将42
的表示分配给名为height
的变量/框——一个整数文字总是表示相同的值[3]。
字符串文字也是如此,所以文字@"Jonny"
总是代表字符串“Jonny”。
现在让我们看一下您的代码,并根据(底层)变量(属性只是包装器)描述它在做什么:
NSString *firstName = [somePerson firstName];
将somePerson
的firstName
变量中的当前值复制到局部变量firstName
中。根据您此时在代码中报告的内容somePerson
的firstName
包含null
的表示,因此这就是被复制的内容。
[somePerson setFirstName:@"Jonny"];
将@"Jonny"
的表示复制到somePerson
的firstName
变量中,丢弃已经存在的任何东西——在你的情况下是null
的表示
[somePerson setLastName:@"Appleseed"];
将@"Appleseed"
的表示复制到somePerson
的lastName
变量中
NSLog(@"%@ %@", firstName, [somePerson lastName]);
复制局部变量 firstName
(null
的表示)和 somePerson
的 lastName
(@"Appleseed"
的表示)中的表示形式,并将它们传递给 NSLog
以转换为可打印的文本和输出。
您的误解可能源于听说NSMutableString
类型。其中之一由一个框表示,其内容可以修改(也称为“变异”),而不是简单地替换。 NSMutableString
的表示是对其框的引用/指针,就像 NSString
一样,但在这种情况下,框内的内容可以修改,而引用/指针将与框的名称保持相同本身不会改变。
希望能帮到你,而不是让你感到困惑! (使用图片/白板更容易解释。)
[1] 计算机如何找到可用的盒子很有趣,但在这里并不重要。
[2] “扔掉”可能涉及很多,当你学习时你会发现母马,有一种叫做“垃圾收集”的东西,你会在 Objective-C 中的“ARC”一词下找到它。但同样,这对你的问题并不重要......
[3] 那些年长的/有足够知识了解 FORTRAN 早期的那些希望在这一点上大声说“啊,但是……”的人站在角落里 ;-)
【讨论】:
感谢详细的解释!如果我没记错的话,firstName
只是一个指向复制值的指针:null
,而不是它复制的值:[somePerson firstName]
。因此,firstName
的值保持不变,尽管对其数据源进行了更改。
不完全是,firstName
包含 somePerson
的 firstName
中引用的副本 - 字符串值本身不会被复制,只是对其的引用。然后设置属性时,会将不同的引用复制到其中,并且此副本不会影响firstName
的内容。 HTH以上是关于来自另一个类的 Objective-C 设置属性返回 Null的主要内容,如果未能解决你的问题,请参考以下文章