zoukankan      html  css  js  c++  java
  • iOS开发中表视图搜索栏实现中的ObjectiveC 递归问题

         在学习iphone开发教程的中第8章(也就是《iOS5开发基础教程》最新版的“08 - Sections2”下载地址:http://vdisk.weibo.com/s/hBHg6

    要为一个tableView实现搜索功能的时候,遇到了一个问题,学习了好长时间终于想通,现在将问题以及我的理解总结一下.

    《iOS5开发基础教程》


    书上讲要实现一个MutableDeepCopy协议,关于这个整个思路,协议,需要一个新的副本这些我都能明白,就是里头的具体实现方法遇到点问题,里头的实现代码如下,

    NSDictionary-MutableDeepCopy.h

    #import <Foundation/Foundation.h>
    @interface NSDictionary(MutableDeepCopy)
    -(NSMutableDictionary *)mutableDeepCopy;
    @end

    NSDictionary-MutableDeepCopy.m

    #import "NSDictionary-MutableDeepCopy.h"
    
    @implementation NSDictionary(MutableDeepCopy)
    - (NSMutableDictionary *)mutableDeepCopy {
        NSMutableDictionary *returnDict = [[NSMutableDictionary alloc]
                                           initWithCapacity:[self count]];
        NSArray *keys = [self allKeys];
        for (id key in keys) {
            id oneValue = [self valueForKey:key];
            id oneCopy = nil;
            
            if ([oneValue respondsToSelector:@selector(mutableDeepCopy)])
                oneCopy = [oneValue mutableDeepCopy];
            else if ([oneValue respondsToSelector:@selector(mutableCopy)])
                oneCopy = [oneValue mutableCopy];
            if (oneCopy == nil)
                oneCopy = [oneValue copy];
            [returnDict setValue:oneCopy forKey:key];
        }
        return returnDict;
    }
    
    
    @end
    


    书上的解释是,

    在for里头迭代每个数组,

    首先尝试创建深层可变副本(mutableDeepCopy),如果不行,再尝试创建可变副本(mutableCopy),再不行再创建常规副本(copy),
    这样保证每个对象都创建了副本。
    我的问题是,如果对象a尝试mutableDeepCopy失败,接着去创建可变副本甚至常规副本,
    那么这个副本还是深层可变副本吗,不是的话,他怎么能保证a的副本被删除或者改变的时候不会影响到a自己的内容呢?



    首先,书本中的例子给了我们三种情况,

     if ([oneValue respondsToSelector:@selector(mutableDeepCopy)])
            oneCopy = [oneValue mutableDeepCopy];
     else if ([oneValue respondsToSelector:@selector(mutableCopy)])
            oneCopy = [oneValue mutableCopy];
    if (oneCopy == nil)
            oneCopy = [oneValue copy];
    
    可是我们却只会用到其中一种,大可将其余两种多余的删除掉,

    因为书本复制的对象是一个plist文件,并且严格遵守一个键对应一个数组,并且数组中均为字符串,所以我们也可以这样写.m文件

    //        if ([oneValue respondsToSelector:@selector(mutableDeepCopy)])//本实例数组中没有字典类型所以不需要对字典进行遍历
    //           oneCopy = [oneValue mutableDeepCopy];
    //        else if ([oneValue respondsToSelector:@selector(mutableCopy)])
            if ([oneValue respondsToSelector:@selector(mutableCopy)]) 
            oneCopy = [oneValue mutableCopy];
    //        if (oneCopy == nil)//数组均不为空,所以不需要考虑这种情况
    //            oneCopy = [oneValue copy];

    那什么时候才会用到其余两种情况呢?

    当数组为空(nil)时会用到

    //        if (oneCopy == nil)//数组均不为空,所以不需要考虑这种情况
    //            oneCopy = [oneValue copy];

    当字典的值--数组中还有字典的时候会用到

    //        if ([oneValue respondsToSelector:@selector(mutableDeepCopy)])//本实例数组中没有字典类型所以不需要对字典进行遍历
    //            oneCopy = [oneValue mutableDeepCopy];

    这个方法是针对字典的而设立的,并且只有字典才能响应这个方法。为什么呢?

    NSString 和NSArray 要由mutableCopy进行处理。为什么呢?

    下面对这两个问题做一下解答:

    观察一下.m文件的开头,

    @implementation NSDictionary(MutableDeepCopy)
    - (NSMutableDictionary *)mutableDeepCopy ;
    
    于是就知道,这不是一般的方法,在NSDictionary 后面加了一个“()”,这是什么意思?这是一种全新的方法,叫分类方法。就是将NSDictionary 额外地添加了一种函数,即扩展出了一种功能,所说的就是这个mutableDeepCopy函数,所以mutableDeepCopy方法是隶属于NSDictionary类的,是 NSDictionary的分类方法,所以是针对 NSDictionary类型数据进行的深拷贝。(关于分类方法可以参考:
    点击打开链接


    这是一个递归方法,可能不好理解,为什么我们自定义了一个函数,在自己定义的函数中还要去调用自己呢?而这就叫递归。

    为了理解什么叫做递归,我们做一个比喻,我们将需要深复制的字典比作一个压缩包,深复制方法就好像解压缩软件,字典中的值相当于压缩包中的文件,但压缩包中的文件,也可能出现这种情况:压缩包中的文件还是压缩包。也就是说:已经把压缩包用解压缩软件解压了,可是为了解压“缩压缩包中的压缩包”,我们还是得用刚用到的解压缩软件,就好像我们为了深复制字典中出现的字典,甚至字典中的字典的字典,还得用同一个方法:mutableDeepCopy。而这,就叫递归!



    那为什么说只需要下面的一种方法就足够了呢?

        if ([oneValue respondsToSelector:@selector(mutableCopy)]) 
            oneCopy = [oneValue mutableCopy];
    首先,你要了解Foundation类,NSArray  NSMutableArray NSMutableDictionary NSDctionary NSString都是Foundation类。而Foundation类已经遵守了<NSCopying>和 <NSMutableCopying>协议,即实现了copy和mutableCopy方法,因此Foundation对象可以使用这些方法创建对象的副本或可变副本。(更多Foundation类信息,可参照点击打开链接


    如果你要复制的对象是一个plist文件,并且严格遵守一个键对应一个数组,并且数组中均为字符串,就像这本书中的例子一样,我们也可以这样写.m文件

    #import "NSDictionary-MutableDeepCopy.h"
    
    @implementation NSDictionary(MutableDeepCopy)
    - (NSMutableDictionary *)mutableDeepCopy {
        NSMutableDictionary *returnDict = [NSMutableDictionary dictionaryWithCapacity:[self count]];
        NSArray *keys = [self allKeys];
        for (id key in keys) {
            id oneValue = [self valueForKey:key];
            id oneCopy = nil;
            
    //        if ([oneValue respondsToSelector:@selector(mutableDeepCopy)])   //本实例数组中没有字典类型所以不需要对字典进行遍历
    //            oneCopy = [oneValue mutableDeepCopy];
    //        else if ([oneValue respondsToSelector:@selector(mutableCopy)])
            if ([oneValue respondsToSelector:@selector(mutableCopy)]) 
            oneCopy = [oneValue mutableCopy];    
    //        if (oneCopy == nil)      //数组均不为空,所以不需要考虑这种情况
    //            oneCopy = [oneValue copy];
            [returnDict setValue:oneCopy forKey:key];
        }
        return returnDict;
    }
    

    而这一种mutableCopy方法如何确保

           a的副本被删除或者改变的时候不会影响到a自己的内容呢?

    答:NSString NSArray 经mutableCopy方法复制后就变成了可变副本。

    如果想深入理解,这就涉及到深拷贝和浅拷贝的问题,这个问题我在上篇文章中已经进行了详细论述,请点击打开链接:iOS开发中表视图搜索栏实现中的Objective-C 深浅拷贝问题






    作者:
    出处:http://www.cnblogs.com/ChenYilong/(点击RSS订阅)
    本文版权归作者和博客园共有,欢迎转载,
    但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    asp.net过滤数据中有异常数据字符串
    微信内置浏览器的 User Agent的判断
    最近突然想了很久还是开博每天写点什么
    Sonar-scanner 插件配置应用
    存clob的值
    动态代理
    在oracle函数中不可直接将变量作为sql语句中的参数
    按照行、列进行统计(按两个维度进行统计)
    查询关联不上的数据,三张表查询
    前台页面——js/jq循环
  • 原文地址:https://www.cnblogs.com/ChenYilong/p/2808622.html
Copyright © 2011-2022 走看看