关于iOS项目的国际化,之前有写过一篇文章,不过不是很系统,也有不少纰漏,还特地写过一篇填坑文,但是因为太坑了,所以不了了事。这段时间又踩了不少坑,也啃了啃官方的文档,特此整理10条Tip,有一些问题不会经常遇到,有些细节也很容易被忽略,不过大部分应该还是很有用的!
如果你之前对iOS的国际化一无所知,推荐看一下这篇文章,很精炼也很完整——《Internationalization Tutorial for iOS [2014 Edition]》

阅读全文 »

关于Aspects

https://github.com/steipete/Aspects

aspects是针对面向切面编程:Aspect Oriented Programming(AOP)的一种实现方案。AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。
以埋点为例,虽然现在已经有像友盟这样强大的第三方埋点方案,但是这并不能满足一些公司的业务需求,如果要完全自定义地进行埋点,监听并统计用户的行为,使用传统的方案,必然导致对整个项目的代码进行大范围的修改。而使用面向切面编程的思想,则可以将埋点和系统原有的逻辑解耦,悄悄地完成埋点。


下面来看看Aspects是如何帮助我们实现这点的。

还是举个例子来说明:
假设我们要统计某些页面的显示的次数,以往使用友盟来统计页面访问我们会这么做

1
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    //do something
    if(self.title){
        [MobClick beginLogPageView:self.title];
    }
}

聪明一点的做法当然是可以把它写在基类。这样至少不会影响太多的代码。但是如果是其他一些更加个性化的埋点,比如说点击某个按钮,通过不同的方法进入某个页面,注册所消耗的时间统计等等等等。。。。

有了Aspect 我们可以这么做

1
[UIViewController aspect_hookSelector:@selector(viewWillAppear:) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) {
    UIViewController* viewController = aspectInfo.instance;
    if (viewController.title) {
        [MobClick beginLogPageView:viewController.title];
    }
} error:NULL];

当然,这块代码完全可以和原有的逻辑隔离。
先解释一下,Aspects针对NSObject实现了aspect_hookSelector的方法,顾名思义,使用一个钩hook住了UIViewController的viewWillAppear方法,withOptions可以有两个参数,一个是AspectPositionAfter,另一个是AspectPositionBefore,分别代表在原有方法执行前或者原有方法执行后执行该block,根本上相当于利用oc的runtime特性替换了原有的方法。
通过aspectInfo中的instance和arguments属性可以分别获得方法的方法体和参数,基本上也就是获得了整个方法执行的上下文。
特别需要注意的是,同一个继承树上的同一个方法只能被hook一次

阅读全文 »

Bug的发现

一次偶然的机会,发现了QQ的一个Bug。
复现过程如下:

  • 在QQ中通过任意途径打开一个pdf或者word文档
  • 单击全屏显示
  • 滑动返回到一半终止返回(再次回到浏览界面)
  • 再次滑动返回,就会观察到这样的场景————导航栏消失不见或者导航栏错位

当然,这是一个必现的Bug,而且我也相信类似的操作在很多别的应用中也会引发这个Bug,归根结底,这是iOS在引入了滑动返回后导航栏本身的一个Bug

阅读全文 »