【Objective-C】Copy语法

感谢:http://my.oschina.net/aofe/blog/266677

一、概念

1. 目的:在改变原有对象的时候,不会改变新对象的值

2. Copy 字面上面的意思是拷贝,是一个产生副本的过程。

3. 特点:

  1). 修改源文件的内容,不会影响副本文件;

  2). 修改副本文件的内容,不会影响源文件;

4. 如何使用Copy功能?

  一个对象可以调用copy或MutableCopy方法来创建一个副本对象。

  1). Copy:创建的是不可变副本(NSString、NSArray....)

  2). MutableCopy:创建的是可变副本(NSMutableString、NSMutableArray....)

5. 使用copy的前提

  1). copy:需要遵守NSCopying协议,实现copyWithZone: 方法;

@protocol NSCopying

  - (id)copyWithZone:(NSZone *)zone;

@end 

  2). MutableCopy::需要遵守NSMutableCopyint协议,实现MutableCopyWithZone: 方法;

   @protocol NSMutableCopying

      - (id)mutableCopyWithZone:(NSZone *)zone;

      @end 
6. 内存管理

  1). 深拷贝:内容拷贝,会产生新的对象,所以源对象的计数器不变 >>> 对象拷贝

       特点: 源对象和副本对象是两个不同的对象;

                   源对象计数器不变,新对象计数器为1(是因为新产生的);

       本质: 产生了新的对象

  2). 浅拷贝: 指针拷贝(不是将地址赋值给另外一个)不产生新的对象,所以源对象计数器+1 >>> 指针拷贝(因为对象本身不可以变,所以没有必要在创建一个对象)

        特点:源对象与新对象是同一对象;

                   源对象(副本对象)引用计数器+1,相当于做了一次retain操作;

        本质: 没有产生了新的对象

关系图如下:

二、NSString 与 copy

1. NSString 与 MutableCopy (深拷贝)

void stringMutableCopy() {
    // 不可变
    NSString *string = [[NSString alloc] initWithFormat:@"age is %i", 10];
    // 可变,产生一个新对象,计数器+1,源对象的计数器不变
    NSMutableString *str = [string mutableCopy];
    // 由不可变转变为可变 不是同一对象了
    NSLog(@"str:%zi", [str retainCount]);
    NSLog(@"string:%zi", [string retainCount]);
    
    // 验证是否为同一对象
    NSLog(@"string == str ?: %i", string == str);
    
    // 改变副本看看源对象是否变化
    [str appendString:@"haha"];
    NSLog(@"string:%@", string);
    NSLog(@"str:%@", str);
    
    // 释放
    [string release];
    [str release];
    
}
2. NSString 与 Copy(浅拷贝)
void stringCopy() {
    // 不可变
    NSString *string = [[NSString alloc] initWithFormat:@"age is %i", 10];
    // 不可变,
    // 没有产生新的对象。(这是由于源对象本身不可变,所以副本是不可变的)
    NSString *str = [string copy];
    // 打印计数器
    NSLog(@"str:%zi", [str retainCount]);
    NSLog(@"string:%zi", [string retainCount]);
    
    // 验证是否为同一对象
    NSLog(@"string == str ?: %i", string == str);
    
    // 改变副本看看源对象是否变化
    //[str appendString:@"haha"];
    NSLog(@"string:%@", string);
    NSLog(@"str:%@", str);
    
    [str release];
    [string release];
    
}
3. NSMutableString 与 MutableCopy(深拷贝)
void mutableStringMutableCopy() {
    // 可变
    NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i", 10];
    
    // 这个属于深拷贝
    // 可变
    NSMutableString *str = [string mutableCopy];
    
    // 验证是否为同一对象
    NSLog(@"string == str ?: %i", string == str);
    
    // 释放
    [str release];
    [string release];
    
}
3. NSMutableString 与 Copy(深拷贝)
void mutableStringCopy() {
    // 可变
    NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i", 10];
    
    // 这个属于深拷贝
    // 不可变
    NSString *str = [string copy];
    
    // 验证是否为同一对象
    NSLog(@"string == str ?: %i", string == str);
    
    // 释放
    [str release];
    [string release];
}
三、对象拷贝实例

对象拷贝实例必须要注意的问题:

 1). 必须要实现NSCopying协议;

 2). 需要重写-(id)copyWithZone:(NSZone *)zone 方法;

 3). 代码中self class的引用 ()

01. GoodStudent.h

#import "Student.h"

@interface GoodStudent : Student

@property (nonatomic, assign) int age;

+(id)goodStudentWithName:(NSString *)name withAge:(int)age;

@end
02. GoodStudent.m
#import "GoodStudent.h"

@implementation GoodStudent

+(id)goodStudentWithName:(NSString *)name withAge:(int)age
{
    GoodStudent *stu = [super studentWithName:name];
    stu.age = age;
    
    return stu;
}

-(id)copyWithZone:(NSZone *)zone
{
    GoodStudent *copy = [super copyWithZone:zone];
    copy.age = self.age;
    
    return copy;
}

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

@end
03. Student.h
#import <Foundation/Foundation.h>

@interface Student : NSObject <NSCopying>

@property (nonatomic, copy) NSString *name;

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

@end
04. Student.m
#import "Student.h"

@implementation Student
+(id)studentWithName:(NSString *)name
{
    Student *stu = [[[[self class] alloc] init] autorelease];
    stu.name = name;
    
    return stu;
}

- (id)copyWithZone:(NSZone *)zone
{
    Student *copy = [[self class] allocWithZone:zone];
    
    copy.name = self.name;
    
    return copy;
}

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

-(void)dealloc
{
    [_name release];
    [super dealloc];
}
@end
05.main
#import <Foundation/Foundation.h>
#import "GoodStudent.h"

void test1()
{
    Student *stu = [Student studentWithName:@"name1"];
    Student *stu1 = [stu copy];
    
    NSLog(@"%@", stu);
    NSLog(@"%@", stu1);
}

void test2()
{
    GoodStudent *stu1 = [GoodStudent goodStudentWithName:@"name1" withAge:10];
    
    GoodStudent *stu2 = [stu1 copy];
    
    NSLog(@"%@", stu1);
    NSLog(@"%@", stu2);
    
}

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        
        test2();
        
    }
    return 0;
}
四、@property内存管理策略的选择

1. 非ARC

  1). copy: 只用于NSString/block;

  2). retain: 除NSString/block以外的oc对象;

  3). assign:基本数据类型、枚举、结构体(非OC对象),当两个对象相互引用,一端用retain,一端用assign;

2. ARC

  1). copy: 只用于NSString/block;

  2). strong: 除NSString/block以外的oc对象;

  2). weak: 当两个对象相互引用,一端用strong,一端用weak;

  3). assign:基本数据类型、枚举、结构体(非OC对象);


感谢:http://my.oschina.net/aofe/blog/266677


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值