IBOutlets in CustomView are coming as nil.
I have created Custom view(xib).
Please find images for more information.
class TextFieldView: UIView {
#IBOutlet var contentView: TextFieldView!
#IBOutlet weak var customTextField: UITextField!
#IBOutlet weak var rightButton: UIButton!
#IBOutlet weak var placeHolderLabel: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
override func awakeFromNib() {
super.awakeFromNib()
}
func commonInit()
{
let bundle = Bundle(for: type(of: self))
bundle.loadNibNamed("TextFieldView", owner: self, options: nil)
customTextField.backgroundColor = UIColor.green
NSLog("Called")
}
Still throwing an error with exc_bad_access.(In loadNibNamed line of code)
Swift 3 Version
This is the solution that worked for me. Make sure your file object in IB has the TextFieldView Class assigned to it (not the UIView itself). Also make sure all your IBOutlets are connected to the right place or you risk running into trouble.
class TextFieldView: UIView {
#IBOutlet var contentView: TextFieldView!
#IBOutlet weak var customTextField: UITextField!
#IBOutlet weak var rightButton: UIButton!
#IBOutlet weak var placeHolderLabel: UILabel!
override init (frame: CGRect) {
super.init(frame: frame)
commonInit()
}
//This lets us use TextFieldView in IB
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
Bundle(for: TextFieldView.self).loadNibNamed("TextFieldView", owner: self, options: nil)
//Positioning content so it fills view space
contentView.frame = self.bounds
contentView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
addSubview(contentView)
}
You need something like:
/// This view must be connected with the main view of the XIB.
#IBOutlet private var view: UIView!
/// This method is used when creating an `ApexView` with code.
override init(frame: CGRect)
{
super.init(frame: frame)
initView()
}
/// This method is called when instantiated from a XIB.
required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
initView()
}
private func initView()
{
/// Fill in the name of your XIB. I assumed it `"TextFieldView"`.
Bundle.main.loadNibNamed("TextFieldView", owner: self, options: nil)
self.view.frame = CGRect(x: 0.0, y: 0.0, width: self.width, height: self.height)
self.addSubview(self.view!)
...
}
Related
This AssetRFPViewController class call a custom view(AssetBasicInfo) in viewDidLoad, if a pass "Hello" its ok but when i pass object to custom view(AssetBasicInfo) its not taken, How can i design a custom view class so its catch object
class AssetRFPViewController: UIViewController
{
var asset:Asset = Asset()
override func viewDidLoad() {
let customView = AssetBasicInfo(frame: self.topHeaderView.bounds)
customView.assetNameValLbl.text = "Hello" // ok
customView.assetObj = self.asset // not ok, passing object
self.topHeaderView.addSubview(customView)
}
}
Now my custom class look like this,
class AssetBasicInfo: UIView {
#IBOutlet var containerView: UIView!
var assetObj:Asset = Asset() // i want value in this object "assetObj"
#IBOutlet var assetNameValLbl: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
print(frame.size.width)
print(frame.size.height)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder : aDecoder)
commonInit()
}
private func commonInit(){
Bundle.main.loadNibNamed("HeaderViewXIB", owner: self, options: nil)
self.addSubview(containerView)
self.containerView.frame = self.frame
containerView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
self.assetNameValLbl.text = assetObj.name // not setting value
print("screenName" , screenName)
}
}
I have set the file owner to be UserBannerView.
The UIView in the storyboard that uses this .xib file is also set to be UserBannerView.
I am not getting any errors, yet it won't show up in either the simulator or the storyboard.
import UIKit
#IBDesignable class UserBannerView: UIView {
var view: UIView!
#IBOutlet weak var userCreditsLabel: UILabel!
#IBOutlet weak var userRenewDateLabel: UILabel!
#IBOutlet weak var userImage: circlePP!
#IBOutlet weak var userMembershipBtn: UIButton!
#IBOutlet weak var userNameLabel: UILabel!
var nibName:String = "UserBannerView"
public override init(frame:CGRect){
super.init(frame: frame)
print("UserBannerView init from frame")
setup()
}
public required init?(coder aDecoder:NSCoder){
super.init(coder: aDecoder)
print("UserBannerView init from decode")
setup()
}
override func awakeFromNib() {
print("UserBannerView awakeFromNib")
// setup()
}
func setup() {
print("UserBannerView:setup")
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "UserBannerView", bundle: bundle)
self.view = nib.instantiate(withOwner: self, options: nil).first as! UIView
self.view.frame = bounds
self.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.addSubview(self.view)
}
}
Try implementing your awakeFromNib method and add prepareForInterfaceBuilder method
override func awakeFromNib() {
super.awakeFromNib()
self.setup()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
setup()
}
Also make sure that your class is setted as fileOwner in your xib file
Hope this helps
I have been trying to figure this out for days and haven't had much luck :(
What I want to do is set the variable inside of an instance of a XIB (called BottomNav) that already exists in another ViewController, called "curX". I have come the closest with the following:
class Util: NSObject {
class func loadNib() {
let nib: BottomNav = Bundle.main.loadNibNamed("BottomNav", owner: self, options: nil)!.first as! BottomNav
nib.curX = 10
}
}
Here is the BottomNav Class:
class BottomNav: UIView {
#IBOutlet var view: UIView!
#IBOutlet weak var homeBtn: UIView!
#IBOutlet weak var scroller: UIScrollView!
#IBOutlet weak var scrollerContent: UIView!
var curX = 32
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
Bundle.main.loadNibNamed("BottomNav", owner: self, options: nil)
self.addSubview(self.view)
}
}
This passes the compiler with no warnings, but when it's ran I get a "this class is not key value coding-compliant for the key" error. This usually appears when there's an outlet that no longer exists, but this is definitely not the case, I've tested it with multiple XIBs that are already on the app, and had no problem loading in the first place via storyboards. I only get this error with "loadNibNamed".
Am I even on the right path here? My thought is maybe my Util class doesn't have access to Bundle or something?
class BottomNav: UIView {
#IBOutlet var view: UIView!
#IBOutlet weak var homeBtn: UIView!
#IBOutlet weak var scroller: UIScrollView!
#IBOutlet weak var scrollerContent: UIView!
var curX = 32
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
func commonInit(){
Bundle.main.loadNibNamed("BottomNav", owner: self, options: nil)
guard let content = view else { return }
content.frame = self.bounds
content.autoresizingMask = [.flexibleHeight, .flexibleWidth]
self.addSubview(content)
}
}
And when calling the instance, try the following.
let instance = BottomNav()
instance.curX = 30
Swift 3.0
I Think you get you solution from this. All the best
var view: UIView!
override init(frame: CGRect) {
// call super.init(frame:)
super.init(frame: frame)
// 3. Setup view from .xib file
xibSetup()
}
required init?(coder aDecoder: NSCoder) {
// call super.init(coder:)
super.init(coder: aDecoder)
// 3. Setup view from .xib file
xibSetup()
}
// MARK: - UI setup
func xibSetup() {
let nib = UINib(nibName: "BottomNav", bundle: nil)
view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
// use bounds not frame or it'll be offset
view.frame = bounds
// Make the view stretch with containing view
view.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]
addSubview(view)
}
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!"
When I try to use this custom control within my main view controller, by dragging a UIView onto screen in IB and setting it to "CustomerControlView", it doesn't actually show it.
Question - What is wrong with the code I have here?
Background - So wanting to basically:
a) design a customer control in IB
b) so I'm assuming I create the NIB file and then create a UIView file, so this is what I've done
Screenshot of NIB & swift file
Code
import UIKit
class CustomControlView: UIView {
// #IBOutlet var icon: UIImageView!
// #IBOutlet weak var view: UIView!
#IBOutlet weak var button: UIButton!
#IBOutlet weak var text1: UITextField!
#IBOutlet weak var text2: UITextField!
override init(frame: CGRect) {
print("override init(frame: CGRect) ")
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
print("required init?(coder aDecoder: NSCoder)")
super.init(coder: aDecoder)
// let arr = NSBundle.mainBundle().loadNibNamed("CustomControlView", owner: nil, options: nil)
// let v = arr[0] as! UIView
// self.view.addSubview(v)
}
}
Snapshot showing how I have included the custom view into my main viewController view:
Just add #IBDesignable above the class line to tell Xcode to compile it before showing it in storyboard. There is a great discussion on this subject here: http://nshipster.com/ibinspectable-ibdesignable/
Also, you need to make sure that the NIB is being loaded:
override init(frame: CGRect) {
print("override init(frame: CGRect) ")
super.init(frame: frame)
xibSetup()
}
required init?(coder aDecoder: NSCoder) {
print("required init?(coder aDecoder: NSCoder)")
super.init(coder: aDecoder)
xibSetup()
}
func xibSetup() {
view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
addSubview(view)
}
func loadViewFromNib() -> UIView {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: "CustomNumberPad", bundle: bundle)
let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
return view
}