LXFoundation for Cocoa programmers

做为一个 OSX 和 iOS 软件开发者,使用 Objective-C 和 Cocoa 开发应该算是王道。尽管 Apple 为开发者提供了一系列方便的类和函数,但是绝对所有 Cocoa 开发者都遇到过这样让人头痛的问题:

Cocoa 自带的容器 NSMutableArray 和 NSMutableDictionary 总是无法强壮的处理一些不正确的值。结果往往是导致程序轻则异常,重则崩溃。而更为难的是,当程序变得庞杂起来的时候,xcode 的 debugger 很难定位这样一个错误。

下面我在 GitHub 上发布一个我自己写的开源库 LXFoundation 目标就是解决这类问题。我已经把它用在了自己的软件中,目前表现稳定。

项目地址

https://github.com/keefo/LXFoundation

详细介绍

从 Class Clusters 说起

在 Cocoa 中有一种奇葩的类存在,有程序员抨击它是 OOP 模式的破坏者,这就是 Class Clusters。面向对象的编程教育我们:“类可以继承,子类具有父类的方法”。而 Cocoa 中的 Class Clusters 虽然平时表现的像普通类一样,但子类却没法继承父类的方法。而 NSMutableArray, NSMutableDictionary 就是这样一个玩意。

为何如此?因为 Class Clusters 内部其实是由多个私有的类和方法组成。虽然它有这样的弊端,但是好处还是不言而喻的。例如,NSNumber 其实也是这种类,这样一个类可以把各种不同的原始类型封装到一个类下面,提供统一的接口。这正设计模式中的抽象工厂模式。

正因为它的特殊性,所以你经常会在 Cocoa 开发论坛之类的地方,看到很多程序员建议,最好不要自己 subclass NSMutableDictionary 或者 NSMutableArray,而尽量使用 Category。但是实际上 category 并不能处理本身类方法的异常抛出。并且除了增加功能外,无法带来调试方面的优势。 这就是为何我也写 LXFoundation 的原因。写自己的容器可以强壮代码,同时便于调试。

如何 Subclass Class Clusters

说了上面这么多,那么到底要如何 subclass 这种类呢? Apple 文档里指明了,subclass 这种类,程序员需要自己实现一系列称为 primitive methods 的函数。这些函数就是构成这种类的必要单元。例如,NSMutableDictionary 文档提到,它的 primitive methods 包括:

而 NSMutableArray 的 primitive methods 包括:

这里我就不再继续写实现细节了,如果你已经感兴趣了,请到github直接阅读源代码和实例。

LXFoundation 的特性

LXFoundation 可以处理异常数据的插入,修改等操作,不会抛出异常 crash 你的程序。并且它在 arc 或者 non-arc 环境下都运行良好。其性能和 NSMutableDictionary, NSMutableArray 基本一致。

更妙的一个好处是,使用 LXFoundation 你不需要修改自己的一行代码。只要在 prefix-pch 里加几行宏指令即可:

这几句宏指令,自动帮你把代码内的容器替换成 LX 前缀,而在你不需要 LXFoundation 的时候,删除掉这几句即可,你的程序就又回到了原来的 NS-Container 模式了。

使用前的注意事项

目前为止,我只能想到1个使用前的注意事项。当你的代码中有地方是需要 NSMutableArray,NSMutableDictionary 抛出异常才能正确工作的时候,用 LXFoundation 就需要更加谨慎。

例如,考虑如下代码,如果你希望有时候 exception 抛出并且要在 catch block 里处理一些重要逻辑,那么 LXFoundation 将无法融入你的代码。

未来计划

目前 LXFoundation 只包含2个最基本的类。今后随着我的程序需要,我会陆续为其增加必要容器实现。

  • Vitosub

    感谢博主的奉献精神,试用一下!

  • 虽然目前还只有两个类,但确实不错,只是担心走了捷径之后,以后的代码就会忘记objc的一些规范了,让人变懒了!

  • treylin

    刚在 GitHub 上把这个项目 clone 了下来 看了代码 总体很好啊 我在开发是好像也遇到这样的问题 怎么就不会自己些点东西来解决 反思一下  还有就是提点建议 项目的代码规范还不够统一 1. 像 – (void)后面接方法名的之前,有时有空格,有时没有 2. 方法的左花括号有些和方法的同一行,有些是另起一行  3. 其实比如 #pragma mark Modifying Contents 是不起作用的 要这样 #pragma mark – Modifying Contents 在 ‘mark’ 后面加 ‘-‘  可能我比较代码洁癖 总体挺好的 🙂

  • hzhydyy

    Nice,  另外,老哥能麻烦问问你这的disqus怎么是中文的啊?怎么弄的呢.  

  • hzhydyy

    我在做一个cocoa下的开发,在NSTableView中使用NSTableCellView,   比如正在播放某一条的时候我想在这条上添加一个状态, 显示为正在播放, 我是新手, 暂时还不知怎么去做. 能否给点思路?

    我的QQ:405200540.  希望能跟您学习啊!

    看了您的开源代码,学到很多东西,再次感谢!!

  • jzh

    请问你如何测试效率的

    • keefo

      帖子里写着呢。

  • Er

    赞一个,平时开发还是尽量用原生的,上线替成你这个,估计crash率应该会降下来:)

    建议:是不是可以考虑加一个block来做为nil等情形的个性化处理。

  • PhilCai

    我们现在是hook了几个方法。。