A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© Medwyn 中级黑马   /  2014-7-10 14:32  /  3777 人查看  /  12 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 Medwyn 于 2014-7-11 17:42 编辑

通过搜索引擎得到的答案不是太明确,请解惑

12 个回复

倒序浏览
copy: 建立一个索引计数为1的对象,然后释放旧对象
retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1
http://www.devdiv.com/objc_retain_copy_-blog-59970-11817.html
回复 使用道具 举报
copy是克隆一个对象,内存中将有两个属性值一模一样但地址不同的对象。retain是引用当前已存在的对象,将该对象的引用计数+1
回复 使用道具 举报
进来学习的!!!
回复 使用道具 举报
把NSString排外,对象的copy就相当于alloc。不知道这么说有错没。
回复 使用道具 举报
一般不可变对象都用copy   例如 @property(nonatomic,copy) NSString *name;
一下是我自己在网上找的资料  希望对你有帮助

在OC语法中,提供了Copy语法(Copy + MutableCopy)用于对象的拷贝。其中很容易混淆的是浅拷贝和深拷贝。
所谓浅拷贝,即是地址拷贝,并不产生新的对象,而是对原对象的引用计数值加1。而深拷贝,即是对象拷贝,产生新的对象副本,计数器为1。
下面通过一个例子来分析一下这个比较容易乱的Copy:
一、对于NSString/NSMutableString; NSArray/NSMutableArray... 这OC提供的类对象:
以NSString/NSMutableString为例:
对于copy,返回的一定是不可变类型;而mutableCopy,返回的一定是可变类型。
①对于 mutableCopy ,一定是深拷贝。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14        //对于 mutableCopy,都是深拷贝:对象的拷贝,产生新的对象
void strMutableCopy(){
     
    NSString *str=[[NSString alloc]initWithFormat:@"abcd"];
//    NSMutableString *str = [[NSMutableString alloc] initWithFormat:@"abcd"];
     
    //产生了一个新的对象 计数器为1 源对象的计数器不变
    NSMutableString *str2=[str mutableCopy];
//    NSString *str2 = [str mutableCopy];
     
    //输出二者的地址,二者的地址是不同的
    NSLog(@"str --> %p",str);
    NSLog(@"str2 --> %p",str2);
}

②对于 copy:
如果是 NSString ---> NSString;则是浅拷贝;如果是 NSMutableString ---> NSString;则是深拷贝。
如果是 NSString 、NSMutableString ---> NSMutableString;则是深拷贝。
注:只有一种情况下是发生浅拷贝:不可变对象 复制到 不可变对象。
?
1
2
3
4
5
6
7
8
9
10
11        //浅拷贝:指针拷贝 不会产生新的对象,源对象计数器加1
void strCopy(){
     
    NSString *str=[[NSString alloc]initWithFormat:@"abcd"];
    //因为NSString对象本身就不可变,所以并没产生新的对象,而是返回对象本身,会做一次retain操作,所以源对象也会retain
    NSString *str2=[str copy];
         
    //输出二者的地址,二者的地址是相同的
    NSLog(@"str --> %p",str);
    NSLog(@"str2 --> %p",str2);
}

除了以上这种情形外,其他都是深拷贝。
例如:
?
1
2
3
4
5
6
7
8
9
10
11
12        //深拷贝
void mutableStrCopy(){
     
    NSMutableString *str=[[NSMutableString alloc]initWithFormat:@"abcd"];
     
    //会产生一个新的对象计数器1
    NSString *str2=[str copy];
     
    //输出二者的地址,二者的地址是不同的
    NSLog(@"str --> %p",str);
    NSLog(@"str2 --> %p",str2);
}

二、对于自定义对象的Copy:该类必须实现NSCopying协议,重写 copyWithZone 方法。
同理,对于自定义对象的mutableCopy:必须实现 NSMutableCopying 协议,重写 mutableCopyWithZone 方法。
在NSCopying协议中,其实只有一个协议方法:
?
1
2
3        @protocol NSCopying
- (id)copyWithZone:(NSZone *)zone;
@end

在NSMutableCopying协议:
?
1
2
3        @protocol NSMutableCopying
- (id)mutableCopyWithZone:(NSZone *)zone;
@end

下面给出一个例子:
?
1
2
3
4
5
6
7
8
9
10        #import <foundation foundation.h="">

@interface Person : NSObject<nscopying>

@property(nonatomic,assign)int age;
@property(nonatomic,copy)NSString *name;

-(instancetype)initWithAge:(int)age withName:(NSString*)name;

@end</nscopying></foundation>

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19        #import "Person.h"

@implementation Person

-(instancetype)initWithAge:(int)age withName:(NSString*)name{
    self = [super init];
    if (self) {
        self.age = age;
        self.name = name;
    }
    return self;
}

-(id)copyWithZone:(NSZone *)zone{
    Person* person = [[[self class] allocWithZone:zone] initWithAge:self.age withName:self.name];
    return person;
}

@end

?
1
2
3
4
5
6
7
8
9
10
11
12
13        int main(int argc, const char * argv[])
{
    @autoreleasepool {
         
        Person *p1 = [[Person alloc] initWithAge:20 withName:@"Jack"];
        Person *p2 = [p1 copy];
         
        //输出两个 Person 对象的地址,二者是不同的
        NSLog(@"p1 --> %p",p1);
        NSLog(@"p2 --> %p",p2);
    }
    return 0;
}

加入对于某些自定义对象是不可变的,那么如何办呢?
?
1
2
3        -(id)copyWithZone:(NSZone *)zone{
    return self;
}
这样,输出的两个对象的地址就是相同的了。

下面了解一下关于如果某一个自定义类继承了 这个Person类的情况。
如果某一个子类继承了实现了NSCopying协议的基类,那么该子类也是会自动继承这个协议的方法。但是需要自己重新实现。
例如:有一个Student子类继承了这个Person类:
?
1
2
3
4
5
6
7
8
9        #import <foundation foundation.h="">
#import "Person.h"
@interface Student : Person

@property(nonatomic,copy)NSString *school;

-(instancetype)initWithAge:(int)age withName:(NSString *)name WithSchool:(NSString*)school;

@end</foundation>

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19        #import "Student.h"

@implementation Student

-(instancetype)initWithAge:(int)age withName:(NSString *)name WithSchool:(NSString*)school{
    self = [super initWithAge:age withName:name];
    if (self) {
        self.school = school;
    }
    return self;
}

-(id)copyWithZone:(NSZone *)zone{
    Student *student = [super copyWithZone:zone];
    student.school = self.school;
    return student;
}

@end

注意其中copyWithZone方法的实现。

点评

有可变子类的不可变对象才需要用copy。因为可以利用多态给不可变对象传入可变子类对象,如果不copy,就无法防止未预期的修改  发表于 2014-7-10 17:54
回复 使用道具 举报
不好意思  有些代码没有拷贝上  直接把文档传上来吧

Objective-C 浅析Copy语法.zip

29.21 KB, 阅读权限: 10, 下载次数: 4

回复 使用道具 举报
Medwyn 中级黑马 2014-7-10 21:51:38
8#
a1130003724 发表于 2014-7-10 17:46
不好意思  有些代码没有拷贝上  直接把文档传上来吧

很有帮助,谢谢!
回复 使用道具 举报
Medwyn 发表于 2014-7-10 21:51
很有帮助,谢谢!

有帮助  就好  哥们现在走到哪一步了呀
回复 使用道具 举报
a1130003724 发表于 2014-7-11 12:41
有帮助  就好  哥们现在走到哪一步了呀

过几天面试,想想还有点小紧张呢。。
回复 使用道具 举报
进来学习.......看你的问题我也上网查了一下, 以我的能力还不能理解,   0.0  我得抓紧拉!

   你也加油!
回复 使用道具 举报
Medwyn 发表于 2014-7-11 17:05
过几天面试,想想还有点小紧张呢。。

我也马上要面试了  你目前有多少分了   方不方便说一下
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马