OC之【深拷贝(mutableCopy)和浅拷贝(copy)】

main.m文件

#import <Foundation/Foundation.h>

#import "Student.h"

#import "GoodStudent.h"

// 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);

    //NSString并不受引用计数器机制管理

  //tring指向常量去,系统为了保护常量区的空间,把常量区的引用计数弄很大......如果用%d打印,会溢出,打印出来-1 此处%d(有黄色警报) == %iz(无警报哦)

    [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的copy

void 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的copy

void 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 {

        goodStudentCopy();

    }

    return 0;

}

Student.h文件

#import <Foundation/Foundation.h>

@interface Student : NSObject <NSCopying>

// copy代表set方法会release旧对象、copy新对象

// 修改外面的变量,并不会影响到内部的成员变量

// 建议:NSString一般用copy策略,其他对象一般用retain

@property (nonatomic, copy) NSString *name;

+ (id)studentWithName:(NSString *)name;

@end

Student.m文件

#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;

    

    return copy;

}

@end

GoodStudent.h

#import "Student.h"

@interface GoodStudent : Student

@property (nonatomic, assign) int age;

+ (id)goodStudentWithAge:(int)age name:(NSString *)name;

@end

GoodStudent.m

#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;

    

    return copy;

}

@end

On the road。。。
原文地址:https://www.cnblogs.com/ianhao/p/4425900.html