XCode 4 无法编译一个非常大的数组,以及关于 NSArray/NSString 开销的问题
Posted
技术标签:
【中文标题】XCode 4 无法编译一个非常大的数组,以及关于 NSArray/NSString 开销的问题【英文标题】:XCode 4 failing to compile a very large array, and questions about NSArray/NSString overhead 【发布时间】:2011-04-17 11:58:40 【问题描述】:我是 Objective C 和 XCode 的新手,目前正在开发我的第一款 iPhone 游戏。游戏必须对超过 250,000 个单词的拼字游戏词典进行一些非常快速的拼写检查,理想情况下,我可以在单帧中检查 100 多个字符串和单词列表。
我之前在 C 和 actionscript 2 中写过这个没有问题,只是使用标准的二进制搜索,但我不确定在 Objective C 中使用 NSString 和 NSArray 等选项实现这个的最佳方法。
目前最大的问题是它甚至根本无法编译。如果我创建一个填充了 NSStrings 的 NSArray,XCode 只会挂起但不会崩溃。我让它编译了大约 30 分钟,没有结果。我使用的代码:
words=[NSArray arrayWithObjects:@"aa", @"aah", ...250,000 words... @"zyzzyvas" ,nil];
当单词列表减少到几百个单词时,它可以编译并正常工作。
谁能解释一下为什么会失败,或者提出更好的解决方法?
接下来我要尝试的是将单词表拆分为许多更小的部分;由第一个字母分隔,也许还有字母的数量,但这意味着需要大量重新格式化巨大的文本文件以进行反复试验,这很可能会碰上同一堵墙。
这个问题的另一部分是关于 NSArray 的速度和 NSString 的开销与老式 C 风格的 char 指针数组相比的一般查询。如果 NSStrings 甚至包含一些额外的标头或函数指针或其他字节,那么在 iPhone 应用程序中创建 250,000 个字节可能是错误的做法,对吧?
任何建议都将不胜感激。
【问题讨论】:
【参考方案1】:我真的很想为此使用数据库 - 内置 SQLite 是一个理想的解决方案。
也就是说,如果您手头有现有的 C 解决方案,那么您没有理由不能按原样使用它(并不是说您必须使用 Cocoa 类毕竟),尽管您需要在内存使用方面小心谨慎,同时牢记 ios 设备的限制。
【讨论】:
+1 - SQLite 数据库意味着您不必将整个列表加载到内存中。【参考方案2】:消息直接转换为 C 函数调用,因此您的代码会这样做:
words = objc_msgSend(NSArray, @selector(arrayWithObjects:), @"aa", @"aah", ...250,000 more arguments...);
当在 C 中调用一个函数时,它的参数首先被压入堆栈。仅仅几百个单词就不可能耗尽堆栈空间,但完全有可能在 250,000 个单词。因此,您可能会遇到编译器对参数数量或参数数据总大小的限制。
肯定有更好的方法来做你正在做的事情。至少,使用@smorgan 的建议并从文件中读取列表。最好使用内存映射文件,这样您就不必一直将整个文件保存在内存中——让操作系统为您处理文件的部分加载和加载。
【讨论】:
【参考方案3】:与其将数十万个静态字符串编译到您的应用程序中,不如将单词列表保存在一个文件中并在启动时读取它?
【讨论】:
这是我可能需要考虑的一个选项,尽管我不希望用户能够编辑单词列表,因为它可能会启用分数作弊。 因此计算单词列表的哈希,并将哈希编译到应用程序中。然后在运行时读取它之前,重新哈希它确保哈希匹配。 @Adam 除非他们越狱他们的 iOS 设备等,否则他们将无法访问捆绑包中的文件或您的应用程序的文档目录。【参考方案4】:您可以通过使用NSAarray +initWithContentsofFile:
方法从属性列表文件中读取整个数组来解决您的编译时问题。
但是,使用带有手动编码二进制搜索的 NSArray 似乎是错误的工具。只是坚持 Cocoa Touch Foundation 课程,NSSet
似乎比NSArray
更适合。
无论如何,您担心创建这么多对象的开销可能是正确的; middaparka 说,使用您现有的 C 解决方案或数据库听起来都是更好的选择。
【讨论】:
以上是关于XCode 4 无法编译一个非常大的数组,以及关于 NSArray/NSString 开销的问题的主要内容,如果未能解决你的问题,请参考以下文章
Xcode 9:使用 Swift 3.1 编译的模块无法在 Swift 4.0 中导入
有没有办法在 Xcode 4 中为 ARM 而不是 Thumb 编译?