天天看點

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

    [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