Link a UIView subclass to xib file - ios

I've created a UIView subclass, which i want to link to a xib file. I've added a xib file and set the class to DraggableView, however when i for instance create a lable and link it to the information. it returns that information is equal to nil? why doesnt it work?
class DraggableView: UIView {
var delegate: DraggableViewDelegate!
#IBOutlet var information: UILabel!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
information.text = "no info given"
information.textAlignment = NSTextAlignment.Center
information.textColor = UIColor.blackColor()
self.backgroundColor = UIColor.whiteColor()
}
}

Please ensure you add init from XIB method in your custom UIView like this:
class func instanceFromNib() -> UIView {
return UINib(nibName: "nib file name", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as UIView
}
And then you can use it like this:
var view = DraggableView.instanceFromNib()
view.information.text = "Test Label"
self.view.addSubview(view)

You need for your custom UIView to load XIB file first before setting objects value.
class DraggableView: UIView {
var delegate: DraggableViewDelegate!
#IBOutlet var information: UILabel!
init() { xibSetup() }
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
if self.subviews.count == 0 {
xibSetup()
}
}
func xibSetup() {
let view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
addSubview(view)
// INIT THERE YOUR LABEL
information.text = "no info given"
information.textAlignment = NSTextAlignment.Center
information.textColor = UIColor.blackColor()
self.backgroundColor = UIColor.whiteColor()
}
func loadViewFromNib() -> UIView {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: "nib file name", bundle: bundle)
let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
return view
}
and call simplely like that :
var view = DraggableView()

Related

Unable to create instance of a resuable view

I am using this code:
import UIKit
class SnackBarView: UIView {
#IBOutlet var containerView: UIView!
#IBOutlet var labelText: UILabel!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
let _ = commonInitialization()
}
func commonInitialization() -> UIView
{
let bundle = Bundle.init(for: type(of: self))
let nib = UINib(nibName: "SnackBarView", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
view.frame = bounds
view.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]
addSubview(view)
return view
}
}
when I try initialising it like this:
let snackBar = SnackBarView()
it gives the error:
Missing argument for parameter 'coder' in call
I know there is something wrong in the init function but I am not sure how to correct this. How should I proceed correcting this?
The error is not in your class but rather in how you are attempting to call it.
Since you want to create the UIView with zero (0) parameters you need to supply it a constructor (init) to deal with that situation when it happens.
Hopefully the below will work to give you a constructor with zero (0) parameters.
class SnackBarView: UIView {
#IBOutlet var containerView: UIView!
#IBOutlet var labelText: UILabel!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
let _ = commonInitialization()
}
// you need to add this init
override init(frame: CGRect) {
super.init(frame: frame)
// call your custom initialization code here
let _ = commonInitialization()
}
// constructor with zero (0) parameters
convenience init() {
// call the override from above with a default CGRect
self.init(frame: CGRect.zero)
}
func commonInitialization() -> UIView
{
let bundle = Bundle.init(for: type(of: self))
let nib = UINib(nibName: "SnackBarView", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
view.frame = bounds
view.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]
addSubview(view)
return view
}
}
You need to add override init(frame: CGRect) in your view: updated code is below:
class SnackBarView: UIView {
#IBOutlet var containerView: UIView!
#IBOutlet var labelText: UILabel!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
let _ = commonInitialization()
}
// you need to add this init
override init(frame: CGRect) {
super.init(frame: frame)
}
func commonInitialization() -> UIView
{
let bundle = Bundle.init(for: type(of: self))
let nib = UINib(nibName: "SnackBarView", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
view.frame = bounds
view.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]
addSubview(view)
return view
}
}
I think it's meaningless to create a UIView with xib , and then add an instance of the same type to it as commonInitialization here occupies all frame of itself , I think you need
class SnackBarView: UIView {
#IBOutlet var containerView: UIView!
#IBOutlet var labelText: UILabel!
class func commonInitialization(_ rec:CGRect) -> SnackBarView
{
let nib = UINib(nibName: "SnackBarView", bundle: nil)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! SnackBarView
view.frame = rec
return view
}
}
//
let v = SnackBarView.commonInitialization(view.frame)
view.addSubview(v)

Error while setting object or calling function EXC_BAD_ACCESS(code=257)

I had created some custom UIViews and implemented in another UIView in my projects.
I'm getting a crash while calling some functions or setting values to some objects but not getting crash when setting property.
Refer below code to understand code and question properly.
class SearchProfileDetailView: UIView {
#IBOutlet weak var userInfoTable: UITableView!
var userObject: UserObject?
override init(frame:CGRect) {
super.init(frame: frame)
loadViewFromNib()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
loadViewFromNib()
}
func loadViewFromNib() {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "SearchProfileDetailView", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
view.frame = bounds
self.addSubview(view);
}
func setColor() {
self.backgroundColor = UIColor.red
}
}
I've used this SearchProfileDetailView in another UIView with the interface builder and assigned outlet refer below code.
class SearchResultView: UIView {
#IBOutlet weak var profileDetailView: SearchProfileDetailView!
var currentIndex: Int?
override init(frame:CGRect) {
super.init(frame: frame)
loadViewFromNib()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
loadViewFromNib()
}
func loadViewFromNib() {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "SearchResultView", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
view.frame = bounds
self.addSubview(view);
}
func setUserProfile(userObject: UserObject) {
profileDetailView.backgroundColor = UIColor.red // Not Crashed
profileDetailView.userObject = userObject //Crashed with error mentioned in title of question
profileDetailView.setColor() ////Crashed with error mentioned in title of question
}
}
Crashed while calling profileDetailView.setColor() and
profileDetailView.userObject = userObject But not crashed on
profileDetailView.backgroundColor = UIColor.red
Now I've used this SearchResultView into UIViewController with the interface builder.
class ExploreViewController: UIViewController {
#IBOutlet weak var searchResultView: SearchResultView!
func getResult() {
SearchAPIHandler().search(params: parameters) {[weak self] (responseData) in
DispatchQueue.main.async {
guard let strongSelf = self else {
return
}
if let users = responseData.users, !users.isEmpty {
strongSelf.searchResultView.setUserProfile(userObject: users[0])
}
}
}
}
I had tried so much and now I've got to know that problem was with my interface builder.
There was none module.
I checked Inherit Module From Target and everything works well.

How to put nib file in collection view in swift

I am one problem in use collection view.
How to put nib file in collection view?
I will create image slider in collection view.
Please help me.
#IBDesignable class Menu: UIView {
var view: UIView!
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
xibSetup()
}
func xibSetup() {
view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
addSubview(view)
}
func loadViewFromNib() -> UIView {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: "Menu", bundle: bundle)
let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
return view
}
etc etc ...
}
Then add a UIView to your Main.storyboard as with a Menu class in the Identity Inspector for that view.

Dynamically instantiating custom UIView's from XIB issue (what's wrong with this code)?

What is wrong with the following code, it's seems to have an endless loop. Initially comes through init:frame, to commonInit, but then the XIB loading line triggers entering again through init:coder etc.
Two areas of question:
a) How to instantiate probably to avoid this problem (i.e. want to use the XIB to layout, but then dynamically creating/position multiple of these on a parent view in code)
b) setting self.label.text is problematic as it seems self.label (a UILabel linked to the XIB) hasn't been setup at this point, hence is nil. So dynamically, when I want to create this little custom UIView via XIB, add it as a subclass, then immediately set a value of the label how do I do this?
import UIKit
class DirectionInfoView: UIView {
#IBOutlet weak var label: UILabel!
func commonInit() {
let viewName = "DirectionInfoView"
let view: DirectionInfoView = NSBundle.mainBundle().loadNibNamed(viewName, owner: self, options: nil).first as! DirectionInfoView // <== EXC_BAD_ACCESS (code=2...)
self.addSubview(view)
view.frame = self.bounds
self.label.text = "testing 123"
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
}
Usage:
let newInfoView = DirectionInfoView(frame: self.mapview.bounds)
myexitingView.addSubview(newInfoView)
This seems to work:
import UIKit
class DirectionInfoView: UIView {
#IBOutlet weak var label: UILabel!
func commonInit() {
self.layer.borderWidth = 5
self.layer.cornerRadius = 25
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
}
Usage:
let directionInfoView : DirectionInfoView = NSBundle.mainBundle().loadNibNamed("DirectionInfoView", owner: self, options: nil).first as! DirectionInfoView
mapview.addSubview(directionInfoView)
directionInfoView.label.text = "It Worked!"

How to load custom UIView from xib using Swift 2?

The task is to create custom UIView that loads UI from .xib file using Swift. How do I do that?
I tried to do that using the code:
import UIKit
#IBDesignable class CustomView: UIView {
var view: UIView!
#IBOutlet weak var label: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
xibSetup()
}
func xibSetup() {
view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
addSubview(view)
}
func loadViewFromNib() -> UIView {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: "CustomView", bundle: bundle)
let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
return view
}
}
It runs, but crashes with EXC_BAD_ACCESS and shows me the message:
warning: could not load any Objective-C class information. This will significantly reduce the quality of type information available.
Actually, I need to translate code given here http://qnoid.com/2013/03/20/How-to-implement-a-reusable-UIView.html to Swift 2.0, but I have no idea how to do this.
Try
let yourView = NSBundle.mainBundle().loadNibNamed("youViewNibName", owner: self, options: nil).first as! YourView
Do it in your ViewController class, then you can access the view in required init with coder, where you should call xibSetup().
Is it correct, that your class is called CustomView and you're loading CustomView.xib where the class for the view in xib is CustomView?
If that is so you probably do not understand what you're doing

Resources