Objective-c之NSCopying
copy的原理:
执行<NSCopying>协议,类中必须实现copyWithZone:方法响应的copy消息。
copy消息将发送copyWithZone:这个消息给你的类,它的参数是nil。
copyWithZone:返回一个不可改变的copy
*MyPoint.h*/#import<Foundation/Foundation.h>@interfaceMyPoint:NSObject<NSCopying>//继承超类{intx;inty;};//set方法-(void)setMyPoint:(int)xandY:(int)y;//get方法-(int)getX;-(int)getY;@end
[cpp]view plaincopy /*MyPoint.m*/#import"MyPoint.h"@implementationMyPoint-(void)setMyPoint:(int)_xandY:(int)_y{//要对传进来的x和y进行判断if(_x<0){x=1;}if(_y<0){y=1;}x=_x;y=_y;}-(int)getX{returnx;}-(int)getY{returny;}//copy/*zone参数处理不同的你alloc出来的内存区域,如果你写的应用程序alloc了大量的内存,并且你又想优化你的内存区域。你可以给copywithzone传值,调用allocwithzone来alloc内存:这个方法可以在指定的区域alloc内存*/-(id)copyWithZone:(NSZone*)zone//创建一个复制的接收器,储存zone{MyPoint*newPoint=[[MyPointallocWithZone:zone]init];[newPointsetMyPoint:xandY:y];returnnewPoint;}/*NSZone是苹果系统对内存分配和释放的优化方式。NSZone不是一个对象;它是一个C结构,用于纪录关于内存处理(管理)一系列对象的信息在这里它处理了zone这个传进来的对象的信息*/@end
[cpp]view plaincopy #import<Foundation/Foundation.h>#import"MyPoint.h"intmain(intargc,constchar*argv[]){MyPoint*point1=[[MyPointalloc]init];//创建myPoint对象,alloc是分配内存空间,init是初始化[point1setMyPoint:2andY:3];//调用对象point1的方法NSLog(@"x=%i",[point1getX]);//[point1getX]调用get方法NSLog(@"y=%i",[point1getY]);MyPoint*point2=[point1copy];//实现复制构造[point2setMyPoint:5andY:5];NSLog(@"x=%i",[point2getX]);NSLog(@"y=%i",[point2getY]);[point1release];//release是释放分配的内存空间[point2release];return0;}
ios拷贝小议
1.copy vs mutableCopy
copy,对于不可变的对象,简单的指向其内存.对于可变对象,复制内存内容到新的内存中并把新的内存值赋值给左值.
mutableCopy,始终复制到新的内存中,以一个可变的类型赋值给左值.
2.copy vc retain
retain,引用计数+1,内存地址赋值给左值.
copy,对于不可变对象的,相当于retain;对于可变对象,则是深拷贝赋值.
举例:
NSString* a = [NSString stringWithFormat:@"%@",@"this is a"];
NSString* b = [a copy];
NSString* bb = [a retain];
NSString* cc = [a mutableCopy];//实际上cc应该是NSMutableString类型
NSLog(@"%d,%d,%d,%d",[a retainCount],[b retainCount],[bb retainCount],[cc retainCount]);
//输出3,3,3,1
NSMutableString* a = [NSMutableString stringWithFormat:@"%@",@"this is a"];
NSString* b = [a copy];//不可变的b
NSString* bb = [a retain];//实际类型是NSMutableString的bb
NSString* cc = [a mutableCopy];//同上
NSLog(@"%d,%d,%d,%d",[a retainCount],[b retainCount],[bb retainCount],[cc retainCount]);
//输出2,1,2,1
3.一些问题
通过上面2点,思考下面的问题
我们通常如果这样定义一个变量
@property(nonatomic,copy) NSMutableString* mString;
然后这样使用
@synthesize mString;
NSMutableString* a = [NSMutableString stringWithFormat:@"%@",@"this is a"];
self.mString = a;
[mString insertString:@"m-" atIndex:0];
能通过么?当然不能,赋值后的mString是NSString类型的,不可变.如果需要可以改变就需要自己定义属性函数.
-(void)setMString:(NSMutableString *)m
{
mString = [m mutableCopy];
}
-(NSMutableString *)mString
{
return mString;
}
(当然,NSMutableString不是线程安全的,一般都建议私有之:@private;或者一定要用的话以NSString作为对外接口类型)
4.NSCopying NSMutableCopying NSCopyObjective()
NSCopying就是复制一个对象
NSMutableCopying就是深拷贝一个对象,让两个对象的改变互不影响
(其实上面着两个完全看你怎么写啦)
NSCopyObject(self,0,zone)就是简单的赋值=
(在涉及到ns对象的时候,NSCopyObject不建议使用)
注意看下面一个例子:
@interface ClassB : NSObject <NSCopying>{
NSString* stringB;
}
@property(nonatomic,copy) NSString* stringB;
@end
-(id)copyWithZone:(NSZone *)zone
{
ClassB *b = NSCopyObject(self, 0, zone);
// 使用NSCopyObject时的正确赋值方法,因为没有涉及到原来的内存指针什么事
b->stringB = @"what";
// 看看被注释的这个错误方法,由于setter方法的特性,原来的stringB指向的内存的retainCount减一
// 而由于NSCopyObject的特性,两者又是指向同一个地址的,所以,原类中stirngB指向的地址已经释放了,之后你dealloc中在释放一次?!.就出错啦
// b.stringB = @"what";
return b;
}
ios拷贝小议-10-13 10:44:45 我来说两句 收藏我要投稿
1.copy vs mutableCopy
copy,对于不可变的对象,简单的指向其内存.对于可变对象,复制内存内容到新的内存中并把新的内存值赋值给左值.
mutableCopy,始终复制到新的内存中,以一个可变的类型赋值给左值.
2.copy vc retain
retain,引用计数+1,内存地址赋值给左值.
copy,对于不可变对象的,相当于retain;对于可变对象,则是深拷贝赋值.
举例:
NSString* a = [NSString stringWithFormat:@"%@",@"thisis a"]; NSString* b = [a copy]; NSString* bb = [a retain]; NSString* cc = [a mutableCopy];//实际上cc应该是NSMutableString类型 NSLog(@"%d,%d,%d,%d",[a retainCount],[b retainCount],[bb retainCount],[cc retainCount]);//输出3,3,3,1 NSMutableString* a = [NSMutableString stringWithFormat:@"%@",@"thisis a"]; NSString* b = [a copy];//不可变的b NSString* bb = [a retain];//实际类型是NSMutableString的bb NSString* cc = [a mutableCopy];//同上 NSLog(@"%d,%d,%d,%d",[a retainCount],[b retainCount],[bb retainCount],[cc retainCount]);//输出2,1,2,1
3.一些问题
通过上面2点,思考下面的问题
我们通常如果这样定义一个变量
@property(nonatomic,copy) NSMutableString* mString;然后这样使用
@synthesize mString;NSMutableString* a = [NSMutableString stringWithFormat:@"%@",@"thisis a"];self.mString = a;[mString insertString:@"m-" atIndex:0];
能通过么?当然不能,赋值后的mString是NSString类型的,不可变.如果需要可以改变就需要自己定义属性函数.
-(void)setMString:(NSMutableString *)m{ mString = [m mutableCopy];}-(NSMutableString *)mString{ return mString;}(当然,NSMutableString不是线程安全的,一般都建议私有之:@private;或者一定要用的话以NSString作为对外接口类型)
4.NSCopying NSMutableCopying NSCopyObjective()
NSCopying就是复制一个对象
NSMutableCopying就是深拷贝一个对象,让两个对象的改变互不影响
(其实上面着两个完全看你怎么写啦)
NSCopyObject(self,0,zone)就是简单的赋值=
(在涉及到ns对象的时候,NSCopyObject不建议使用)
注意看下面一个例子:
@interface ClassB : NSObject <NSCopying>{ NSString* stringB;}@property(nonatomic,copy) NSString* stringB;@end-(id)copyWithZone:(NSZone *)zone{ ClassB *b = NSCopyObject(self, 0, zone);// 使用NSCopyObject时的正确赋值方法,因为没有涉及到原来的内存指针什么事 b->stringB = @"what";// 看看被注释的这个错误方法,由于setter方法的特性,原来的stringB指向的内存的retainCount减一// 而由于NSCopyObject的特性,两者又是指向同一个地址的,所以,原类中stirngB指向的地址已经释放了,之后你dealloc中在释放一次?!.就出错啦// b.stringB = @"what"; return b;}