我是Objective-C中iOS开发和编程的新手.我一直在app dev库上做练习.
这是我想要了解的当前练习.
3.测试如果将可变字符串设置为该人的名字会发生什么,然后在调用修改后的sayHello方法之前改变该字符串.通过添加copy属性更改NSString属性声明并再次测试.
我尝试这样做,但是我修改的NSString实际上改变了,尽管使用了copy属性.
这是我的声明和实现以及我的测试代码.
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 btw):
#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