[英]Custom UIView is blank when instantiated from a XIB in Swift 4
I have a custom view that I am trying to load from a custom XIB, but the view appears to be blank when loaded, even thought it has the correct sizes when debugged. 我有一个试图从自定义XIB加载的自定义视图,但是加载后该视图似乎是空白的,甚至认为调试时它的大小正确。
My debug statements show that the frame has the correct sizes: 我的调试语句显示框架具有正确的大小:
commonInit()
commonInit()
XIB: MyCustomViewXIB:MyCustomView
myView Frame: (0.0, 0.0, 320.0,568.0)myView框架:(0.0、0.0、320.0、568.0)
myView ContentSize: (320.0, 710.0)myView ContentSize:(320.0,710.0)
This is my custom VC that I am using to call my Custom View 这是我用来调用“自定义视图”的自定义VC
class MyCustomViewController: UIViewController {
var myView : MyCustomView!
override func viewDidLoad() {
super.viewDidLoad()
myView = MyCustomView(frame: self.view.frame)
self.view.addSubview(myView)
updateScrollViewSize()
print("myView Frame: \(myView.frame)")
print("myView ContentSize: \(myView.contentView.contentSize)")
}
func updateScrollViewSize () {
var contentRect = CGRect.zero
for view in myView.contentView.subviews {
contentRect = contentRect.union(view.frame)
}
myView.contentView.contentSize = CGSize(width: myView.contentView.frame.size.width, height: contentRect.size.height + 5)
}
}
There is a XIB
that has the files owner as MyCustomView and all the outlets are hooked up correctly. 有一个
XIB
,其文件所有者为MyCustomView,并且所有插座均已正确连接。
class MyCustomView: UIView {
let kCONTENT_XIB_NAME = "MyCustomView"
@IBOutlet var contentView: UIScrollView!
@IBOutlet weak var lbl_datein: UILabel!
//.. A bunch of other GUI elements for the scrollview
@IBOutlet weak var text_location: UITextField!
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
func commonInit() {
print(#function)
print("XIB: \(kCONTENT_XIB_NAME)")
Bundle.main.loadNibNamed(kCONTENT_XIB_NAME, owner: self, options: nil)
contentView.addSubview(self)
contentView.frame = self.bounds
contentView.backgroundColor = .blue
}
}
Does anyone see what I have done wrong when trying to load the view 有人在尝试加载视图时是否看到我做错了什么
I'm going to post an alternative to what you've done, using an extension. 我将使用扩展程序发布您所做的替代方案。
extension UIView {
@discardableResult
func fromNib<T : UIView>(_ nibName: String? = nil) -> T? {
let bundle = Bundle(for: type(of: self))
guard let view = bundle.loadNibNamed(nibName ?? String(describing: type(of: self)), owner: self, options: nil)?[0] as? T else {
return nil
}
view.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(view)
view.autoPinEdgesToSuperviewEdges()
return view
}
}
*Note that I am using PureLayout for convenient autolayout management, you could just apply the constraints manually yourself though if you aren't using PureLayout. *请注意,我正在使用PureLayout进行方便的自动布局管理,即使您不使用PureLayout,也可以自己手动应用约束。
Using the above all you have to do is call the below from your init; 使用以上所有操作,您只需从init调用以下内容;
fromNib()
*Final note. *最后的笔记。 The custom view name must match the nib name, otherwise you must pass the nib name in to you fromNib function.
自定义视图名称必须与笔尖名称匹配,否则,您必须从nib函数将笔尖名称传递给您。
You now have something much more reusable. 您现在有了更多可重用的东西。
I couldn't get this to run copy/pasting the code. 我无法获取此代码来运行复制/粘贴代码。 Maybe there's some setup missing, but I'm having a hard time understanding how it's supposed to work.
也许缺少一些设置,但是我很难理解它应该如何工作。 The original code in the question crashes on this line:
问题中的原始代码在此行崩溃:
contentView.addSubview(self)
because when you have IBOutlets
, they will always be nil
if you initialize it using MyCustomView(frame: self.view.frame)
. 因为当您拥有
IBOutlets
,如果使用MyCustomView(frame: self.view.frame)
对其进行初始化,则它们将始终为nil
。 It has to call the initWithCoder
function. 它必须调用
initWithCoder
函数。
There's a lot going on here, but this is how I would do it: 这里有很多事情,但这就是我要做的:
class MyCustomViewController: UIViewController {
var myView: MyCustomView!
override func viewDidLoad() {
super.viewDidLoad()
myView = Bundle.main.loadNibNamed("MyCustomView", owner: self, options: nil)?.first as? MyCustomView
self.view.addSubview(myView)
updateScrollViewSize()
print("myView Frame: \(myView.frame)")
print("myView ContentSize: \(myView.contentView.contentSize)")
}
func updateScrollViewSize () {
var contentRect = CGRect.zero
for view in myView.contentView.subviews {
contentRect = contentRect.union(view.frame)
}
myView.contentView.contentSize = CGSize(width: myView.contentView.frame.size.width, height: contentRect.size.height + 5)
}
}
class MyCustomView: UIView {
let kCONTENT_XIB_NAME = "MyCustomView"
@IBOutlet var contentView: UIScrollView!
@IBOutlet weak var lbl_datein: UILabel!
//.. A bunch of other GUI elements for the scrollview
@IBOutlet weak var text_location: UITextField!
}
I'm assuming that the top-level object in the nib is of class MyCustomView
, which is going to lead to a lot of weird things. 我假设笔尖中的顶级对象是
MyCustomView
类,这将导致很多奇怪的事情。 loadNibNamed
will call init?(coder aDecoder: NSCoder)
, so ideally you'd just be calling that from your view controller in the first place, instead of from the custom view object. loadNibNamed
将调用init?(coder aDecoder: NSCoder)
,因此理想情况下,您首先只是从视图控制器而不是自定义视图对象调用它。
With regards to the "can't add self as subview" error, I did not see that error while running, but I would expect it from this line: 关于“无法将自己添加为子视图”错误,我在运行时没有看到该错误,但我希望从此行可以看到它:
contentView.addSubview(self)
since that's exactly what it does, add self
as a subview of a view that's already a subview of self
. 因为这正是它,加入
self
因为这是已经是一个子视图视图的子视图self
。
If my alternative answer is too much, let me try solve your existing issue. 如果我的替代答案太多,请让我尝试解决您现有的问题。 Instead of the below;
代替下面的内容;
Bundle.main.loadNibNamed(kCONTENT_XIB_NAME, owner: self, options: nil)
contentView.addSubview(self)
Try; 尝试;
let nibView = Bundle.main.loadNibNamed(kCONTENT_XIB_NAME, owner: self, options: nil)
self.addSubView(nibView)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.