站在巨人的肩膀上:QA恋 iOS 客户端是怎样炼成的

QA恋iOS 客户端是我的 iOS 开发处女作,今天给大家分享一下这款 App 是如何写出来的,这里并不打算讲具体的实现代码细节,只是介绍一下开发过程中用到的开源代码以及如何处理遇到的问题。

有人说,目前国产手机还只是停留在堆砌硬件的阶段,缺乏自己的核心技术;那么请允许我把我自己目前的 iOS 开发水平定义为:“堆砌他人的优秀代码和开源项目”,当然,也可以理解为是“君子善假于物也”或者“站在巨人的肩膀上”

网络请求

在移动客户端的开发中,网络请求毋庸置疑是非常重要的一部分,尽管使用苹果官方提供的 NSURLConnection 和 NSURLRequest 网络 API 固然能够解决我们大部分的 Web Service 请求,但是使用起来不是很简洁方便,因此强烈建议在实际开发中使用现有的开源而优秀的第三方网络框架。

在QA恋的 iOS 客户端中,我采用的是 MKNetworkKit,它是一个使用十分方便,功能又十分强大且完整的 iOS 网络编程代码库,完全基于 ARC。它只有两个类,它的目标是使用像 AFNetworking 这么简单,而功能像 ASIHTTPRequest 那么强大。

MKNetworkKit 最吸引我的是它的缓存机制,几乎不需要其他额外的代码,只要简单设置,似乎一切它都会帮你悄悄做好了,不过相比 AFNetworking,MKNetworKit 的使用与维护者较少,Github 上作者也已经有两年不更新代码了,框架本身存在一些小Bug,不过都可以解决,如果你想处理更复杂的网络请求,还是推荐 AFNetworking 框架。

页面左右滑动 Tab 实现

在 QA恋客户端中,多处使用到左右滑动切换视图内容的分段选择控件,如下面两张图所示,在首页中有【我的关心、QA 广场】两个切换子 Tab,在发现页中有【QA 热、遇见 Ta、搜索】三个切换子 Tab,iOS 自带的 Segmented Control 无法达到这样的效果,不能手势滑动只支持点击 Tab 切换,所以在这里使用的是第三方提供的:HMSegmentedControl,支持多种顶部标题样式,点击标题切换事件,手势滑动切换事件。

下拉刷新,上拉加载实现

自从 Twitter 客户端引入下拉刷新列表后,它似乎就成为了一种标准的手势,全世界的开发者都在模仿,以至于苹果在 iOS 6 以后自带的 UITableViewController 也支持了下拉刷新事件,不过很遗憾的是,在多数情况下,我们并不希望一个页面仅仅是列表项页面,而是希望它由 UITableView 控件和其他元素组合而成,但 UITableView 并不支持下拉刷新,需要自己实现。这里采用的是:MJRefresh,使用非常简洁,只要在相应的地方引入头文件,添加下拉刷新和上拉加载事件响应,无需其他额外的代码设置。

加载进度条和Toast提示

UIView+Toast: An Objective-C category that adds Android-style toast notifications to iOS. 实现类似安卓系统原生的 Toast 通知那样的样式。(例如:在QA恋的登录页面,用户未填写邮箱就点击登录按钮,弹出 Toast 提示相应信息,这时我希望页面上的其他控件仍是可点击或可编辑的,这是与 MBProgressHUD 不同的。)

MBProgressHUD: 实现各种加载进度条样式的透明指示层(HUD),与 UIView+Toast 不同的是,MBProgressHUD 是 UIWindow 级别的控件,当它被显示时,屏幕上其他元素将不可点击。(举个例子:在 QA恋的登录页面,用户点击登录按钮时,调用 MBProgressHUD 的 show 方法,页面中显示“正在登录…”进度条,后台开始网络请求登录,这时我不希望屏幕上的其他按钮再被用户点击,MBProgressHUD 刚好可以做到这一点,当请求结束后,调用 hide 方法,页面恢复,继续其他操作。)

查看大图

XHImageViewer: 支持图片缩放,多张图片同时左右切换查看,图片打开关闭动画效果等。唯一的不足:如果想在每张图片下加一段文字描述(如下图),则需要自己修改代码实现。

日期选择控件

用户修改生日等资料时,点击列表向总是要弹出一个日期选择列表让用户选择,在 iOS 8 之前,一般采用 UIDatePicker 和 UIActionSheet 结合来实现,但在 iOS 8 以后,UIActionSheet 控件里不允许再插入其他 View,所以这种方法只能弃用,好在 Github 上已有专为 iOS 8 提供弹出的日期选择控件:RMDateSelectionViewController,提供了类似 UIActionSheet 效果的时间和日期选择样式。

汉字分组索引

iOS 自带的 UITableView 支持列表分组显示,但是如何根据每个列表项文字的第一个字的拼音首字母进行分组是需要解决的问题。这里参考了 这篇博文 中提供的方法,先根据 pinyin.h 中提供的 pinyinFirstLetter 方法,获取列表项文字第一个汉字的拼音首字母进行分组,然后在 UITableView 的 sectionIndexTitlesForTableView delegate 进行显示。

表情输入与富文本显示

表情的输入面板的布局基本上是参考微信的表情输入布局,聊天气泡的图文多行显示是基于 MLEmojiLabelTTTAttributedLabel 实现的,这里具体的实现逻辑比较复杂,篇幅有限,不再赘述,有时间写一篇博文详细讲解一下。(左图为 QA恋回复页面,右图为微信聊天页面)

内嵌浏览器

在应用中,我们经常需要打开一些 url 链接,如果总是调用 Safari 打开,会切换出应用,这是一种很不友好的体验,于是绝大部分应用都有基于 UIWebView 的内嵌浏览器来打开 url 链接,这里推荐:TOWebViewController,可以很方便和高效地在 App 中嵌入一个小型的网页浏览器,具有前进、后退、刷新、分享等功能,并且具有加载进度条。

第三方登录、分享、统计

在QA恋的登录页面分别提供了用微博账号、QQ 账号登录,以及支持分享QA恋到微博,QQ,人人,微信等第三方社交平台,如果去挨个开放平台下载集成他们提供的 SDK,将是一件非常繁琐的事,好在这一切 友盟 帮我们做好了,只要在工程中集成友盟提供的 SDK 即可。此外友盟还提供了应用统计,崩溃日志记录,自动检查更新等功能,也是非常方便易用,

推送通知

对于移动设备来说,推送通知无疑也是非常重要的一部分。请期待我接下来的系列博文《细说 iOS 推送通知》,将分别详细讲解如何实现客户端和服务器端的推送技术。

其他

在 QA恋的 iOS 客户端中,除了采用上述提到的开源框架、项目、代码之外,还使用了大量网上很多开发者无私贡献的优秀代码片段和开发教程,如图片的压缩裁剪,字符串的转换处理,获取设备唯一 ID,字符串 MD5 加密哈希计算,日期的转换显示,数据的储存,自定义宏等等,每一部分细说起来都需要大量篇幅,有时间一一分析。

当然,一款优秀的 App,除了需要优秀的开发工程师之外,也外离不开一个优秀的产品经理和优秀的设计师一起协作。

推荐网站、书籍

Google:人生苦短,善用谷歌,技术问题就不要去问度娘了。

GitHub:你可能已经发现,上面贴出的 iOS 开源库都链向了 GitHub,把它说是最大的开源代码库以及版本控制系统一点也不为过,目前绝大部分的开源软件和项目都托管在这上面。

Stack Overflow:国外知名的技术问答社区,你开发过程中遇到的绝大部分问题前人也都已经遇到了,且在这里基本上已经有了详细的问答。当然,国内的 SegmentFault 也是不错的选择。

此外,国内的 Code4AppCocoaChina 上也有大量的优秀 iOS 代码和实例。

最后,多看一些牛人的技术博客,也可以让自己在开发过程中少走弯路,这里有很多中文 iOS/Mac 开发博客列表

如果你还在疑惑 iOS开发如何提高,看看唐巧的这篇博文吧,也许能给你一些建议。

推荐两本我正在看的 iOS 开发书籍:
《iOS开发进阶》 唐巧 著
《Objective-C 高级编程:iOS与OS X 多线程和内存管理》 黎华 译

总结

上文只是地列出了 QA恋 iOS 客户端使用到得开源项目、代码,可能比较零散,其实在实际的开发过程中,遇到的问题通常会更多,但于通过团队讨论和借助互联网资源一般都能一一解决。一个优秀的工程师善于阅读他人优秀代码的能力应该跟自己写出优秀代码的能力一样重要。如果你在项目中同样用到上述开源代码遇到问题,欢迎留言跟我交流讨论。