来自另一个类的 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 中初始化属性firstNamelastName。 (我正在学习 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 * 类型的值,这是一个 referencepointer 指向代表(以计算机的任何方式这样做)一个字符串,本质上,引用字符串的表示。

现在考虑分配:

height = 42;

这总是将42 的表示分配给名为height 的变量/框——一个整数文字总是表示相同的值[3]。

字符串文字也是如此,所以文字@"Jonny"总是代表字符串“Jonny”。

现在让我们看一下您的代码,并根据(底层)变量(属性只是包装器)描述它在做什么:

NSString *firstName = [somePerson firstName];

somePersonfirstName变量中的当前值复制到局部变量firstName中。根据您此时在代码中报告的内容somePersonfirstName 包含null 的表示,因此这就是被复制的内容。

[somePerson setFirstName:@"Jonny"];

@"Jonny" 的表示复制到somePersonfirstName 变量中,丢弃已经存在的任何东西——在你的情况下是null 的表示

[somePerson setLastName:@"Appleseed"];

@"Appleseed"的表示复制到somePersonlastName变量中

NSLog(@"%@ %@", firstName, [somePerson lastName]);

复制局部变量 firstNamenull 的表示)和 somePersonlastName@"Appleseed" 的表示)中的表示形式,并将它们传递给 NSLog 以转换为可打印的文本和输出。

您的误解可能源于听说NSMutableString 类型。其中之一由一个框表示,其内容可以修改(也称为“变异”),而不是简单地替换NSMutableString 的表示是对其框的引用/指针,就像 NSString 一样,但在这种情况下,框内的内容可以修改,而引用/指针将与框的名称保持相同本身不会改变。

希望能帮到你,而不是让你感到困惑! (使用图片/白板更容易解释。)


[1] 计算机如何找到可用的盒子很有趣,但在这里并不重要。

[2] “扔掉”可能涉及很多,当你学习时你会发现母马,有一种叫做“垃圾收集”的东西,你会在 Objective-C 中的“ARC”一词下找到它。但同样,这对你的问题并不重要......

[3] 那些年长的/有足够知识了解 FORTRAN 早期的那些希望在这一点上大声说“啊,但是……”的人站在角落里 ;-)

【讨论】:

感谢详细的解释!如果我没记错的话,firstName 只是一个指向复制值的指针:null,而不是它复制的值:[somePerson firstName]。因此,firstName 的值保持不变,尽管对其数据源进行了更改。 不完全是,firstName 包含 somePersonfirstName 中引用的副本 - 字符串值本身不会被复制,只是对其的引用。然后设置属性时,会将不同的引用复制到其中,并且此副本不会影响firstName 的内容。 HTH

以上是关于来自另一个类的 Objective-C 设置属性返回 Null的主要内容,如果未能解决你的问题,请参考以下文章

Objective-C:访问另一个类的属性

IOS/objective-c/core-data:如何从相关实体获取属性

来自另一个域类的属性的 Grails 自定义验证器

在另一个类objective-c中保存一个类的实例

Objective-C属性和综合逻辑

带有指针的属性与objective-c中的属性之间的差异