问题
Xcode 9.1
学习StoryBoard,想自定义一个xib,对一个XXView添加一个xib,取名为XXView.xib
,运行的时候发现,竟然奔溃了…粗略查找了下,发现可能跟我有一个XXViewController
类(没有带xib)有关。于是便做了一下尝试。
过程
有一个AAViewController
控制器(创建时候没有点上),就创建了一个AAView.xib
,画好界面后发现push进入这个控制器就会奔溃,报如下信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| 2017-11-17 16:51:29.581676+0800 CleanTest[28157:4303971] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UIViewController _loadViewFromNibNamed:bundle:] loaded the "AAView" nib but the view outlet was not set.' *** First throw call stack: ( 0 CoreFoundation 0x000000010a4a41ab __exceptionPreprocess + 171 1 libobjc.A.dylib 0x0000000107329f41 objc_exception_throw + 48 2 CoreFoundation 0x000000010a518cb5 +[NSException raise:format:] + 197 3 UIKit 0x0000000107d62965 -[UIViewController _loadViewFromNibNamed:bundle:] + 684 4 UIKit 0x0000000107d63164 -[UIViewController loadView] + 177 5 UIKit 0x0000000107d63495 -[UIViewController loadViewIfRequired] + 195 6 UIKit 0x0000000107d63cf2 -[UIViewController view] + 27 7 UIKit 0x0000000107d95d4e -[UINavigationController _startCustomTransition:] + 954 8 UIKit 0x0000000107dac5a4 -[UINavigationController _startDeferredTransitionIfNeeded:] + 686 9 UIKit 0x0000000107dad8c3 -[UINavigationController __viewWillLayoutSubviews] + 150 10 UIKit 0x0000000108006a49 -[UILayoutContainerView layoutSubviews] + 231 11 UIKit 0x0000000107c8f6f5 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1439 12 QuartzCore 0x000000010d9a33ee -[CALayer layoutSublayers] + 153 13 QuartzCore 0x000000010d9a74dd _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 401 14 QuartzCore 0x000000010d92fded _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 365 15 QuartzCore 0x000000010d95b704 _ZN2CA11Transaction6commitEv + 500 16 QuartzCore 0x000000010d95c450 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 76 17 CoreFoundation 0x000000010a446d37 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23 18 CoreFoundation 0x000000010a446c8e __CFRunLoopDoObservers + 430 19 CoreFoundation 0x000000010a42b254 __CFRunLoopRun + 1572 20 CoreFoundation 0x000000010a42a9b9 CFRunLoopRunSpecific + 409 21 GraphicsServices 0x000000010cb569c6 GSEventRunModal + 62 22 UIKit 0x0000000107bbe5e8 UIApplicationMain + 159 23 CleanTest 0x000000010686c28f main + 111 24 libdyld.dylib 0x000000010b515d81 start + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException
|
渣渣的我自然看不懂,然后就做了尝试:
试验
把AAView.xib -> File’s Owner -> Class设置为AAViewController,运行:
同样报错奔溃。
把AAView.xib -> File’s Owner -> Class设置为AAViewController,control按住拖线从 File’s Owner 到 View,运行:
成功push到AAViewController,显示的是AAView.xib。
新建一个BBViewController,在新建的时候勾选上Also create XIB file,push到BBViewController,运行:
成功push到BBViewController,显示的是BBViewController.xib。
新建一个BBViewController,在新建的时候勾选上Also create XIB file,然后在新建一个BBView.xib,push到BBViewController,运行:
成功push到BBViewController,显示的是BBViewController.xib。
对比1和2,3和4,很明显,xib和viewController差了个连接关系,所以我打开BBView.xib和BBViewController.xib的源文件显示,对比了下:
BBView.xib:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13142" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> <dependencies> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12042"/> <capability name="Safe area layout guides" minToolsVersion="9.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <objects> <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/> <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> <view contentMode="scaleToFill" id="iN0-l3-epB"> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/> </view> </objects> </document>
|
BBViewController.xib:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13142" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> <dependencies> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12042"/> <capability name="Safe area layout guides" minToolsVersion="9.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <objects> <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="BBViewController"> <connections> <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/> </connections> </placeholder> <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT"> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <viewLayoutGuide key="safeArea" id="Q5M-cg-NOt"/> </view> </objects> </document>
|
主要差别就在于第一个里面有没有:
1 2 3
| <connections> <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/> </connections>
|
其实就是试验2拖线的操作,就是差一个viewController和xib的连接关系。
所以我猜想,当你创建XXXViewController
的时候如果没有勾选上Also create XIB file,那么系统在加载这个ViewController的时候在有XXXView.xib
的情况下会自动加载这个xib,如果这个xib并没有连接到XXXViewController
时,便会抛出异常,奔溃闪退。
如果勾选上了,加载的便是系统创建的XXXViewController.xib
,无论是否有XXXView.xib
都不影响正常运行。
解决
所以要我们在有XXXViewController
没自带XXXViewController.xib
的时候,不能为其他View或者ViewController创建连接XXXView命名的xib,因为这已经被XXXViewController
占有了,必须用其他命名或者给XXXViewController
指定连接另一个xib。