本文由CocoaChina译者小袋子(博客)翻译
原文:Storyboard Reference, Strong IBOutlet, Scene Dock in iOS 9html
Strong 引用的 IBOutletios
Apple已经对Xib和Storyboard文件作了不少优化。而且因为这些优化,你如今能够将IBOutlet定义为strong,而不是weak。Apple曾在上一届的WWDC上指出这一点,所以让咱们来看一下其中的更多细节。你能够从 这个文档 中找到管理Nib文件中对象生命周期的章节:git
Outlet通常来讲应该为weak,除了在nib文件 ( 或者iOS中,storyboard scene) 中的File’s Owner的顶级对象,这个对象能够是strong。你建立的Outlets应该为weak,缘由以下:web
你建立的一个 view controller 视图的子视图或者 window controller 窗体视图的 Outlets,是对象之间的弱引用,不该该有依赖关系。swift
strong的outlet一般是特殊的framework类(如:UIViewController 视图的 outlet,或者 NSWindowController 视窗的 outlet)。xcode
正如这个段落所解释的同样,view controller视图的子视图 outlet应该为 weak,由于这个视图已经被nib文件的顶级对象所拥有了。然而,当一个Outlet被定义为weak指针时,ARC会在编译期间调用如下函数:app
1
|
id objc_storeWeak(id *object, id value);
|
这个函数把对象的值做为key,并把它添加到table中。这个table被称为weak table。ARC使用这个table去存储应用中的全部的weak指针。如今,当对象被deallocated时,ARC将会指向weak table而且将weak引用置为nil。同时,ARC将会调用:ide
1
|
void objc_destroyWeak(id * object);
|
紧接着,注销这个对象并再次调用objc_destroyWeak:函数
1
|
objc_storeWeak(id *object, nil);
|
这种weak引用关联的生命周期是strong引用的2-3倍。因此,经过避免简单地定义outlets为strong,使用弱引用是一种运行期间的通用作法。优化
我想这个决策与已废弃的viewDidUnload方法有关。直到iOS 5,这个方法被用于清空在低内存环境下的视图。正如文档中解释的那样:
在iOS 5以前,当发生低内存警告或者当前view controller的视图不被须要时,在视图被释放以后,系统会选择性地调用这个方法。这个方法让你能够进行最后的清理工做。若是你的视图存储了视图或者其子视图的单独引用,你应该使用这个方法去释放这些引用。
在那时,定义一个属性为weak是有意义的,由于这就不用在viewDidUnload额外地释放对象。可是在iOS 9中,我相信咱们已经有足够的时间去避免使用这个方法。所以,在IBOutlets定义weak是没意义的。
如今 Storyboard 的几个限制
Apple是在iOS 5中开始引入storyboards的。在此以前,使用Interface Builder的nib文件是建立UI的惟一途径。在iOS开发中,单个文件中操纵多个nib文件是很广泛的。然而,为了理解应用流以及view controller如何链接在一块儿,开发者须要去每个view controller类内去找出跳转到下一个界面的桥接点。这是一个很是耗费时间的工序,尤为当你不是应用的原始开发者时。
Apple提出Storyboards用以简化这个过程,并帮助开发者可以对整个应用程序流有彻底的控制。除此以外,storyboards容许你在一个文件中拥有一个view controller视图(经过添加 .storyboard文件)。用这种方式,你能够看到整个程序的流状态,而且可以方便地理解view controller的链接关系。然而,storyboards也引出了一些问题。把全部的nib文件都放在一个文件中显然是很是便利而且能完美工做,可是这只是在你为单人开发的前提下。只要你的团队扩大了,你会使用版本控制,例如git或者subversion,这时你就会讨厌storyboards。由于,当把修改合并到一个通用的git branch时,就会产生冲突,而解决此类冲突是很头疼的。在编译期间,nib会被编译成XML文件。因此,为了解决合并冲突,你须要比较两个巨大的XML文件,而且要尝试理清哪部分是你修改的,哪部分是你同事修改的。此外,Apple常常修改这个文件格式。因此,试图去理解而且反转storyboard格式是很是浪费时间的。
例如,在iNVASIVECODE(这是做者所在的公司),咱们倾向于使只用storyboards去构建app原型。咱们的设计师可以在几个小时内设计出一个可以在iOS设备上运行的原型,有时候只须要几分钟。这样能够在不写一行代码的状况下使用storyboards。因此,storyboards对于构建原型来讲是很是方便的,可是不建议在开发期间使用。
另外一个storyboard的重要局限是不能添加不属于一个场景体系的视图。我我的认为跟前面所说的合并问题相比,这是一个更为致命的限制。只要可以使用,我一定会使用IB。我喜欢这个,由于这能够避免写代码。可是使用storyboards,不能添加场景体系之外的视图。所以,当我须要额外的视图时,我就强迫本身去使用nib。
Storyboards还有一个额外的局限就是转场动画问题。在iOS 7及以后的iOS 8,Apple提出了在两个view controller之间定制一个转场动画的新方法。当你运行一个segue时,这个新方法须要建立不能使用storyboard的特殊对象。因此,若是你想要添加定制转场动画的方法到你的view controllers,你要避免使用storyboards。
可是猜猜看!Xcode 7和iOS 9为咱们解决了全部的这些问题。
Storyboard Reference
在Xcode 7中,咱们有一个在多个storyboards中组织scenes的新方法,而且能对它们进行引用。让咱们来看一个实践的例子。下载 这个我已经准备好的例子。打开它,而且选择Main.storyboard文件。我已经为了准备好了一系列组织在一个tab bar controller下view controller。每个tab包含一个navigation controller。下面的图片强调了示例项目的storyboard部分。
正如你所看到的那样,tab bar controller包含了三个navigation controller。每个navigation controller控制着不一样的视图控制器。如今,想象一下在这个项目里和其余开发者一块儿工做。正如我前面描述的那样,使用同一个storyboard文件是很是使人头疼的,由于大家每一个人都会修改它。你能够把着三个navigation分支分割成三个storyboard文件。然而,当你准备在运行期从一个storyboard跳转到另一个时,你必须加载相应的storyboard文件。这须要增长额外的代码。
xcode 7容许你建立多个storyboards,而且能够方便地操纵它们。选择顶部的navigation controller 以及两个view controller,以下图所示:
选择好以后,打开菜单栏的Editor,而后选择Refactor to Storyboard(如图)
为新的storyboard取一个名字(如图)。我将它命名为First.storyboard。
点击保存。正如你所见到的那样,一个新的storyboard已经被添加到你的项目中了。让咱们回到Main.storyboard,你将会看到以下的对象。
这个称之为Storyboard Reference,它确实为新建的First.storyboard的引用,而且替换了先前选择的三个view controller。最棒的是若是你双击storyboard引用,Xcode 7会打开所引用的storyboard。所以,当你想要控制应用流时,你能够方便地导向不一样的storyboard。在运行期间,当segue指向的一个Storyboard Reference被执行时,这个被引用的storyboard中的初始化view controller会被加载。此外,Storyboard References还可以引用相同的storyboard。
另外,你也能够手工建立一个新的storyboard,而后添加一个Storyboard Reference到起始的storyboard中。让咱们来试一下。
建立一个新的storyboard并命名为Third.storyboard。在Main.storyboard文件中,从Object Library中添加新的Storyboard Reference。选择Storyboard Reference而且打开相应的Attributes Inspector。以下图所示:
在这个字段中,选择你想要引用的storyboard(在咱们的例子中是Third)。若是这个字段为空白,则被引用的storyboard是定义的Storyboard Reference。Reference ID指向在目的storyboard中的一个特定scene。若是你置空的话,初始化view controller会加载。
最后,Bundle字段须要被置为包含目的storyboard的bundle。若是你留空的话,就会使用源storyboard的bundle。
在Third.storyboard文件中,你须要添加一个新的view controller并将其做为初始化的view controller。以后,只要view controller是Main storyboard的一部分,你能够均可以运行app而且导航到那里。
全部,如今你能够在多个文件里组织你的storyboard,而且能够保持这些storyboard的引用。此外,每个storyboard可以被分配给一个不一样的开发者,而你不须要去考虑view controller间的链接组合。这真是很是方便。
Scene Dock and Extra Views
这是我最喜欢的特性。如今,我可以在storyboard中添加在scene体系外的视图。为了让你明白它使如何工做的,咱们先建立一个新的项目。将其命名为ExtraView,打开Main storyboard,在顶部的First Responder和Exit之间添加一个新的view。以下图所示(这个叫作Scene Dock):
把这个view的大小调整为 1500×120 像素。而后在这个view的顶层添加一个大小为 240×112 的小view。把这个视图放到大视图的中心,而后增长顶部和底部的约束 (constants = 8),宽度约束(constant = 240) 以及水平居中的约束。而后添加一个scrollview到view controller中,将其居中,并添加trailing和leading space约束 (constant = 0),高度约束(constant=128),最后增长垂直居中约束。在ViewController.swift中,添加下列两个outlet:
1
2
|
@IBOutlet
var
externalView: UIView!
@IBOutlet
var
scrollView: UIScrollView!
|
将它们链接到scrollview以及外面的view。最后,添加viewDidAppear:方法:
1
2
3
4
5
|
override func viewDidAppear(animated: Bool) {
super
.viewDidAppear(animated)
scrollView.contentSize = externalView.frame.size
scrollView.addSubview(externalView)
}
|
而后运行项目,能够看到的是,你如今能够添加额外的视图(能够任意添加),而且能够在运行期间很方便地加载出来。你能够 下载 这个示例来加深理解。
定制转场动画
这是Xcode 7中storyboard另一个很酷的新特性。具体的细节我将会留到以后发布的文章,这里我只想先给你一些你能作什么的想法。若是你在多storyboard项目中选择任意的action segue,而且打开Attributes Inspector,你将会看到一个新的字段Segue Class,正以下图所示:
你能够建立一个UIStoryboardSegue的子类,而后听从UIViewControllerTransitioningDelegate 协议。而后,在类中实现animationControllerForPresentedController: presentingController: sourceController: 以及 animationControllerForDismissedController:。此外,你还须要建立两个NSObject的子类,听从UIViewControllerAnimatedTransitioning delegate。在这些类中,你必须实现两个方法:transitionDuration: 和 animateTransition:。
我将会在接下来的文章中介绍其中的细节。
总结
Xcode 7的Storyboards增长了不少便利的新特性。咱们如今能够建立storyboard references,在scene体系外增长视图,而且可使用新的定制视图转场动画。我还讨论了为何你应该将outlet定义为strong引用而不是weak。
做者介绍
Geppy
Geppy Parziale (@geppyp) is cofounder of InvasiveCode (@invasivecode). He has developed iOS applications andtaught iOS development since 2008. He worked at Apple as iOS and OS X Engineer in the Core Recognition team. He has developed several iOS and OS X apps and frameworks for Apple, and many of his development projects are top-grossing iOS apps that are featured in the App Store.