Objective-C之文法copy、mutablecopy以及自訂複製功能

來源:互聯網
上載者:User

copy設計的目的:改變副本的時候,不會影響到原來的對象
1、一個對象使用copy或者mutableCopy方法可以建立對象的副本
2、copy需要先實現NSCopying協議,建立的是不可改變副本(NSString、NSArray、NSDictionary)
mutableCopy 需要先建立NSMutableCopying協議,建立的是可變副本(如NSMutableString、NSMutableArray、NSMutableDictionary)
3、深複製:內容拷貝,來源物件和副本指向的是同一個對象。來源物件引用計數器不變,副本計數器設定為1
淺複製:指標複製,來源物件和副本對象指向的二十同一個對象,對象的引用對象加1,其實相當於做了一次retain操作
只有不可變對象建立不可變副本(copy)才是淺複製,其它都是深複製

4、NSString、NSArray、NSDictionary三種OC對象預設都已經實現了cooppying和NSMutableCopying協議

5、自訂類添加複製功能:
如果想自訂copy,那麼必須遵守NSCopying,並實現copyWithZone:方法
如果想自訂mutableCopy,那麼就必須遵守NSMutableCopying,並實現mutableCopyZone:方法
例如copy:
建議用self class 代替類名

- (id)copyWithZone:(NSZone *)zone{
    id copy = [[[self class] allocWithZone:zone] init];
    //這兒開始做一些屬性的初始化
    return copy;
}

測試demo代碼如下:
在這個demo中主要示範copy、mutableCopy,解說深拷貝、淺拷貝
以及自訂copy、mutableCopy的方法

Student.h檔案
#import <Foundation/Foundation.h>
@interface Student : NSObject<NSCopying>
//copy代表set方法會release舊對象,copy新對象
//修改外面的變數,並不會影響到內部的成員變數
//建議:NSString一般用copy策略,其它對象一般用retain
//retain 和外邊是同一個對象,外邊該了,裡面這個name屬性也會改
@property (nonatomic, retain) NSString *name;

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

@end

Student.m檔案:
#import "Student.h"
@implementation Student
/**
//@property (copy) :的意思如同下面這段setName方法
- (void)setName:(NSString *)name{
    if(_name!=name){
        [_name release];
        _name = [name copy];
    }
}
**/

+ (id)studentWithName:(NSString *)name{
    //最好寫slef class
    Student *stu = [[[[self class] alloc] init] autorelease];
    stu.name = name;
    return stu;
}

#pragma mark coping協議的方法
//這裡建立的副本對象不要求釋放
- (id)copyWithZone:(NSZone *)zone{
    Student *copy = [[[self class] allocWithZone:zone]init];
    copy.name = self.name;
    return copy;
}
//description 內部不能列印self不然會有死迴圈
- (NSString *)description{
    return [NSString stringWithFormat:@"name=%@",_name];
}

- (void) dealloc{
    NSLog(@"student %@ is destoryed", self);
    [_name release];
    [super dealloc];
}

@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 ;
}

#pragma mark 重寫父類的方法
- (id)copyWithZone:(NSZone *)zone{
    //一定要調用父類的這個方法,因為父類幫我們copy了名字
    GoodStudent *copy = [super copyWithZone:zone];
    copy.age = self.age;
    return copy;
}

- (NSString *)description{
    return [NSString stringWithFormat:@"[name=%@, age=%i]",self.name, _age];
}
@end

main測試方法:

#import <Foundation/Foundation.h>
#import "Student.h"
#import "GoodStudent.h"

void stringMutableCopy(){
    NSString *string = [[NSString alloc] initWithFormat:@"age is %i",10];
    //產生一個新的對象,計數器為1,來源物件的計數器不改變
    NSMutableString *str = [string  mutableCopy];
   
    NSLog(@"string: %zi",[string retainCount]); //1
    NSLog(@"str :%zi",[str retainCount]);  //1
    //str和string不是相同對象
    NSLog(@"%i",str ==string);//0
   
    [str release];
    [string release];
   
}
/**
 只有這一種情況是淺拷貝:指標拷貝,不會產生新的對象
 **/
void stringCopy(){
    NSString *string = [[NSString alloc] initWithFormat:@"age is %i",10];
    //copy是不可變副本,由於來源物件本身就不可變,所以為了效能著想,copy直接返回來源物件本身
   // 來源物件計數器+1
    NSString *str = [string copy];

    NSLog(@"%zi",[string retainCount]); //2
    NSLog(@"%zi",[str retainCount]); //2
    //相同對象
    NSLog(@"%i",str == string);  //1
   
    [str release];
    [string release];
}
/**
 只有一種情況淺拷貝:string-string
 **/
//深拷貝
void mutableStringCopy(){
    NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i",10];
    NSString *str = [string copy];
   
    NSLog(@"%i",str == string); //0
}
//深拷貝
void mutableStringMutableCopy(){
    NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i",10];
    NSMutableString *str = [string mutableCopy];
    NSLog(@"%i",str == string ); //0
   
    [str appendString:@"abc"];
    NSLog(@"%@", str); //10abc
   
}
//stendent屬性的copy
void studentNameCopy(){
    Student *stu = [[[Student alloc]init] autorelease];
    NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i", 10];
   
    stu.name = string;
   
    [string appendString:@"abcd"];
   
    NSLog(@"stu.name=%@",stu.name);
    NSLog(@"string=%@",string);
}
//stendent對象的copy
void studentCopy(){
    Student *stu1 = [Student studentWithName:@"stu1"];
    Student *stu2 = [stu1 copy];
   
    NSLog(@"stu1:%@",stu1.name);
    NSLog(@"stu2:%@",stu2.name);
   
    stu2.name = @"stu2";
   
    NSLog(@"stu1:%@",stu1.name);
    NSLog(@"stu2:%@",stu2.name);
    NSLog(@"%i",stu1 == stu2);
   
    [stu2 release];
}
//GoodStudent子類的copy
void goodStudent(){
    GoodStudent *goodStu1= [GoodStudent goodStudentWithAge:20 name:@"goodStu1"];
    NSLog(@"goodStu1:%@",goodStu1);
   
    GoodStudent *goodStu2 = [goodStu1 copy];
    NSLog(@"goodStu2:%@",goodStu2);
}
int main(int argc, const char * argv[])
{

    @autoreleasepool {
        NSLog(@"----stringMutableCopy----");
        stringMutableCopy();
        NSLog(@"----stringcopy----");
        stringCopy();
        NSLog(@"----mutableStringCopy----");
        mutableStringCopy();
        NSLog(@"----mutableStringMutableCopy----");
        mutableStringMutableCopy();
        NSLog(@"----studentNameCopy----");
        studentNameCopy();
        NSLog(@"----studentCopy----");
        studentCopy();
        NSLog(@"----goodStudent----");
        goodStudent();
    }
    return 0;
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.