让@IBDesignable UIView 在不崩溃 Interface Builder 的情况下进行绘制
Getting @IBDesignable UIView to draw without crashing Interface Builder
我正在尝试在界面生成器中配置自定义 UIView
并获取要呈现的视图。每次我尝试使用自定义 Xib 执行此操作时,我都可以让 xib 在界面生成器中看起来很好,但是当我尝试将我的 MyCustomView
放入界面生成器中的 UIVewController
时,我得到各种编译器错误。
我看过的每个教程都是这样的:"Just add @IBDesignable
in front of your class declaration and put @IBInspectable
in front of your vars and then watch the magic happen"(例如:WWDC 2015 video)。或者是 Objective-C,或者是 30 分钟的阿拉姆语中文字幕视频等
我的目标 objective 是能够拖入一个 UIView,在身份检查器中分配我的自定义 class 并让 xib 的内容填充我拖入的 UIView 并能够进行调整@IBInspectable
个属性。
我在哪里寻找答案:
我得到的错误:
Base.lproj/Main.storyboard: error: IB Designables: Failed to render
and update auto layout status for PlaylistViewController (o1G-QR-OwX):
The agent crashed
Base.lproj/Main.storyboard: error: IB Designables: Failed to update
auto layout status: The agent crashed
我的 CurrentlyPlayingView
的身份检查器:
出现上述错误后我的观点的故事板:
我想要出现在上述故事板底部的视图:
我的代码:
import UIKit
@IBDesignable class CurrentlyPlayingView: UIView {
var view = UIView()
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var subtitleLabel: UILabel!
@IBOutlet weak var progressSlider: UISlider!
// IBInspectable attributes
@IBInspectable public var titleLabelColor: UIColor = .black {
didSet {
self.titleLabel.textColor = titleLabelColor
}
}
@IBInspectable public var subtitleLabelColor: UIColor = .black {
didSet {
self.subtitleLabel.textColor = subtitleLabelColor
}
}
@IBInspectable public var sliderMinColor: UIColor = .blue {
didSet {
self.progressSlider.minimumTrackTintColor = sliderMinColor
}
}
@IBInspectable public var sliderMaxColor: UIColor = .red {
didSet {
self.progressSlider.maximumTrackTintColor = sliderMaxColor
}
}
// MARK: - Initialization
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
initialConfig()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
xibSetup()
initialConfig()
}
private func initialConfig() {
self.titleLabel.textColor = titleLabelColor
self.subtitleLabel.textColor = subtitleLabelColor
self.progressSlider.minimumTrackTintColor = sliderMinColor
self.progressSlider.maximumTrackTintColor = sliderMaxColor
}
// MARK: - Nib handlers
private func xibSetup() {
view = loadViewFromNib()
view.frame = bounds
// Make the view stretch with containing view
view.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]
// Adding custom subview on top of our view (over any custom drawing > see note below)
addSubview(view)
}
private func loadViewFromNib() -> UIView {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "CurrentlyPlayingView", bundle: bundle)
// Assumes UIView is top level and only object in CustomView.xib file
let view = nib.instantiate(withOwner: self, options: nil).first as! UIView
return view
}
}
如果您已经读到这里,感谢您的阅读。如果你看到我遗漏了什么,我欢迎你的建议。
我认为这是因为您缺少 prepareForInterfaceBuilder
功能。
像这样重写这个函数。
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
//setup your view with the settings
}
OP 的附录:
将 UIView
拖到 YourViewController
并在 Identity Inspector 中将其自定义 Class 设置为 YourCustomView
后,确保勾选 "Inherit from Target"(如Xcode 8.x).
我正在尝试在界面生成器中配置自定义 UIView
并获取要呈现的视图。每次我尝试使用自定义 Xib 执行此操作时,我都可以让 xib 在界面生成器中看起来很好,但是当我尝试将我的 MyCustomView
放入界面生成器中的 UIVewController
时,我得到各种编译器错误。
我看过的每个教程都是这样的:"Just add @IBDesignable
in front of your class declaration and put @IBInspectable
in front of your vars and then watch the magic happen"(例如:WWDC 2015 video)。或者是 Objective-C,或者是 30 分钟的阿拉姆语中文字幕视频等
我的目标 objective 是能够拖入一个 UIView,在身份检查器中分配我的自定义 class 并让 xib 的内容填充我拖入的 UIView 并能够进行调整@IBInspectable
个属性。
我在哪里寻找答案:
我得到的错误:
Base.lproj/Main.storyboard: error: IB Designables: Failed to render and update auto layout status for PlaylistViewController (o1G-QR-OwX): The agent crashed
Base.lproj/Main.storyboard: error: IB Designables: Failed to update auto layout status: The agent crashed
我的 CurrentlyPlayingView
的身份检查器:
出现上述错误后我的观点的故事板:
我想要出现在上述故事板底部的视图:
我的代码:
import UIKit
@IBDesignable class CurrentlyPlayingView: UIView {
var view = UIView()
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var subtitleLabel: UILabel!
@IBOutlet weak var progressSlider: UISlider!
// IBInspectable attributes
@IBInspectable public var titleLabelColor: UIColor = .black {
didSet {
self.titleLabel.textColor = titleLabelColor
}
}
@IBInspectable public var subtitleLabelColor: UIColor = .black {
didSet {
self.subtitleLabel.textColor = subtitleLabelColor
}
}
@IBInspectable public var sliderMinColor: UIColor = .blue {
didSet {
self.progressSlider.minimumTrackTintColor = sliderMinColor
}
}
@IBInspectable public var sliderMaxColor: UIColor = .red {
didSet {
self.progressSlider.maximumTrackTintColor = sliderMaxColor
}
}
// MARK: - Initialization
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
initialConfig()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
xibSetup()
initialConfig()
}
private func initialConfig() {
self.titleLabel.textColor = titleLabelColor
self.subtitleLabel.textColor = subtitleLabelColor
self.progressSlider.minimumTrackTintColor = sliderMinColor
self.progressSlider.maximumTrackTintColor = sliderMaxColor
}
// MARK: - Nib handlers
private func xibSetup() {
view = loadViewFromNib()
view.frame = bounds
// Make the view stretch with containing view
view.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]
// Adding custom subview on top of our view (over any custom drawing > see note below)
addSubview(view)
}
private func loadViewFromNib() -> UIView {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "CurrentlyPlayingView", bundle: bundle)
// Assumes UIView is top level and only object in CustomView.xib file
let view = nib.instantiate(withOwner: self, options: nil).first as! UIView
return view
}
}
如果您已经读到这里,感谢您的阅读。如果你看到我遗漏了什么,我欢迎你的建议。
我认为这是因为您缺少 prepareForInterfaceBuilder
功能。
像这样重写这个函数。
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
//setup your view with the settings
}
OP 的附录:
将 UIView
拖到 YourViewController
并在 Identity Inspector 中将其自定义 Class 设置为 YourCustomView
后,确保勾选 "Inherit from Target"(如Xcode 8.x).