目前在做的一个项目迁移到 React Native 已经一年多了,也意味着踩了一年的坑,感觉光填上各种奇怪的坑都会让自己的水平提升不少。最近解决了一个占比接近 10% 的崩溃,在这里记录一下。
让 WKWebView 支持 NSURLProtocol
最近把公司的项目从 UIWebView 迁移到了 WKWebView,因为之前大体上还是遵从了 Apple 的 API 没有过度地去 hack,而且 WebViewJavascriptBridge 也同样支持 WKWebView,所以迁移过程没有想象中那么痛苦,只要把 UIWebViewDelegate 的方法改成 WKUIDelegate 和 WKNavigationDelegate 对应方法就好了。
UIWebView 与 3D Touch 的自定义交互
0x00 3D Touch API 处理 UIWebView 的局限
从 iOS 9 开始,UIKit 新增了 3D Touch 相关接口,如果使用苹果推荐的 storyboard 搭建 UI,勾选了 Preview & Commit Segues
选项之后就可以零代码实现系统级的 3D Touch 效果;用代码实现也很简单,只要实现 UIViewControllerPreviewingDelegate
协议,然后调用 - [UIViewController registerForPreviewingWithDelegate:sourceView:]
方法,就可以对任意 UIView 进行 Peek 和 Pop 操作了。
实际上,尽管 - [UIViewController registerForPreviewingWithDelegate:sourceView:]
方法的第二个参数接受的是任意的 UIView,但在 UIWebView 和 WKWebView 上按压的操作却是没有效果的。虽然苹果针对这两个 WebView 提供了 allowsLinkPreview
属性做了特殊处理,但这也仅仅是调用了 Safari 打开链接,实际应用中经常要针对某些特殊的链接进行应用内跳转,这是 allowsLinkPreview
无论如何也完成不了的。
View Controller 转场实现机制分析
众所周知,iOS 的 View Controller 的转场效果本质上是基于“当前视图消失和下一视图出现”所进行的动画。如果是自己实现的 UIViewControllerAnimatedTransitioning 协议,那么此动画就由 - animateTransition:
方法来提供;如果没有实现此协议则此动画由系统提供。以结构如下图的 Navigation Controller 为例:
在 iOS APP 崩溃时弹出友好提示框
昨天补了 iOS RunLoop 相关的基础知识,在一部讨论 RunLoop 实现细节的视频的最后面,@sunnyxx 讲到了一个很有意思的黑科技————“让 App 在 Crash 的时候回光返照”,内容大致如下:
1
2
3
4
5
6
7
8
9
10
11 //取当前 run loop
CFRunLoopRef runLoop = CFRunLoopGetCurrent();
//取 run loop 所有运行的 mode
NSArray *allModes = CFBridgingRelease(CFRunLoopCopyAllModes(runLoop));
while (1) {
for (NSString *mode in allModes) {
//在每个 mode 中轮流运行至少 0.001 秒
CFRunLoopRunInMode((CFStringRef)mode, 0.001, false);
}
}
>
对于因为接收到 crash 的 signal 而挂掉的程序,可以在接收到 crash 的信号之后重新起一个 run loop 然后跑起来。但是这个并不能保证 app 能像原来一样能正常运行,只能是利用它来在奄奄一息的状态下弹出一些友好的错误信息。
检测 iOS 项目中的内存泄漏
一般来说,在 ARC 环境下,只要在使用 delegate、NSTimer、block 的时候注意一下不要出现循环引用,那么 Objective-C 对象的内存泄漏问题就可以轻松避免。
但是在实际项目中,一些错误的结构设计可能会导致难以发现的泄漏问题,比如像 A -> B -> C -> ... -> A
这种长环的循环引用,或者一个实例被一个 单例 持有,在 review 的时候可能会漏掉这些问题,这时就需要流程化的方式来检测了。
给 Objective-C 中的 Protocol 加上默认的实现
扩展 UIButton 和 UICollectionViewCell 的响应区域
使用 Objective-C Runtime 解决 unrecognized selector 错误
0x01 前言
NSOperation
类有一个属性 name
,用以标记一个 NSOperation 对象。苹果提供这个属性的本意是为了调试方便,但实际上通过它我们还可以简便地实现一些业务需求,比如加入 NSOperationQueue
前检查去重和排序什么的。
但很可惜,这个属性是 NS_AVAILABLE(10_10, 8_0)
的,换言之如果在 iOS 7 以下的系统上使用这个属性的话,控制台会打印这样一行错误:
unrecognized selector sent to instance
如果项目需要兼容 iOS 7 系统的话,我们就需要寻找一种方法,在 iOS 7 上也能方便地标记一个 NSOperation 。
使用git log命令自动生成周报
2016-3-15 update: 项目已提交至GitHub,地址https://github.com/yeatse/git-log-weekly-report/
最近公司主管突然让我们每周末发周报了,具体就是总结一下上周都干了什么之类的。从小学开始就经常不交作业的我心里是一百个不愿意,但是这个是跟绩效挂钩的,人总不能跟钱过不去嘛,没办法只能养成习惯去写周记了。
当然,作为一个懒惰的程序员,每周让我拿出半个小时的时间去整理周报这种事我是不会去做的。好在现在的项目是用git作为版本控制工具的,用git log命令的话,只要一行就可以在屏幕输出日志内容了:
1 | $ git log --author="yeatse" --format="%cd : %s" --since=last.Monday --reverse --no-merges --date=format:'%F %T' |
具体的参数意义在git-log Documentation上可以找到(其中date format选项需要升级git版本到v2.6.0rc以上才有效)。输出的结果大概是这个样子:
1 | 2016-02-29 22:04:54 : Update elctron-prebuilt version. Fix #11. |