zoukankan      html  css  js  c++  java
  • [OC Foundation框架

    一个对象使用copy或mutableCopy方法可以创建对象的副本

    1.copy
    需要实现NSCopying协议
    创建出来的是不可变副本,如NSString, NSArray, NSDictionary
     
    (1)不可变对象调用copy  (NSSring除外)
    不会产生新的对象,而是返回对象本身,相当于retain,计数器+1
    属于浅拷贝
     
    复制代码
     1         NSArray *arr1 = [NSArray arrayWithObjects:@"张三", @"李四", nil];
     2         NSLog(@"arr1.addr: %p", arr1); // 0x1002052b0
     3         NSLog(@"arr1.retainCount: %ld", arr1.retainCount); // 1
     4 
     5        
     6         NSArray *arr2 = [arr1 copy];
     7         NSLog(@"arr1.addr: %p", arr1); // 0x1002052b0
     8         NSLog(@"arr1.retainCount: %ld", arr1.retainCount); // 2  <-- 浅拷贝,相当于retain, retainCount+1
     9         NSLog(@"arr2.addr: %p", arr2); //0x1002052b0 <-- 浅拷贝,依旧指向同一个对象
    10         NSLog(@"arr2.retainCount: %ld", arr2.retainCount); // 2 <-- 浅拷贝,还是原来对象的retainCount
    复制代码
     
    (2)可变对象调用copy (NSMutableString会拷贝出一个NSString”常量对象")
    返回一个不可变对象,但是不是原来的对象,属于深拷贝
    复制代码
     1         NSMutableArray *arr1 = [NSMutableArray array];
     2         [arr1 addObject:@"123"];
     3         [arr1 addObject:@"abc"];
     4         NSLog(@"arr1.addr: %p", arr1); // 0x100204840
     5         NSLog(@"arr1.retainCount: %ld", arr1.retainCount); // 1
     6        
     7        
     8         NSMutableArray *arr2 = [arr1 copy];
     9         NSLog(@"arr1.addr: %p", arr1); // 0x100204840
    10         NSLog(@"arr1.retainCount: %ld", arr1.retainCount); // 1 <-- 深拷贝,原来的对象retainCount保持
    11         NSLog(@"arr2.addr: %p", arr2); // 0x100300000 <-- 深拷贝,开辟了新的内存空间,拷贝出来的实际对象是NSArray
    12         NSLog(@"arr2.retainCount: %ld", arr2.retainCount); // 1 <-- 深拷贝,新的对象retainCount独立
    复制代码
     
    (3)重点: NSString的特殊性
    由于使用了 @“” 进行初始化,数据存放在了常量池
     
    因为NSString指向字符串常量,系统不会收回,也不会对其作引用计数,即使我们对NSString变量如何retain或release,retainCount都是-1 (无符号最大值)
    复制代码
     1         NSString *str1 = [[NSString alloc] initWithString:@"abc"];
     2         NSLog(@"str1.addr: %p", str1); // 0x100001030
     3         NSLog(@"str1.retainCount: %ld", str1.retainCount); // -1 <-- 字符串常量存在常量池,不使用堆内存
     4        
     5         NSString *str2 = [str1 copy];
     6         NSLog(@"str1.addr: %p", str1); // 0x100001030
     7         NSLog(@"str1.retainCount: %ld", str1.retainCount); // -1 <-- 无论是copy, retain, release操作都不会改变retianCount
     8         NSLog(@"str2.addr: %p", str2); // 0x100001030 <-- 拷贝之后的变量依旧指向原来的常量
     9         NSLog(@"str2.retainCount: %ld", str2.retainCount); // -1 <-- 原来常量的retainCount
    10        
    11         [str1 retain];
    12         NSLog(@"after retain -> str1.retainCount: %ld", str1.retainCount); // -1 <-- 无论是copy, retain, release操作都不会改变retianCount
    13         [str2 release];
    14         NSLog(@"after release -> str2.retainCount: %ld", str2.retainCount); // -1 <-- 无论是copy, retain, release操作都不会改变retianCount
    复制代码
     
    要使一个NSString变量也有retainCount:
    就要是指向另外一个”NSString”对象,而不是字符串常量
    1         // 先创建出一个NSString对象,再用另一个指向
    2         NSString *str1 = [NSString stringWithFormat:@"abc"];
    3         NSLog(@"%ld", str1.retainCount); // -1
    4         NSString *str2 = [NSString stringWithString:str1];
    5         NSLog(@"%ld", str2.retainCount); // 1
     
    (4)copy出来的是不可变对象,如NSMutableString调用copy创建出来的实际是NSString
    复制代码
     1         // 这里不能使用 NSMutableString *mstr1 = @"abc", 或者在延迟赋值 mstr1 = @"abc"; 否则同样指向常量池
     2         NSMutableString *mstr1 = [[NSMutableString alloc] initWithString:@"abc"];
     3         NSLog(@"mstr1.addr: %p", mstr1); // 0x100404990
     4         NSLog(@"mstr1.retainCount: %ld", mstr1.retainCount); // 1
     5 
     6 
     7         NSMutableString *mstr2 = [mstr1 copy];
     8         NSLog(@"mstr1.addr: %p", mstr1); // 0x100404990
     9         NSLog(@"mstr1.retainCount: %ld", mstr1.retainCount); // 1 <-- 深拷贝,原来的对象retainCount保持
    10         NSLog(@"mstr2.addr: %p", mstr2); // 0x63626135 <-- 深拷贝,开辟了新的内存空间,但是指向的实际是一个字符串常量
    11         NSLog(@"mstr2.retainCount: %ld", mstr2.retainCount); // -1 <-- 因为其实拷贝出来的是一个字符串常量
    复制代码
    2.mutableCopy
    需要实现NSMutableCopying协议
    创建的是可变副本,如NSMutableString, NSMutableArray, NSMutableDictionary
     
    (1)不可变对象调用mutableCopy
    产生一个新的对象,新旧对象的计数器独立,不会互相干扰,属于深拷贝
    复制代码
    1         NSString *str1 = [[NSString alloc] initWithString:@"abc"];
    2         NSLog(@"str1.addr: %p", str1); // 0x100001030
    3         NSLog(@"str1.retainCount: %ld", str1.retainCount); // -1 <-- 字符串常量存在常量池,不使用堆内存
    4 
    5         NSMutableString *mstr2 = [str1 mutableCopy]; // mutableCopy 出来的是一个 NSMutableString 对象
    6         NSLog(@"str1.addr: %p", str1); // 0x100001030
    7         NSLog(@"str1.retainCount: %ld", str1.retainCount); // -1 <-- 对于字符串常量, 无论是copy, retain, release操作都不会改变retianCount
    8         NSLog(@"mstr2.addr: %p", mstr2); // 0x100106460 <-- 深拷贝,开辟新的空间
    9         NSLog(@"mstr2.retainCount: %ld", mstr2.retainCount); // 1 <-- 由于是NSMutableString对象,retainCount == 1
    复制代码
     
    (2)可变对象调用mutableCopy
    产生一个新的对象,新旧对象的计数器独立,不会互相干扰,属于深拷贝
    复制代码
    1         NSMutableString *mstr1 = [[NSMutableString alloc] initWithString:@"abc"];
    2         NSLog(@"mstr1.addr: %p", mstr1); // 0x100402910
    3         NSLog(@"mstr1.retainCount: %ld", mstr1.retainCount); // 1
    4 
    5         NSMutableString *mstr2 = [mstr1 mutableCopy]; // mutableCopy 出来的是一个 NSMutableString 对象
    6         NSLog(@"mstr1.addr: %p", mstr1); // 0x100402910
    7         NSLog(@"mstr1.retainCount: %ld", mstr1.retainCount); // 1
    8         NSLog(@"mstr2.addr: %p", mstr2); // 0x100300e90 <-- 深拷贝,开辟新的空间
    9         NSLog(@"mstr2.retainCount: %ld", mstr2.retainCount); // 1
    复制代码
     
    3.自定义类的copy
    1 @interface Student : NSObject
    2 
    3 //copy代表setter会release旧对象,copy新对象
    4 @property (nonatomic, copy) NSString *name;
    5 
    6 @end
     
    传入外部NSMutableString对象到student的setter,当外部对象改变的时候,不会改变student中copy来的对象
    如果使用retain或者assign,就会影响,因为指向的是同一个对象
    ==>传入NSMutableString时(成员变量为NSString),一般使用copy策略,其他使用retain
     
    (1)实现<NSCopying>
    (2)实现 - (id) copyWithZone:(NSZone *) zone
    1 - (id)copyWithZone: (NSZone *) zone
    2 {
    3      Student *stu = [[Student allocWithZone:zone] init];
    4      stu.name = self.name;
    5      return stu;
    6 }
    如果一件事情你觉得难的完不成,你可以把它分为若干步,并不断寻找合适的方法。最后你发现你会是个超人。不要给自己找麻烦,但遇到麻烦绝不怕,更不要退缩。 电工查找电路不通点的最快方法是:分段诊断排除,快速定位。你有什么启示吗? 求知若饥,虚心若愚。 当你对一个事情掌控不足的时候,你需要做的就是“梳理”,并制定相应的规章制度,并使资源各司其职。
  • 相关阅读:
    155. 最小栈
    160. 相交链表
    PAT 1057 Stack
    PAT 1026 Table Tennis
    PAT 1017 Queueing at Bank
    PAT 1014 Waiting in Line
    PAT 1029 Median
    PAT 1016 Phone Bills
    PAT 1010 Radix
    PAT 1122 Hamiltonian Cycle
  • 原文地址:https://www.cnblogs.com/wvqusrtg/p/4515328.html
Copyright © 2011-2022 走看看