Foundation Objective-c:带数组的字典;字典与字典

2024-03-09

假设我有一个 NSDictionary,其中包含 NSArray 和 NSDictionary 的两个子集合:

NSMutableDictionary *mkDict(void){
    NSMutableDictionary *dict=[NSMutableDictionary dictionary];
    NSMutableDictionary *sub=[NSMutableDictionary dictionary];
    NSMutableArray *array= [NSMutableArray array];
    [dict setObject:array forKey:@"array_key"];
    [dict setObject:sub forKey:@"dict_key"];
    return dict;
}

有多种方法可以访问子集合的单个元素,我选择对其中三种进行计时。

第一种方法是通过访问父元素的键来间接访问子元素:

void KVC1(NSMutableDictionary *dict, int count){

    for(int i=0; i<count; i++){
        char buf1[40], buf2[sizeof buf1];
        snprintf(buf1,sizeof(buf1),"element %i", i);
        snprintf(buf2, sizeof buf2, "key %i", i);

        [[dict objectForKey:@"array_key"] 
          addObject:
             [NSString stringWithUTF8String:buf1]];
        [[dict objectForKey:@"dict_key"] 
          setObject:[NSString stringWithUTF8String:buf1] 
          forKey:[NSString stringWithUTF8String:buf2]];
    }
}

第二种是使用KeyPath访问:

void KVC2(NSMutableDictionary *dict, int count){

    for(int i=0; i<count; i++){
        char buf1[40], buf2[sizeof buf1], buf3[sizeof buf1];
        snprintf(buf1,sizeof(buf1),"element %i", i);
        snprintf(buf2, sizeof buf2, "key %i", i);
        snprintf(buf3, sizeof buf3, "dict_key.key %i",i);

        [dict insertValue:
             [NSString stringWithUTF8String:buf1] 
            atIndex:i inPropertyWithKey:@"array_key"];
        [dict setValue:
             [NSString stringWithUTF8String:buf1] 
            forKeyPath:
             [NSString stringWithUTF8String:buf3]];
    }
}

第三种与第一种类似,是访问指向子元素的指针,然后使用该指针:

void KVC3(NSMutableDictionary *dict, int count){

    NSMutableArray *subArray = [dict objectForKey:@"array_key"];
    NSMutableDictionary *subDict = [dict objectForKey:@"dict_key"];

    for(int i=0; i<count; i++){
        char buf1[40], buf2[sizeof buf1];
        snprintf(buf1,sizeof(buf1),"element %i", i);
        snprintf(buf2, sizeof buf2, "key %i", i);

        [subArray addObject:[NSString stringWithUTF8String:buf1]];
        [subDict 
           setObject:
            [NSString stringWithUTF8String:buf1] 
           forKey:
            [NSString stringWithUTF8String:buf2]];
    }
}

这是计时代码:

#import <Foundation/Foundation.h>
#import <mach/mach_time.h>

// KVC1, KVC2 and KVC3 from above...

#define TIME_THIS(func,times) \
({\
mach_timebase_info_data_t info; \
mach_timebase_info(&info); \
uint64_t start = mach_absolute_time(); \
for(int i=0; i<(int)times; i++) \
func ; \
uint64_t duration = mach_absolute_time() - start; \
duration *= info.numer; \
duration /= info.denom; \
duration /= 1000000; \
NSLog(@"%i executions of line %i took %lld milliseconds", times, __LINE__, duration); \
});

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSMutableDictionary *dict=mkDict();
    NSMutableDictionary *dict2=mkDict();
    NSMutableDictionary *dict3=mkDict();

    TIME_THIS(KVC1(dict,1000),10);
    TIME_THIS(KVC2(dict2,1000),10);
    TIME_THIS(KVC3(dict3,1000),10);

    if([dict isEqualToDictionary:dict2])
        NSLog(@"And they are the same...");
    [pool drain];
    return 0;
}

结果如下:

10 executions of line 256 took 57 milliseconds
10 executions of line 257 took 7930 milliseconds
10 executions of line 258 took 46 milliseconds
And they are the same...

问:为什么 OS X Snow Leopard / Lion 建议的使用 KeyPaths 的方法如此缓慢?如果你增加尺寸count到 10,000 或更多时,KVC2 变得无限慢,而其他两种方法则线性增加。

难道我做错了什么?是否有更好的习惯用法来访问字典中子集合的单个元素?


In KVC2(),你发送

[dict insertValue:[NSString stringWithUTF8String:buf1] 
          atIndex:i
inPropertyWithKey:@"array_key"]; 

该方法的文档说明如下:

方法insertIn<Key>:atIndex:如果存在则被调用。如果没有相应的符合脚本 KVC 的方法(insertIn<Key>:atIndex:) 被发现,该方法调用mutableArrayValueForKey:并改变结果。

由于消息正在发送至dict,一个实例NSDictionary,没有-insertIn<Key>:atIndex:方法,因此-mutableArrayValueForKey:已发送。此方法的文档说明如下:

返回值一个可变数组代理,提供对 key 指定的有序对多关系的读写访问。

讨论添加到可变数组中的对象将与接收者相关,而从可变数组中删除的对象将变得无关。默认实现识别与 valueForKey: 相同的简单访问器方法和数组访问器方法,并遵循相同的直接实例变量访问策略,但始终返回可变集合代理对象,而不是 valueForKey: 将返回的不可变集合。

所以发生的事情是这样的在每次迭代时:

  1. 代理可变数组被创建为可变副本原始数组的;
  2. 一个对象被添加到代理数组中;
  3. 代理数组将相同的对象添加到原始数组中。

如果您使用 Instruments 来分析您的程序,您会注意到大约 50% 的处理时间花费在-[NSKeyValueSlowMutableArray insertObject:atIndex:]— 我认为可以肯定地假设NSKeyValueSlowMutableArray是代理数组,它的名称应该是其性能的线索。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Foundation Objective-c:带数组的字典;字典与字典 的相关文章

  • 为什么 Objective-C 使用 YES 和 NO 而不是 1 和 0? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 Objective C 使用 YES 和 NO 而不是 1 和 0 是否有任何技术原因 或者只是为了使其更具可读性 使其更具可读性is技术原因
  • Xcode 4 Core Data:如何使用在数据模型编辑器中创建的获取属性

    如何在 Xcode 4 中实现获取的属性 Here is an example of two entities a book and a page 我按照此处的指南创建了一个获取的属性 该属性使用变量 FETCH SOURCE 引用来自源实
  • 使用 twitterkit 将图像发布到 Twitter

    我正在尝试使用 Twitter 的新 TwitterKit 和自定义 UI 发布图像和推文 他们提供的唯一文档是如何用他们的观点来做这件事 所以我可以弄清楚如何在没有图像的情况下做到这一点 NSMutableDictionary messa
  • 如何在pop UIViewController中删除UIParallaxDimmingView?

    我有一个UIViewController vc1这是在之后推送的UIViewController vc2 Both vc1 and vc2具有透明背景 问题 当我尝试弹出时vc2使用交互式弹出手势 从边缘平移 在我看来堆栈显得很神秘UIPa
  • 我应该在我的 iOS Objective-C 项目中使用它吗?

    Xcode 中的 构建设置 中的 Mach O 类型是什么 应该设置什么 它有这些选项 可执行文件 动态库 捆绑包 静态库 可重定位对象文件 自从我将其从可执行文件更改为静态库以来 我遇到了错误 Apple Mach O 链接器错误组 我的
  • 将 CFIndex 转换为 NSUInteger?

    我如何转换typedef signed long CFIndex to typedef unsigned int NSUInteger 如果我使用一个可以吗 CFIndex作为类型的参数NSUInteger 我还没有铸造它 编译者似乎也不介
  • UITableView 无法一直滚动到底部[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我只是好奇 我做了一些UITable
  • 小视频播放

    根据我从互联网收集的信息 MPMoviePlayerController 类不支持小视频播放 因此 为了死马当活马医 我想知道可以使用什么样的方法来让小视频在屏幕的一角播放 而不中断屏幕的其余部分 到目前为止 我们已经遇到了两种可行的解决方
  • 方法调用中的插入符[重复]

    这个问题在这里已经有答案了 我正在阅读本教程 并遇到了这行代码 这让我感到困惑 localSearch startWithCompletionHandler MKLocalSearchResponse response NSError er
  • 在后台每 X 分钟执行一次函数不起作用

    我使用此代码每 X 分钟执行一次函数 void executeEveryOneMinute self myFunction dispatch after dispatch time DISPATCH TIME NOW int64 t 60
  • 使用 iPhone 控制蓝牙音频设备

    我正在寻找为 iPhone 编写应用程序 它将能够控制汽车中的收音机和 CD 播放器 收音机和播放器具有可用的蓝牙连接 我开始这个问题是为了获得这个地方所需的所有信息 我有几个问题 但如果您发现任何我没有要求的对我开始开发此应用程序不重要的
  • xcode“将源编译为”覆盖特定文件

    我有一个项目 必须将 编译源为 值设置为 Objective C 不 根据文件类型 在我的主项目中不起作用 我从框架 特别是 OpenFeint 获得的文件有问题 该文件在编译为 Objective C 时出现编译错误 error poin
  • 通过应用程序组在应用程序之间通信和保存数据

    iOS 8 昨天发布了一个有关应用程序组的新 API 以前在应用程序之间共享数据和通信有点混乱 我相信这正是应用程序组旨在纠正的问题 在我的应用程序中 我启用了应用程序组并添加了一个新组 但我找不到任何有关如何使用它的文档 文档和 API
  • [[NSMutableDictionary alloc] initWithObjects:...] 和 [NSMutableDictionary DictionaryWithObjects:...] 之间的区别?

    仍在学习 Objective C iPhone SDK 我想我知道为什么这不起作用 但我只是想确认一下 In awakeFromNib 如果我使用 NSMutableDictionary alloc initWithObjects 它实际上
  • NSOperation 中委托的使用

    我正在尝试利用CLLocationManager in an NSOperation 作为其中的一部分 我需要能够startUpdatingLocation然后等到收到 CLLocation 后才完成操作 目前我已经完成了以下操作 但是委托
  • malloc:***错误:已释放对象的校验和不正确 - 对象可能在释放后被修改

    我的 iOS 应用程序有一个大问题 它有时会崩溃 而没有详细的调试错误 堆栈跟踪为空 这是堆栈跟踪中仅有的两行 UIApplicationMain 中的 符号存根 UIHostedTextServiceSession DismissText
  • Xcode 4 调试器代码完成

    首先 很高兴他们尝试在 Xcode 4 中的 gdb 命令提示符上完成代码 但在当前状态下 它使得使用命令提示符来调查目标 c 对象几乎不可能 当我打字时 它自动将单词补全为我不想要的内容 并且如果不手动选择文本并将其删除 然后重新开始 则
  • ios 11 - UIBarButtonItem 内的 UIButton 导致自动布局错误

    我在将 UIButton 添加到 UIBarButtonItem 时遇到了一个已知问题 我尝试按照建议添加自动布局约束堆栈溢出 https stackoverflow com a 46336639 505603但我收到如下所述的错误 UIB
  • 将捕获的图像精确裁剪为 AVCaptureVideoPreviewLayer 中的外观

    我有一个使用 AV Foundation 的照片应用程序 我使用 AVCaptureVideoPreviewLayer 设置了一个预览层 它占据了屏幕的上半部分 因此 当用户尝试拍照时 他们只能看到屏幕上半部分看到的内容 这很好用 但是当用
  • 如何将unix时间戳转换为iphone中的nsdate [重复]

    这个问题在这里已经有答案了 可能的重复 从 Unix 时间戳创建 NSDate https stackoverflow com questions 5827240 create nsdate from unix timestamp 我有一个

随机推荐