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.
My debug statements show that the frame has the correct sizes:
commonInit()
XIB: MyCustomView
myView Frame: (0.0, 0.0, 320.0,568.0)
myView ContentSize: (320.0, 710.0)
This is my custom VC that I am using to call my Custom View
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.
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.
Using the above all you have to do is call the below from your 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.
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)
. It has to call the initWithCoder
function.
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. 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.
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
.
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)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.