黑马程序员---oc copy

来源:互联网 发布:莱恩打碟软件设置 编辑:程序博客网 时间:2024/06/06 03:54

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

1.一般结结构体对象的copy和mutablecopy

只有一种情况是浅拷贝:不可变对象调用copy方法时
l一个对象使用copy或mutableCopy方法可以创建对象的副本
lcopy – 需要先实现NSCoppying协议,创建的是不可变副本(如NSString、NSArray、NSDictionary)
lmutableCopy – 需要先实现NSMutableCopying协议,创建的是可变副本(如NSMutableString、NSMutableArray、NSMutableDictionary)
l深复制:内容拷贝,源对象和副本指向的是不同的两个对象。源对象引用计数器不变,副本计数器设置为1
l浅复制:指针拷贝,源对象和副本指向的是同一个对象。对象的引用计数器+1,其实相当于做了一次retain操作
l只有不可变对象创建不可变副本(copy)才是浅复制,其他都是深复制

2.一般自定义的对象的copy和mutablecopy(现在没感受到区别好像都是深拷贝)
对象的拷贝分为浅拷贝和深拷贝,浅拷贝就是只拷贝对象,但是属性不拷贝,拷贝出来的对象和原来的对象共用属性,即指向同一个属性地址,深拷贝则相当于不仅拷贝了一个对象还拷贝了它的属性,即完全是两个东西,只不过内容相同而已。

拷贝用到协议,如果这个类创建对象后,这个对象要被拷贝,那么这个类就需要用到拷贝协议,分两种:和相当于一个是拷贝,另一个是拷贝后可修改。


在最新版本的cocoa已经优化过了,所以有如下规则:

a:如果是Foundation框架里地不可变对象,就是Array,NSString等创建的对象,直接用copy来拷贝相当于retain,也就是属性还是同一个;

b:如果是用mutableCopy来拷贝,不管是可变还是不可变对象,属性神马的都直接拷贝了一份,即真正意义上得拷贝,它拷贝出来的对象统统都是可变的;

c:如果是可变对象,我们用copy也能实现真正意义上的拷贝,但是拷贝出来的对象是不可变的。

所以,我们拿name实验(因为age没有mutableCopy)实现语句的修改:

person.name=[_name mutableCopy]
person.age=[_age copy];
然后再输出person1和person2的name属性的地址,发现就不同了。

==========

自定义类的copy时,需要实现copyWithZone

// 这里创建的副本对象不要求释放
- (id)copyWithZone:(NSZone *)zone {
Student *copy = [[[self class] allocWithZone:zone] init];

// 拷贝名字给副本对象 这样实现了深拷贝 // copy.name = self.name;  copy.name=_name; //copy.name=[_name  mutableCopy];//copy.name=[_name copy];return copy;

}
——————————————————————————————————

////  Student.h//  copy-mutableCopy////  Created by amesty on 15-1-18.//  Copyright (c) 2015年 itcast. All rights reserved.//#import <Foundation/Foundation.h>//因为这个类要支持拷贝,所以需要引入拷贝协议,有两种,后一种拷贝后可修改@interface Student : NSObject <NSCopying,NSMutableCopying>// copy代表set方法会release旧对象、copy新对象// 修改外面的变量,并不会影响到内部的成员变量// 建议:NSString一般用copy策略,其他对象一般用retain@property (nonatomic, copy) NSString *name;+ (id)studentWithName:(NSString *)name;@end

————————————————————————

#import "Student.h"@implementation Student+ (id)studentWithName:(NSString *)name {    // 这里最好写[self class]    Student *stu = [[[[self class] alloc] init] autorelease];    stu.name = name;    return stu;}- (void)dealloc {    [_name release];    [super dealloc];}#pragma mark description方法内部不能打印self,不然会造成死循环- (NSString *)description {    return [NSString stringWithFormat:@"[name=%@]", _name];}#pragma mark copying协议的方法// 这里创建的副本对象不要求释放- (id)copyWithZone:(NSZone *)zone {    Student *copy = [[[self class] allocWithZone:zone] init];    // 拷贝名字给副本对象 这样实现了深拷贝    //copy.name = self.name;    copy.name=_name;    //copy.name=[_name  mutableCopy];    //copy.name=[_name copy];    return copy;}@end

————————————————————————

////  GoodStudent.h//  copy-mutableCopy////  Created by amesty on 15-1-18.//  Copyright (c) 2015年 itcast. All rights reserved.//#import "Student.h"@interface GoodStudent : Student@property (nonatomic, assign) int age;+ (id)goodStudentWithAge:(int)age name:(NSString *)name;@end

————————————————————————

#import "GoodStudent.h"@implementation GoodStudent+ (id)goodStudentWithAge:(int)age name:(NSString *)name {    GoodStudent *good = [GoodStudent studentWithName:name];    good.age = age;    return good;}- (NSString *)description {    return [NSString stringWithFormat:@"[name=%@, age=%i]", self.name, _age];}- (id)copyWithZone:(NSZone *)zone {    // 一定要调用父类的方法    GoodStudent *copy = [super copyWithZone:zone];    copy.age = [self.age copy];    return copy;}@end

————————————————————————

// 只有一种情况是浅拷贝:不可变对象调用copy方法时#import <Foundation/Foundation.h>#import "Student.h"#import "GoodStudent.h"// 只有一种情况是浅拷贝:不可变对象调用copy方法时// copy语法的目的:改变副本的时候,不会影响到源对象#pragma mark 演示字符串的拷贝(深拷贝)// 深拷贝:会产生新的对象,内容拷贝。新对象计数器置为1,源对象计数器不变。void stringMutableCopy() {    // string:1    NSString *string = [[NSString alloc] initWithFormat:@"age is %i", 10];    // 产生了一个新的对象,计数器为1。源对象的计数器不变。    // str:1    // string:1    NSMutableString *str = [string mutableCopy];    //NSLog(@"str:%zi", [str retainCount]);    //NSLog(@"string:%zi", [string retainCount]);    // str和string不是相同对象    // NSLog(@"%i", str == string);    [str appendString:@" abcd"];    NSLog(@"string:%@", string);    NSLog(@"str:%@", str);    // str:0    [str release];    // string:0    [string release];}#pragma mark 演示字符串的拷贝(浅拷贝)// 只有一种情况是浅拷贝:不可变对象调用copy方法时// 浅拷贝:指针拷贝,不会产生新的对象。源对象计数器+1。void stringCopy() {    NSString *string = [[NSString alloc] initWithFormat:@"age is %i", 10];    NSLog(@"%zi", [string retainCount]);    // copy产生的是不可变副本,由于源对象本身就不可变,所以为了性能着想,copy会直接返回源对象本身    // 源对象计数器会+1    // 在浅拷贝情况下,copy其实就相当于retain    NSString *str = [string copy];    NSLog(@"%zi", [string retainCount]);    // NSLog(@"%i", str == string);    [str release];    [string release];}#pragma mark 可变字符串的copy(深拷贝)void mutableStringCopy() {    NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i", 10];    // 会产生一个新对象,str计数器为1    NSString *str = [string copy];    [str release];}#pragma mark 可变字符串的MutableCopy(深拷贝)void mutableStringMutableCopy() {    NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i", 10];    // 会产生一个新对象,str计数器为1    NSMutableString *str = [string mutableCopy];    [str appendString:@"1234"];    NSLog(@"str:%@", str);    NSLog(@"string:%@", string);    [str release];}#pragma mark 演示Student的name的copyvoid studentNameCopy() {    Student *stu = [[[Student alloc] init] autorelease];    NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i", 10];    stu.name = string;    [string appendString:@"abcd"];    NSLog(@"name=%@", stu.name);    NSLog(@"string=%@", string);}#pragma mark 演示Student的copyvoid studentCopy() {    Student *stu1 = [Student studentWithName:@"stu1"];    Student *stu2 = [stu1 copy];    stu2.name = @"stu2";    NSLog(@"stu1:%@", stu1);    NSLog(@"stu2:%@", stu2);    [stu2 release];}void goodStudentCopy() {    GoodStudent *stu1 = [GoodStudent goodStudentWithAge:10 name:@"good1"];    GoodStudent *stu2 = [stu1 copy];    stu2.name = @"good2";    stu2.age = 11;    NSLog(@"stu1:%@", stu1);    NSLog(@"stu2:%@", stu2);}int main(int argc, const char * argv[]){    @autoreleasepool {   studentCopy();    }    return 0;}
0 0
原创粉丝点击