文档章节

黑马程序员-15-Objective-C学习笔记(copy语法)

 明天过后1
发布于 2014/10/10 00:47
字数 1808
阅读 38
收藏 0
点赞 0
评论 0

---------------------- Java培训.Net培训Android培训IOS培训、期待与您交流! ----------------------

1. 简介

    (1) OC也提供了copy(copy + mutableCopy)语法,来实现对象的拷贝;对于拷贝我们要弄明白两个问题: 深层拷贝 和 浅层拷贝。

    (2) 浅层拷贝 : 就是地址拷贝,并不铲射别难过新的对象,对象的引用计数器加1。

    (3) 深层拷贝 : 就是对象拷贝,产生新的对象性副本,对象本身计数器计数器不变,副本的引用计数器为1.

    (4) copy语法设计目的 : 改变副本的同时,不会影响到原对象。

    (5) OC中可以使用获得该引用计数器的值来检查是否深拷贝。


2. 常用类的copy语法使用

    a. copy

         OC中常用的类有 : NSString,NSArray,NSSet,NSDictionary等等,copy比较特殊 : 它返回的是对象本身(浅层拷贝)。根据copy语法的设计目的,copy之后返回的是对象本身,因为它本身就不能被改变了。因此,常用OC类的设计者为了性能考虑,使NSString的copy返回对象本身的引用。

// ARC关闭
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
    /***************************************************** NSString **************************************************************/
        // 创建一个 NSString 对象
        NSString *str = [NSString stringWithFormat:@"age is %d",10];
        // 检查引用计数器
        NSLog(@"current count = %lu",[str retainCount]);                        // current count = 1
        // str进行一次copy
        NSString *strCopy = [str copy];                                         
        // 再次检查引用计数器,验证是否深拷贝
        NSLog(@"current count = %lu",[str retainCount]);                        // current count = 2
        // 进一步验证 NSString 的 copy 是否返回对象本身
        NSLog(@"str == strCopy --> %@",strCopy == str ? @"true" : @"false");    // str == strCopy --> true
        [strCopy release];
         strCopy = nil;
    /***************************************************** NSArray **************************************************************/
        // 创建 OC 数组
        NSArray *arr = @[@"one",@"two"];
        // 检查引用计数器
        NSLog(@"arr current count is %lu",[arr retainCount]);                   // arr current count is 1
        
        // copy
        NSArray *arrCopy = [arr copy];
        
        // 验证 copy 是否深拷贝
        NSLog(@"arr current count is %lu",[arr retainCount]);                   // arr current count is 2
        NSLog(@"arrCopy current count is %lu",[arrCopy retainCount]);           // arrCopy current count is 2
        NSLog(@"arr == arrCopy --> %@",arr == arrCopy ? @"true" : @"false");    // arr == arrCopy --> true

        [arrCopy release];
        arrCopy = nil;
     /***************************************************** NSSet ***************************************************************/
        NSSet *set = [NSSet setWithObjects:@"one",@"two", nil];
        NSLog(@"set current count is %lu",[set retainCount]);                   // set current count is 1
        // copy
        NSSet *setCopy = [set copy];
        
        // 验证 copy 是否深拷贝
        NSLog(@"set current count is %lu",[set retainCount]);                   // set current count is 2
        NSLog(@"setCopy current count is %lu",[setCopy retainCount]);           // setCopy current count is 2
        NSLog(@"set == setCopy --> %@",set == setCopy ? @"true" : @"false");    // set == setCopy --> true
    
        [setCopy release];
        setCopy = nil;
     /***************************************************** NSDictionary ***************************************************************/
        NSDictionary *dict = @{@"1" : @"one" ,@"2" : @"two"};
        NSLog(@"dict current count is %lu",[dict retainCount]);                 // dict current count is 1
        // copy
        NSDictionary *dictCopy = [dict copy];
        
        // 验证 copy 是否深拷贝
        NSLog(@"dict current count is %lu",[dict retainCount]);                 // dict current count is 2
        NSLog(@"dictCopy current count is %lu",[dictCopy retainCount]);         // dictCopy current count is 2
        NSLog(@"dict == dictCopy --> %@",dict == dictCopy ? @"true" : @"false"); // set == setCopy --> true
        
        [dictCopy release];
        dictCopy = nil;
    }
    return 0;
}

    b. mutableCopy

        mutableCopy,根据copy语法设计的目的返回一个可变对象(NSMutable),而且改变副本同时不影响原对象,因此只有深拷贝满足条件。

// ARC关闭
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
    /***************************************************** NSString **************************************************************/
        // 创建一个 NSString 对象
        NSString *str = [NSString stringWithFormat:@"age is %d",10];
       
        // 检查引用计数器
        NSLog(@"str current count = %lu",[str retainCount]);                                                    // str current count = 1
        
        // NSString的 mutableCopy 返回的可变对象 NSMutableString
        NSMutableString *strMutableCopy = [str mutableCopy];
        // 修改副本
        [strMutableCopy appendString:@" ,and name is mike"];
        
        // 检查引用计数器,验证是 否深拷贝
        NSLog(@"str : %@ current count = %lu",str,[str retainCount]);                                           // age is 10 current count = 1
        NSLog(@"str == strCopy --> %@",strMutableCopy == str ? @"true" : @"false");                             // str == strCopy --> false
        
        // mutableCopy 后的对象都是一个新的对象引用计数器为1
        NSLog(@"strMutableCopy : %@ current count = %lu",strMutableCopy,[strMutableCopy retainCount]);          // age is 10 ,and name is mike current count = 1
        [strMutableCopy release];
     /***************************************************** NSArray **************************************************************/
         // 创建 OC 数组
        NSArray *arr = @[@"one",@"two"];
        // 检查引用计数器
        NSLog(@"arr current count is %lu",[arr retainCount]);                                                   // arr current count is 1
        
         // mutableCopy
        NSMutableArray *arrMutable = [arr mutableCopy];
        
        // 验证 mutableCopy 是否深拷贝
        [arrMutable addObject:@"three"];
        NSLog(@"arrMutable : %@",arrMutable);                                                                     // arrMutable : (one,two,three)
        NSLog(@"arr : %@",arr);                                                                                   // arr : (one,two)
        NSLog(@"arr == arrMutable --> %@",arr == arrMutable ? @"true" : @"false");                                // arr == arrMutable --> false
        [arrMutable release];
        arrMutable = nil;
    /***************************************************** NSSet **************************************************************/
        NSSet *set = [NSSet setWithObjects:@"one",@"two", nil];
        NSLog(@"set current count is %lu",[set retainCount]);                                                       // set current 
        // mutableCopy
        NSMutableSet *setMutable = [set mutableCopy];
        
        // 验证 mutableCopy 是否深拷贝
        [setMutable addObject:@"three"];
        NSLog(@"arrMutable : %@",setMutable);                                                                        // setMutable : {(one,two,three)}
        NSLog(@"set : %@",set);                                                                                      // set : {(one,two)}
        NSLog(@"set == setMutable --> %@",set == setMutable ? @"true" : @"false");                                   // set == setMutable --> false

        [setMutable release];
        setMutable = nil;
    /***************************************************** NSMutableDictionary **************************************************************/     
        NSDictionary *dict = @{@"1" : @"one" ,@"2" : @"two"};
        NSLog(@"dict current count is %lu",[dict retainCount]);                                                     // dict current is 1
        
        NSMutableDictionary *dictMutable = [dict mutableCopy];
        // 验证 mutableCopy 是否深拷贝
        [dictMutable setObject:@"3" forKey:@"three"];
        NSLog(@"dictMutable : %@",dictMutable);                                                                     // dictMutable : {1 = one ;2 = two ;3 = three}
        NSLog(@"dict : %@",dict);                                                                                   // dict : {1 = one ;2 = two}
        NSLog(@"dict == dictMutable --> %@",dict == dictMutable ? @"true" : @"false");                              // dict == dictMutable --> false
          
        [dictMutable release];
        dictMutable = nil;
    }
    return 0;
}


3. copy语法在自定义对象中的用法

    (1) 我们打开 NSString 的声明发现它遵守了NSCopying协议,因此我们如果想在自定义对象中实现使用copy语法,必须遵守 NSCopying 协议,并实现

- (id)copyWithZone:(NSZone *)zone 方法。

    (2) @property 其中有一个参数是 copy ,它在set方法中的作用是释放旧值,copy新值。但如果我们给set放入的参数是可变对象,那么它覆盖属性的时候是进行深层拷贝,如果给它的参数是不可变对象,那么它覆盖属性的时候是进行浅层拷贝,对于我们自己设计对象,选择深层还是浅层决定于我们实现的  - (id)copyWithZone:(NSZone *)zone 方法。

// ARC关闭
/************************************** Person.h **************************************/
#import <Foundation/Foundation.h>

// 如果要使用copy语法必须遵守 NSCopying 协议
@interface Person : NSObject <NSCopying>
/*
 * copy是释放旧值,copy新值
 * 对于set方法 :
 * 参数 : 可变对象    -> 深层拷贝
 *        不可变参数  -> 浅层拷贝
 */
@property (nonatomic,copy) NSString *name;

@end

/************************************** Person.m **************************************/
#import "Person.h"

@implementation Person

+ (id) initWithName :(NSString *) name
{
    Person *p = [[self alloc] init];
    p.name = name;
    return p;
}

- (id)copyWithZone:(NSZone *)zone
{
    NSLog(@"调用copy...");
    // 对于使用 copy 语法,内存释放由调用者完成
    Person *copy = [[[self class] allocWithZone:zone] init];
    
    copy.name = _name;
    return copy;
}

-(NSString *)description
{
    NSString *des = [NSString stringWithFormat:@"name : %@ , name的地址 : %p",_name,_name];
    return des;
}

-(void)dealloc
{
    [_name release];
    [super dealloc];
}

@end

/************************************** main.m **************************************/

/*
* copy参数的验证示例
*/

#import <Foundation/Foundation.h>
#import "Person.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // 不可变字符串
        // NSString *str1 = [NSString stringWithFormat:@"age is %d",10];
        // Person *p = [[[Person alloc] init] autorelease];
        // p.name = str1;
        // 判断对象的地址是否一样来检验是否完成深拷贝
        // NSLog(@"%d",str1 == p.name);                                                    // 打印结果为 1 则说明完成浅拷贝
        
        // 可变字符串
        NSMutableString *str1 = [NSMutableString stringWithFormat:@"age is %d",10];
        Person *p = [[[Person alloc] init] autorelease];
        p.name = str1;
        // 判断对象的地址是否一样来检验是否完成深拷贝
        NSLog(@"%d",str1 == p.name);                                                        // 打印结果为 0 则说明完成深拷贝
    }
    return 0;
}

/*
* 对象copy语法实现深层拷贝验证
*/

#import <Foundation/Foundation.h>
#import "Person.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // 不可变对象
        NSString *name = [NSString stringWithFormat:@"%@",@"jack"];
        Person *p = [[[Person alloc] init] autorelease];
        p.name = name;
        
        Person *p2 =[[p copy] autorelease];                                                 // 调用copy...
        NSLog(@"p 地址: %p ,p : %@",&p,p);                                                   // p  地址: 0x7fff5fbff870 ,p  : name : jack , name的地址 : 0x1002040f0
        NSLog(@"p2 地址: %p ,p2 : %@",&p2,p2);                                               // p2 地址: 0x7fff5fbff868 ,p2 : name : jack , name的地址 : 0x1002040f0

    }
    return 0;
}

4. 总结

     (1) 使用或者实现copy语法,一切从copy语法设计的目的出发 : 改变副本的同时,不会影响到原对象

     (2) 对于@property参数中的copy它的规律是 : 如果set方法传入的对象是不可变对象那么完成的是浅层拷贝,否则为深层拷贝,对于自定义对象是否深层拷贝取决于我们实现的 - (id)copyWithZone:(NSZone *)zone 方法。

   (3)对于常用的类 : NSString ,NSArray ,NSSet ,NSDictionary 等都有这些规律 : copy --> 浅层拷贝  mutableCopy  --> 深层拷贝



---------------------- Java培训.Net培训Android培训IOS培训、期待与您交流! ---------------------- 

 详情请查看:http://edu.csdn.net/heima



© 著作权归作者所有

共有 人打赏支持
粉丝 2
博文 20
码字总数 36166
作品 0
佛山
IOS学习笔记——Objective-c基础(一)

最近自学ios,ios的支持语言是Objective-c,所以要学习ios就需要先学习Objective-c语言。当掌握了Objective-c的基础知识之后,我们就可以入手学习iOS开发做出一些自己的应用。 我现在还是...

丛林迷雾 ⋅ 2012/12/30 ⋅ 1

objective-c优雅的语法

对初学者来说,objective-c存在了很多令人费解的写法,实际上他们是非常优雅的。 程序员写的最多的就是函数以及调用自己写的或者别人写的函数。本文就从函数的角度来看下objective-c的优雅之...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

为什么 Objective-C 很难

作为一个Objective-C的coder,我总能听到一部分人在这门语言上抱怨有很多问题。他们总在想快速学习这门语言来写一个App出来,但他们也总是联想到Objective-C看上去实在太难了或者在想这些语法...

junwong ⋅ 2012/03/07 ⋅ 69

【objective-c】初次学习objective-c问题汇总... 【暂完,待修改错误】

---------------------------------------------------------------------------------------- 这本书,我已经看过两遍,那两遍都是在买mac pro之前看的,目的是...因为语法怪怪的很有趣。 ...

小小M ⋅ 2013/06/26 ⋅ 2

给大家分享黑马程序员Android课程笔记

黑马程序员课程笔记,这套笔记目的是让黑马的学员能够有一个详细的课下资料,也非常适合想学习Android的同学。 这套课程笔记包含内容: 1.Android基础视频部分: 2.Android360项目: 3.智慧北...

小梦想家 ⋅ 2015/12/04 ⋅ 4

苹果Objective-C一枝独秀:程序员啃骨头

【IT168 技术】作为一个 Objective-C的 coder,我总能听到一部分人在这门语言上抱怨有很多问题。他们总在想快速学习这门语言来写一个 App 出来,但他们也总是联想到 Objective-C看上去实在太...

开源中国社区 ⋅ 2012/03/08 ⋅ 0

Swift 个人学习笔记 - 06: 控制流

本文章纯粹是中文版《The Swift Programming Language》的学习笔记,所以绝大部分的内容都是文中有的。本文是本人的学习笔记,不是正式系统的记录。仅供参考 以下还是有很多没看懂、不确定的...

amc ⋅ 2017/02/22 ⋅ 0

《从零开始学Swift》学习笔记(Day 69)——Swift与Objective-C混合编程之语言

《从零开始学Swift》学习笔记(Day 69)——Swift与Objective-C混合编程之语言 原创文章,欢迎转载。转载请注明:关东升的博客 在Swift语言出现之前,开发iOS或OS X应用主要使用Objective-C...

智捷课堂 ⋅ 2016/02/24 ⋅ 0

TIOBE编程语言排行榜:Objective-C蝉联“年度语言”

TIOBE发布了最新的编程语言排行版,Objective-C连续第2年获得“年度语言”殊荣。年度语言是指在上一年份额增长最多的语言。Objective-C最新的份额为10.283%,比去年同期增长了3.37%。在2010年...

oschina ⋅ 2013/01/06 ⋅ 46

Swift是花拳绣腿吗?——谈谈开发语言与程序员的职业发展

作者简介: 任旻,北京工业大学硕士, 2005年加入微软中国有限公司,2009年加入腾讯,现任高级工程师,曾负责开发“QQ概念版”、“Q+”、”QQ互联”、“iPad QQ”等产品。腾讯学院讲师,专利...

腾讯Bugly ⋅ 2015/11/26 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Gitee 生成并部署SSH key

1.如何生成ssh公钥 你可以按如下命令来生成 sshkey: ssh-keygen -t rsa -C "xxxxx@xxxxx.com" # Generating public/private rsa key pair...# 三次回车即可生成 ssh key 查看你的 ...

晨猫 ⋅ 24分钟前 ⋅ 0

zblog2.3版本的asp系统是否可以超越卢松松博客的流量[图]

最近访问zblog官网,发现zlbog-asp2.3版本已经进入测试阶段了,虽然正式版还没有发布,想必也不久了。那么作为aps纵横江湖十多年的今天,blog2.2版本应该已经成熟了,为什么还要发布这个2.3...

原创小博客 ⋅ 今天 ⋅ 0

聊聊spring cloud的HystrixCircuitBreakerConfiguration

序 本文主要研究一下spring cloud的HystrixCircuitBreakerConfiguration HystrixCircuitBreakerConfiguration spring-cloud-netflix-core-2.0.0.RELEASE-sources.jar!/org/springframework/......

go4it ⋅ 今天 ⋅ 0

二分查找

二分查找,也称折半查找、二分搜索,是一种在有序数组中查找某一特定元素的搜索算法。搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;如果某一特定元素大于...

人觉非常君 ⋅ 今天 ⋅ 0

VS中使用X64汇编

需要注意的是,在X86项目中,可以使用__asm{}来嵌入汇编代码,但是在X64项目中,再也不能使用__asm{}来编写嵌入式汇编程序了,必须使用专门的.asm汇编文件来编写相应的汇编代码,然后在其它地...

simpower ⋅ 今天 ⋅ 0

ThreadPoolExecutor

ThreadPoolExecutor public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, ......

4rnold ⋅ 昨天 ⋅ 0

Java正无穷大、负无穷大以及NaN

问题来源:用Java代码写了一个计算公式,包含除法和对数和取反,在页面上出现了-infinity,不知道这是什么问题,网上找答案才明白意思是负的无穷大。 思考:为什么会出现这种情况呢?这是哪里...

young_chen ⋅ 昨天 ⋅ 0

前台对中文编码,后台解码

前台:encodeURI(sbzt) 后台:String param = URLDecoder.decode(sbzt,"UTF-8");

west_coast ⋅ 昨天 ⋅ 0

实验楼—MySQL基础课程-挑战3实验报告

按照文档要求创建数据库 sudo sercice mysql startwget http://labfile.oss.aliyuncs.com/courses/9/createdb2.sqlvim /home/shiyanlou/createdb2.sql#查看下数据库代码 代码创建了grade......

zhangjin7 ⋅ 昨天 ⋅ 0

一起读书《深入浅出nodejs》-node模块机制

node 模块机制 前言 说到node,就不免得提到JavaScript。JavaScript自诞生以来,经历了工具类库、组件库、前端框架、前端应用的变迁。通过无数开发人员的努力,JavaScript不断被类聚和抽象,...

小草先森 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部