关于iOS适配的问题

简介

目前阶段的 iPhone APP主要是适配 iOS6与 iOS7两个系统,但是 iOS7相对 iOS6来说变化还是很大的,对于开发者来说要做的事情也不少。这里主要谈谈 APP 如何方便的适配 iOS7与 iOS6下不同的布局。布局主要是 statusbar 和 navigationBar 的适配。

适配方案

在 APP 开发中大部分开发者都会做一个 UIViewController 的基类,这里我们主要针对这个基类来做改动。这样就能在所有的子类 UIViewController 上面生效了

方案一

在基类中自定义 statusBar 和 navigationBar 同时加入一个 contentView。

对于自定义的 statusBar 和 navigationBar 可以在不同的系统中显示成两种不同的风格。而且目前来讲自定义的 navigationBar 应该是比系统自带的 navigationBar 要容易扩展的多

自定义的 contentView 在基类中设置好坐标。然后在所有子类中的控件全部加入到这个 contentView 中。

这种方式我们把 window 分成了三个部分(statusBar/navigationBar/contentView),基类中针对iOS6和 iOS7分别进行设置,在子类中就做到了隐藏 iOS6和 iOS7的变化,可以按照过去的习惯去做布局了

方案二

这种方案是我目前在用的方案。就是自定义 statusBar 和 navigationBar,然后在基类中定义 navigationHeight、statusBarHeight、topMargin 属性,在每个 UIViewController 里面手动的去使用这三个属性去做布局。实际上这种方法并没有隐藏 iOS6与 iOS7的变化,但是隐藏了变化的细节,我们知道 iOS7下 view 的Y 坐标应该在 statusBar 的下边,所以我们只要加上 statusBarHeight 就可以了,而不是直接加20,这种方式只是减少了代码布局中一大推的坐标看起来凌乱的问题。

方案三

这种方式是通过修改 window 大小来实现,但是如果取修改 window 大小的话容易出现一些隐式的问题,所以我们按照这个思路,不去修改 window 大小,而是修改 UIVireController 里的 view 的大小来做适配。

要修改这个 view 的大小就得说一下 UIViewController 的生存周期了

加载界面A的时候调用顺序

A initWithCoder
A loadView//如果说你进行了重写,会在这里调用,这一步可以参考下文
A viewDidLoad
A viewWillAppear
A viewWillLayoutSubviews//布局改变时调用,比如屏幕旋转
A viewDidLayoutSubviews
A viewDidAppear

切换至界面B的时候调用顺序

B initWithCoder//先将B初始化
A prepareForSegue//调用A的准备过度的函数,所以在该函数中可以对界面B的一些相关属性进行赋值
B loadView//如果这里进行了重写
B viewDidLoad//B界面加载
A viewWillDisappear
B viewWillAppear
B viewWillLayoutSubviews
B viewDidLayoutSubviews
B viewDidAppear
A viewDidDisappear

从B切换回A的时候调用顺序

B viewWillDisappear
A viewWillAppear
A viewDidAppear
B viewDidDisappear
B dealloc

我的思路是直接重写 loadView 方法,在这个方法里面初始化一个 view,指定 view 的大小,然后把这个 view 赋给 UIViewController 的 view。
注意:如果在自己创建 view 那就不要在 loadView 方法里面用[super loadView]调用方法了

但是时间后发现在 loadView 里面定义view 大小实际上是不起作用的。后来google 后发现是因为在 appDelegate里面设置self.window.rootViewController = mainVC引起的,设置了 rootviewcontroller 之后这个 view 的大小就默认为 window 的大小。我尝试使用[self.window addSubview:mainVC.view];方法来代替上面的方法之后,设置的 view 大小就生效了。

但是还是有一个问题就是屏幕旋转之后我们还是需要修改 view 的大小。这时我们可以在viewWillLayoutSubviews方法里面重新设置 view 的大小。

方案四

我们写一个 UIViewController 的 category,在 category 中定义一个用于适配 iOS6和 iOS7的方法,在每个 UIViewController 里面调用,来做到适配。这种方案只是个人觉得可行,并被有具体实践

总结

对于上面几个方案,我比较倾向于方案一二。
对于方案一,由于需要自定义 statusBar 和 navigationBar,个人觉得这个工作量稍微有点大;但是换句话说这个基类只是定义一次便可以在多个项目中使用了,而且这种方式应该是最方便子类布局的方式,因为他是最好的隐藏了变化,子类只需要在很少的地方来针对 iOS6和 iOS7来做适配就可以了,打算在以后尝试下这种方式

以上只是个人觉得可行的方案,并不代表最优,如果您有什么好的适配方式不妨告诉我。