文章目录
学学copy和mutableCopy方法
提示:以下是本篇文章正文内容,下面案例可供参考
一、copy和mutableCopy
copy方法用于复制对象的副本
即使对象本身可以被修改,copy方法也会返回一个不可修改的副本
mutableCopy方法用于复制对象的可变副本
即使对象本身是不可修改的,mutableCopy也会返回一个可以修改的副本
程序调用NSString的mutableCopy方法时,将会返回一个NSMutableString对象。
copy和mutableCopy方法返回的总是原有对象的副本,当程序对复制的副本进行修改时,原有对象不会受到影响
函数测试:
#import<Foundation/Foundation.h>
int main(){
@autoreleasepool {
NSMutableString* person=[NSMutableString stringWithString:@"娜娜"];
//使用nutableCopy函数,得到的对象可以被修改
NSMutableString* personcopy=[person mutableCopy];
[personcopy replaceCharactersInRange:NSMakeRange(0,1) withString:@"nuonuo"];
NSLog(@"person=%@",person);
NSLog(@"persοncοpy=%@",personcopy);
NSString* str=@"神奇";
//同上可被修改
NSMutableString* strCopy=[str mutableCopy];
[strCopy appendString:@"nuonuo"];
NSLog(@"%@",strCopy);
//使用copy方法,所以personCopy2不能被修改,所以下边的程序语句报错
NSMutableString* personCopy2=[person copy];
//[personCopy2 appendString:@"挪"];
}
}
当加上最下边的一句代码时,会看到如下报错:这是因为personCopy2的值时不能修改的。
二、NSCopying和NSMutableCopying协议
1.自定义类的copy和mutableCopy复制
类的接口部分
#import <Foundation/Foundation.h>
@interface Person:NSObject
@property(nonatomic, strong)NSMutableString* name;
@property(nonatomic,assign)int age;
@end
类的实现部分
#import"FK.h"
@implementation Person
@synthesize name;
@synthesize age;
@end
测试
#import<Foundation/Foundation.h>
#import"FK.h"
int main(){
@autoreleasepool {
Person* person1=[Person new];
person1.name=[NSMutableString stringWithString:@"娜娜"];
person1.age=29;
Person* person2=[person1 copy];
}
}
运行结果如下:
类的实现部分:
#import"FK.h"
@implementation Person
@synthesize name;
@synthesize age;
-(id)copyWithZone:(NSZone*)zone
{
NSLog(@"heihei");
Person* person=[[[self class]allocWithZone:zone]init];
person.name=self.name;
person.age=self.age;
return person;
}
@end
测试:
#import<Foundation/Foundation.h>
#import"FK.h"
int main(){
@autoreleasepool {
Person* person1=[Person new];
person1.name=[NSMutableString stringWithString:@"娜娜"];
person1.age=29;
Person* person2=[person1 copy];
person2.name=[NSMutableString stringWithString:@"heihei"];
person2.age=31;
NSLog(@"%@",person1.name);
NSLog(@"%d",person1.age);
NSLog(@"%@",person2.name);
NSLog(@"%d",person2.age);
}
}
2.深复制和浅复制
类的接口:
#import <Foundation/Foundation.h>
@interface Person:NSObject
@property(nonatomic, strong)NSMutableString* name;
@property(nonatomic,assign)int age;
@end
类的实现:
#import"FK.h"
@implementation Person
@synthesize name;
@synthesize age;
-(id)copyWithZone:(NSZone*)zone
{
NSLog(@"heihei");
Person* person=[[[self class]allocWithZone:zone]init];
person.name=self.name;
person.age=self.age;
return person;
}
@end
测试:
#import<Foundation/Foundation.h>
#import"FK.h"
int main(){
@autoreleasepool {
Person* person1=[Person new];
person1.name=[NSMutableString stringWithString:@"娜娜"];
person1.age=29;
Person* person2=[person1 copy];
[person2.name replaceCharactersInRange:NSMakeRange(0,1) withString:@"nuo"];
NSLog(@"%@",person2.name);
NSLog(@"%@",person1.name);
}
}
结果:
我们只是修改了person2,为什么person1也改变了?
程序创建了第一个person对象,并使用person1的指针指向它,如图:
这是我们的对象复制的代码:
person代表被复制出来的对象,此时的name只是一个指针对象,该变量中存放的只是字符串的地址,并不是字符串本身。==这样赋值的效果是让person的name属性与被复制对象的name指向同一个字符串。
此时的person1和person2分别指向老公不同的person对象。但这两个对象的name的属性都是指针。而且指向同一个NSMutableString对象。这样当我们修改其中一个对象的属性值时,另一个对象的name值也会改变
对于这种复制方式,当对象的属性是指针变量是,如果程序只是复制该指针的地址,而不是复制指针所指向的对象,这种复制方式就称为浅复制
我们修改类的实现部分:
#import"FK.h"
@implementation Person
@synthesize name;
@synthesize age;
-(id)copyWithZone:(NSZone*)zone
{
NSLog(@"heihei");
Person* person=[[[self class]allocWithZone:zone]init];
person.name=[self.name mutableCopy];
person.age=self.age;
return person;
}
@end
为什么这次两个对象的值又不一样了?
我们这次采用的复制方式为深复制,深复制本身不仅复制对象本身,而且会递归复制每隔指针类型的属性,直到两个对象没有任何共用的部分。修改类的实现部分即可实现深复制。
一般来说,深复制的实现难度大,尤其是当该对象包含大量的指针类型属性时。如果某些属性所引用的对象再次包含指针类型的属性,那么深复制会更复杂。
一般来说,Foundation框架中的大部分类都只实现了浅复制
三、setter方法的复制选项
1.什么时候使用?
前面介绍setter和getter方法时提到可以使用copy指示符。
类的接口:
#import <Foundation/Foundation.h>
@interface Item :NSObject
@property(nonatomic, copy)NSMutableString* name;
@end
类的实现:
#import"FK.h"
@implementation Item
@synthesize name;
@end
测试:
#import<Foundation/Foundation.h>
#import"FK.h"
int main(){
@autoreleasepool {
Item* item=[Item new];
item.name=[NSMutableString stringWithString:@"nuonuo"];
[item.name appendString:@"magic"];
}
}
这是代码运行结果:
这段报错提示不允许修改name的属性值,是因为程序定义name时调用了copy指示符,该指示符调用setName时,程序实际上会使用参数的副本对name实例变量赋值。
copy方法默认是复制该对象的不可变副本,虽然程序传入的是NSMutableString,但程序调用该参数的copy方法得到的是不可变副本。因此name变量仍然是不可变字符串。
四、Objective-C集合概述
OC的集合类可以用于存储多个数量不等的对象,并实现常用的数据结构。OC的集合大概可以分为NSArray,NSSet,NSDictionary三种。NSArray代表有序,可重复的集合。NSSet代表无需,不可重复的集合,NSDictionary代表具有映射关系的集合。
集合里只能保存对象,(指针变量)