加载的 Xib 总是在创建出口后立即崩溃

Loaded Xib Always Crashes As Soon As An Outlet Is Made

我有一个可以成功加载的 xib 文件:

    let xib = MyBundle.bundle.loadNibNamed("MyXib", owner: self, options: nil)!
    let confirmView = xib[0] as! MyXib

这将加载并正确显示在屏幕上。

class 在 xib 中设置正确,并且在签入代码时正确转换。文件所有者也设置正确。

但是,如果我将一个对象从 xib 文件拖到它的 class(例如设置一个按钮引用),那么应用程序将在加载此 xib 后立即崩溃。

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: [MyXib 0x7fcaf0d3eb50 setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key button.

初始化调用:

required init?(coder: NSCoder) {
    super.init(coder: coder)
}

被调用所以我知道它完成了初始化。

没有坏掉的插座或任何时髦的东西。我实际上只是拖动一个按钮并创建一个插座,然后 运行。如果我删除插座,它将起作用。如果我再次将任何插座添加到任何东西,它都会因同样的问题而崩溃。

关于其他可能的原因有什么建议吗?我已经看过 main causes of this.

解决方案

按照下面的建议,我删除了文件所有者,删除了所有出口并使用 exact 加载语法 DonMag 建议。

我想你不想设置笔尖的所有者。除非情况是 self 对象与 XIB 顶级对象

相同 class

当您使用这种实例化方式时会发生什么?

let nib = NSNib(nibNamed: "MyXib", bundle: nil)
var array: NSArray?
if let nib = nib {
  let result = nib.instantiate(withOwner: nil, topLevelObjects: &array)
  if result, let array = array { //first object is nominally the one you want }
}

或使用您的风格:

let xib = MyBundle.bundle.loadNibNamed("MyXib", owner: nil, options: nil)!
let confirmView = xib[0] as! MyXib

要以这种方式使用 XIB,您需要将 XIB 的 "root view" 设置为您的自定义 class:

进行更改后,您需要取消并重新建立 @IBOutlet 连接。

这是一个 XIB 示例(名为 BasicXIBView.xib):

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="16096" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
    <device id="retina3_5" orientation="portrait" appearance="light"/>
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
        <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" customClass="BasicXIBView" customModule="PassBackNavController" customModuleProvider="target">
            <rect key="frame" x="0.0" y="0.0" width="320" height="93"/>
            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
            <subviews>
                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="kuh-dy-Zhq">
                    <rect key="frame" x="8" y="8" width="304" height="77"/>
                    <subviews>
                        <button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8KY-Pe-K0s">
                            <rect key="frame" x="162" y="20" width="122" height="37"/>
                            <color key="backgroundColor" red="1" green="0.14913141730000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                            <state key="normal" title="Cancel"/>
                            <connections>
                                <action selector="cancelTapped:" destination="iN0-l3-epB" eventType="touchUpInside" id="w6M-G8-kcb"/>
                            </connections>
                        </button>
                        <button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ny7-lN-ZrV">
                            <rect key="frame" x="20" y="20" width="122" height="37"/>
                            <color key="backgroundColor" red="1" green="0.14913141730000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                            <state key="normal" title="Continue"/>
                            <connections>
                                <action selector="continueTapped:" destination="iN0-l3-epB" eventType="touchUpInside" id="32u-xJ-uxC"/>
                            </connections>
                        </button>
                    </subviews>
                    <color key="backgroundColor" red="0.46202266219999999" green="0.83828371759999998" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                    <constraints>
                        <constraint firstItem="ny7-lN-ZrV" firstAttribute="leading" secondItem="kuh-dy-Zhq" secondAttribute="leading" constant="20" id="2rf-kC-UJW"/>
                        <constraint firstItem="ny7-lN-ZrV" firstAttribute="width" secondItem="8KY-Pe-K0s" secondAttribute="width" id="4wL-HV-gXu"/>
                        <constraint firstItem="8KY-Pe-K0s" firstAttribute="leading" secondItem="ny7-lN-ZrV" secondAttribute="trailing" constant="20" id="DM1-NU-W8P"/>
                        <constraint firstAttribute="trailing" secondItem="8KY-Pe-K0s" secondAttribute="trailing" constant="20" id="cyP-o4-Bac"/>
                        <constraint firstAttribute="bottom" secondItem="ny7-lN-ZrV" secondAttribute="bottom" constant="20" id="iaW-ir-x5w"/>
                        <constraint firstAttribute="bottom" secondItem="8KY-Pe-K0s" secondAttribute="bottom" constant="20" id="m9V-Vf-AAA"/>
                        <constraint firstItem="8KY-Pe-K0s" firstAttribute="top" secondItem="kuh-dy-Zhq" secondAttribute="top" constant="20" id="q8j-Ce-ubu"/>
                        <constraint firstItem="ny7-lN-ZrV" firstAttribute="top" secondItem="kuh-dy-Zhq" secondAttribute="top" constant="20" id="rBK-uY-4NU"/>
                    </constraints>
                </view>
            </subviews>
            <color key="backgroundColor" red="1" green="0.83234566450000003" blue="0.47320586440000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
            <constraints>
                <constraint firstItem="kuh-dy-Zhq" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="8" id="0ST-Ya-cGb"/>
                <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="kuh-dy-Zhq" secondAttribute="trailing" constant="8" id="3zW-8F-7Ae"/>
                <constraint firstItem="vUN-kp-3ea" firstAttribute="bottom" secondItem="kuh-dy-Zhq" secondAttribute="bottom" constant="8" id="7GJ-Vc-C2u"/>
                <constraint firstItem="kuh-dy-Zhq" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" constant="8" id="peG-dz-caP"/>
            </constraints>
            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
            <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
            <connections>
                <outlet property="backgroundView" destination="kuh-dy-Zhq" id="GTo-Hw-kwM"/>
            </connections>
            <point key="canvasLocation" x="138.75" y="-89.375"/>
        </view>
    </objects>
</document>

这里是 class 的代码和在视图控制器中使用的示例:

class BasicXIBView: UIView {

    @IBOutlet var backgroundView: UIView!

    @IBAction func continueTapped(_ sender: Any) {
        print("Continue Button Tapped!")
    }

    @IBAction func cancelTapped(_ sender: Any) {
        print("Cancel Button Tapped!")
    }

}

class TestXIBViewController: UIViewController {

    var confirmView: BasicXIBView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let xib = Bundle.main.loadNibNamed("BasicXIBView", owner: self, options: nil)!

        // make sure it loads correctly
        guard let v = xib[0] as? BasicXIBView else {
            fatalError("XIB setup incorrectly!")
        }

        // use it as our class's confirmView
        confirmView = v

        // add it
        view.addSubview(confirmView)

        // use auto-layout
        confirmView.translatesAutoresizingMaskIntoConstraints = false

        // respect safe-area
        let g = view.safeAreaLayoutGuide

        // constrain it centered X and Y,
        //  80% of the width
        //  use its internal constraints to determine its height
        NSLayoutConstraint.activate([
            confirmView.centerYAnchor.constraint(equalTo: g.centerYAnchor),
            confirmView.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            confirmView.widthAnchor.constraint(equalTo: g.widthAnchor, multiplier: 0.8),
        ])

        // demo that we have access to backgroundView in the XIB
        confirmView.backgroundView.backgroundColor = .green

    }

}