1.Copy的使用
- 如何使用copy功能
- 一个对象可以调用copy或mutableCopy方法来创建一个副本对象
- copy : 创建的是不可变副本(如NSString、NSArray、NSDictionary)
- mutableCopy :创建的是可变副本(如NSMutableString、NSMutableArray、NSMutableDictionary)
- 使用copy功能的前提
- copy : 需要遵守NSCopying协议,实现copyWithZone:方法
@protocol NSCopying
- (id)copyWithZone:(NSZone *)zone;
@end
- 使用mutableCopy的前提
- 需要遵守NSMutableCopying协议,实现mutableCopyWithZone:方法
@protocol NSMutableCopying
- (id)mutableCopyWithZone:(NSZone *)zone;
@end
2.深复制和浅复制
- 浅复制(浅拷贝,指针拷贝,shallow copy)
- 源对象和副本对象是同一个对象
- 源对象(副本对象)引用计数器+1,相当于做一次retain操作
- 本质是:没有产生新的对象
NSString *srcStr = @"gx";
NSString *copyStr = [srcStr copy];
NSLog(@"src = %p, copy = %p", srcStr, copyStr);
- 深复制(深拷贝,内容拷贝,deep copy)
- 源对象和副本对象是不同的两个对象
- 源对象引用计数器不变,副本对象计数器为1(因为是新产生的)
- 本质是:产生了新的对象
NSString *srcStr = @"gx";
NSMutableString *copyStr = [srcStr mutableCopy];
NSLog(@"src = %p, copy = %p", srcStr, copyStr);
NSLog(@"src = %@, copy = %@", srcStr, copyStr);
[copyStr appendString:@" cool"];
NSLog(@"src = %@, copy = %@", srcStr, copyStr);
NSMutableString *srcStr = [NSMutableString stringWithFormat:@"gx"];
NSString *copyStr = [srcStr copy];
[srcStr appendString:@" cool"];
NSLog(@"src = %p, copy = %p", srcStr, copyStr);
NSLog(@"src = %@, copy = %@", srcStr, copyStr);
NSMutableString *srcStr = [NSMutableString stringWithFormat:@"gx"];
NSMutableString *copyStr = [srcStr mutableCopy];
[srcStr appendString:@" cool"];
[copyStr appendString:@" 520it"];
NSLog(@"src = %p, copy = %p", srcStr, copyStr);
NSLog(@"src = %@, copy = %@", srcStr, copyStr);
copy.png
- 完全深拷贝:在拷贝的时候,被拷贝对象的每一层都进行了拷贝。
copy与内存管理
1.copy与内存管理
-
浅拷贝
-
原对象引用计数器+1
-
必须对原对象进行释放
char *cstr = "this is a c string"; NSString *str1 = [[NSString alloc] initWithUTF8String:cstr]; NSLog(@"str = %lu", [str1 retainCount]); NSString *str2 = [str1 copy]; NSLog(@"str = %lu", [str1 retainCount]); [str2 release];//必须做一次release
-
-
深拷贝
-
必须释放新对象
char *cstr = "this is a c string"; NSString *str1 = [[NSString alloc] initWithUTF8String:cstr]; NSLog(@"str = %lu", [str1 retainCount]); NSMutableString *str2 = [str1 mutableCopy]; NSLog(@"str = %lu", [str1 retainCount]); [str2 release]; // 必须做一次release
-
@property中的copy关键字
1.@property中的copy的作用
- 防止外界修改内部的值
@interface Person : NSObject
@property (nonatomic, retain) NSString *name;
@end
NSMutableString *str = [NSMutableString stringWithFormat:@"gx"];
Person *p = [[Person alloc] init];
p.name = str;
// person中的属性会被修改
[str appendString:@" cool"];
NSLog(@"name = %@", p.name);
-
防止访问对象对象已经释放
-
不用copy情况
Person *p = [[Person alloc] init]; p.name = @"gx"; Dog *d = [[Dog alloc] init]; d.age = 10; NSLog(@"retainCount = %lu", [d retainCount]); // 1 p.pBlock = ^{ // 报错, 调用之前就销毁了 NSLog(@"age = %d", d.age); }; [d release]; // 0 p.pBlock(); [p release];
-
用copy情况
Person *p = [[Person alloc] init]; p.name = @"gx"; Dog *d = [[Dog alloc] init]; d.age = 10; NSLog(@"retainCount = %lu", [d retainCount]); // 1 p.pBlock = ^{ // 会对使用到的外界对象进行一次retain NSLog(@"age = %d", d.age); NSLog(@"retainCount = %lu", [d retainCount]); // 1 }; [d release]; // 1 p.pBlock(); [p release];
-
2.@property内存管理策略选择
- 非ARC
- 1> copy : 只用于NSString\block
- 2> retain : 除NSString\block以外的OC对象
- 3> assign :基本数据类型、枚举、结构体(非OC对象),当2个对象相互引用,一端用retain,一端用assign
- ARC
- 1> copy : 只用于NSString\block
- 2> strong : 除NSString\block以外的OC对象
- 3> weak : 当2个对象相互引用,一端用strong,一端用weak
- 4> assgin : 基本数据类型、枚举、结构体(非OC对象)
自定义的类实现copy操作
1.自定义类实现copy操作
-
让类遵守NSCopying协议
-
实现 copyWithZone:方法,在该方法中返回一个对象的副本即可。
-
在copyWithZone方法中,创建一个新的对象,并设置该对象的数据与现有对象一致, 并返回该对象.
zone: 表示空间,分配对象是需要内存空间的,如果指定了zone,就可以指定 新建对象对应的内存空间。但是:zone是一个非常古老的技术,为了避免在堆中出现内存碎片而使用的。在今天的开发中,zone几乎可以忽略
-
无父类实现
-(id)copyWithZone(NSZone *)zone{
CustomMode *custom = [[[self class] copyWithZone:zone] init];
Custom ->_a = [_a copyWithZone:zone];
Custom -> _c = _c;//不是对象的 直接赋值
Return custom;
}
-
有父类实现
- 不调用父类方法, 无法拷贝父类中继承的属性
-
不重写父类copyWithZone, 无法拷贝本来中的特有属性
-(id)copyWithZone(NSZone *)zone{
CustomModel *custom = [super copyWithZone:zone];
….//添加子类属性
Return custom;
}
单例设计模式
1.单例模式概念
- 什么是单例模式:(Singleton)
- 单例模式的意图是是的类的对象成为系统中唯一的实例,供一个访问点,供客户类 共享资源。
- 什么情况下使用单例?
- 1、类只能有一个实例,而且必须从一个为人熟知的访问点对其进行访问,比如工厂方 法。
- 2、这个唯一的实例只能通过子类化进行扩展,而且扩展的对象不会破坏客户端代码。
- 单例设计模式的要点:
- 某个类只能有一个实例
- 2)他必须自行创建这个对象
- 3)必须自行向整个系统供这个实例;
- 4)为了保证实例的唯一性,我们必须将
- 5)这个方法必须是一个静态类
2.简单的单例模式实现
#define interfaceSingleton(name) +(instancetype)share##name
#if __has_feature(objc_arc)
// ARC
#define implementationSingleton(name) \
+ (instancetype)share##name \
{ \
name *instance = [[self alloc] init]; \
return instance; \
} \
static name *_instance = nil; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [[super allocWithZone:zone] init]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone{ \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return _instance; \
}
#else
// MRC
#define implementationSingleton(name) \
+ (instancetype)share##name \
{ \
name *instance = [[self alloc] init]; \
return instance; \
} \
static name *_instance = nil; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [[super allocWithZone:zone] init]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone{ \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return _instance; \
} \
- (oneway void)release \
{ \
} \
- (instancetype)retain \
{ \
return _instance; \
} \
- (NSUInteger)retainCount \
{ \
return MAXFLOAT; \
}
#endif
网友评论