ios - 使用 "copy"property 属性来维护不可变的 NSString

标签 ios properties attributes copy

我对使用 Objective-C 进行 iOS 开发和编程非常陌生。我一直在做应用程序开发库的练习。

这是我正在尝试理解的当前练习。 3. 测试如果将可变字符串设置为人的名字会发生什么情况,然后在调用修改后的 sayHello 方法之前改变该字符串。通过添加复制属性更改 NSString 属性声明并再次测试。

然而,我尝试这样做,尽管使用了复制属性,但我修改的 NSString 实际上发生了变化。

这是我的声明和实现以及我的测试代码。

XYZPerson.h
#import <Foundation/Foundation.h>

@interface XYZPerson : NSObject

@property (copy) NSString *firstName;
@property NSString *lastName;
@property NSDate *dob;

- (void)sayHello;
- (void)saySomething:(NSString *)greeting;

+ (id)init;
+ (id)personWithFirstName:(NSString *)firstName lastName:(NSString *)lastName dob:(NSDate   *)dateOfBirth;


@end

//XYZPerson.m
#import "XYZPerson.h"

@implementation XYZPerson

@synthesize firstName = _firstName;
@synthesize lastName = _lastName;
@synthesize dob = _dob;


- (void)sayHello {
    [self saySomething:@"Hello World!"];
    NSLog(@"This is %@ %@", self.firstName, self.lastName);
}

- (void)saySomething:(NSString *)greeting {
    NSLog(@"%@", greeting);
}

+ (id)init {
    return [self personWithFirstName:@"Yorick" lastName:@"Robinson" dob:8/23/1990];
}

+ (id)personWithFirstName:(NSString *)firstName lastName:(NSString *)lastName dob:(NSDate   *)dateOfBirth{
    XYZPerson *person = [[self alloc] init];
    person.firstName = firstName;
    person.lastName = lastName;
    person.dob = dateOfBirth;

    return person;
}

@end

//Test code
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "XYZPerson.h"
#import "XYZShoutingPerson.h"


int main(int argc, char *argv[])
{
    @autoreleasepool {
        XYZPerson *guy = [XYZPerson init];
        [guy sayHello];

        //I thought that this change would never be made, but it is everytime I run the code.
        guy.firstName = @"Darryl";
        [guy sayHello];

        XYZShoutingPerson *girl = [XYZShoutingPerson init];
        [girl sayHello];
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

最佳答案

考虑这个较短的示例(顺便说一句,它在 CodeRunner 中运行):

#import <Foundation/Foundation.h>

@interface Person : NSObject
@property (nonatomic,strong) NSString *name; // strong should be copy
@end

@implementation Person
@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        Person *p = [Person new];

        NSMutableString *name = [[NSMutableString alloc] initWithString:@"Alice"];
        p.name = name;
        NSLog(@"%@",p.name); // prints Alice

        [name appendString:@"xxx"];
        NSLog(@"%@",p.name); // prints Alicexxx
    }
}

我将名称指向可变字符串,然后附加一些字符。结果,名称在对象内部发生了变化。但是,如果您在声明该属性时将 strong 替换为 copy,则会仅为 Person 对象创建一个新的不可变字符串。

这个故事的寓意是,当有人传递一个对象然后该对象发生变化时,使用复制可以防止副作用。

消息 -[NSString copy] 在传递可变字符串(NSMutableString)时生成副本,或者在不可变字符串(NSString)时保留。因此,在声明 NSString 属性时总是复制:

@property (nonatomic,copy)   NSString *string;  // OK
@property (nonatomic,strong) NSString *string;  // strong should be copy 

关于ios - 使用 "copy"property 属性来维护不可变的 NSString,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14008230/

相关文章:

javascript - 如何获取自定义 mvc3 属性以验证客户端

asp.net-mvc - MVC 中的 HttpPost 与 HttpGet 属性 : Why use HttpPost?

ios - webkit 中的 CSS 最大高度过渡双动画错误

ios - dispatch_after 会阻塞 UI 吗?

JavaScript:动态生成的对象键

iphone - 属性类型与访问器 mkmapview 的类型不匹配

c# - 在不同的命名空间中实现多个属性

c# - 限制 .NET 类型是否只能通过 ByVal 或 ByRef

ios - UIWebView 的内容背景颜色不透明

ios - Xcode 7.3.1 自动完成代码完成不起作用