已加载的 Xib 总是在制作插座后立即崩溃
Posted
技术标签:
【中文标题】已加载的 Xib 总是在制作插座后立即崩溃【英文标题】:Loaded Xib Always Crashes As Soon As An Outlet Is Made 【发布时间】:2020-06-09 16:36:50 【问题描述】:我有一个可以成功加载的 xib 文件:
let xib = MyBundle.bundle.loadNibNamed("MyXib", owner: self, options: nil)!
let confirmView = xib[0] as! MyXib
这将加载并正确显示在屏幕上。
该类在 xib 中设置正确,并且在签入代码时可以正确转换。文件所有者也设置正确。
但是,如果我将一个对象从 xib 文件拖到它的类中(例如,设置一个按钮引用),那么一旦加载了这个 xib,应用程序就会崩溃。
*** 由于未捕获的异常“NSUnknownKeyException”而终止应用程序,原因:[MyXib 0x7fcaf0d3eb50 setValue:forUndefinedKey:]: this 类与键按钮的键值编码不兼容。
init 被调用:
required init?(coder: NSCoder)
super.init(coder: coder)
被调用,所以我知道它完成了初始化。
没有损坏的插座或任何时髦的东西。我实际上只是拖动一个按钮并创建一个插座然后运行。如果我删除插座,它将起作用。如果我再次将任何插座添加到任何内容,它将因同样的问题而崩溃。
关于其他可能的原因有什么建议吗?我已经浏览过main causes of this。
解决方案
如下所示,我删除了文件所有者,删除了所有出口并使用 exact 加载语法 DonMag 建议。
【问题讨论】:
啊,是的,沉默的反对票。如果您要投反对票,至少解释一下您的问题。 错误信息看起来有点奇怪。当我有这个时,我相信它已经告诉我它在[ setValue:forUndefinedKey:]
部分中抱怨哪个类。
是的,很抱歉标签弄乱了格式。它确实在错误中引用了我的类
而 MyXib 类确实有一个名为“按钮”的插座......奇怪。
该文件也已链接,因为如果我转到文件所有者,然后单击 -> 箭头,它将带我进入课堂。如果我添加一个插座,它会显示为一个实心点。我还打开了文件文本并清除了所有内容,加载了它,然后添加了一个基本的插座引用,一旦加载它就会再次崩溃
【参考方案1】:
要以这种方式使用您的 XIB,您希望将 XIB 的 “根视图” 设置为您的自定义类:
在进行更改后,您需要撤消并重新建立您的 @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" />
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="kuh-dy-Zhq">
<rect key="frame" x="8" y="8" />
<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" />
<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" />
<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 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
【讨论】:
我将文件所有者和***视图都设置为类。我从来没有尝试过将***视图设置为类并将文件所有者留空 只要我引用按钮,它就会再次崩溃:/ 之前设置的 outlet 删除了吗?你试过我的例子吗? 我做了,但我会再次尝试从头开始创建它 嗯,我不确定为什么它会突然起作用,但是当我将加载语法更改为您的建议时,它已经开始起作用了。我之前的加载代码:func loadViewFromNib() -> U_MakePaymentConfirmation! let bundle = Bundle(for: type(of: self)) let nib = UINib(nibName: "MakePaymentConfirmation", bundle: bundle) return nib.instantiate(withOwner: self, options: nil).first as! U_MakePaymentConfirmation 没用。你知道有什么区别吗?【参考方案2】:我认为您不想设置笔尖的所有者。除非是self
对象和XIB顶层对象是同一个类
当您使用这种实例化风格时会发生什么?
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,我尝试将视图控制器作为所有者传递。我会按照您的建议尝试使用 nil 所有者 同样的问题。我还在上面添加了一个屏幕截图,显示了正在设置的后台插座。当我尝试这个时,我仍然收到错误:*** 由于未捕获的异常 'NSUnknownKeyException' 导致应用程序终止,原因:'[MyXib
或您的班级?
是的,我还添加了一个屏幕截图。另请注意,单击 -> 会将我带到课堂,因此我知道它已连接以上是关于已加载的 Xib 总是在制作插座后立即崩溃的主要内容,如果未能解决你的问题,请参考以下文章