swift delegate showing nil - swift

I have created a .xib and adding this xib to another view. I want to add a delegate method in that .xib file. Here is my code :
.xib file
import UIKit
protocol CustomCheckBoxWithCrossDelegate {
func deleteCustomCheckbox(itemToDelete: String)
}
class CustomCheckBoxWithCross: UIView {
#IBOutlet weak var radioButton: UIButton!
#IBOutlet weak var checkboxLbl: UILabel!
#IBOutlet weak var checkboxCrossBtn: UIButton!
var blockIndexForTheCrossButton: Int = 0
var delegate: CustomCheckBoxWithCrossDelegate!
override init(frame: CGRect) {
super.init(frame: frame)
loadViewFromNib ()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
loadViewFromNib ()
}
func loadViewFromNib() {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: "CustomCheckBoxWithCross", bundle: bundle)
let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
view.frame = bounds
view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
self.addSubview(view);
}
#IBAction func crossBtnTapped(sender: AnyObject) {
print("Delegate --> \(delegate)")
delegate!.deleteCustomCheckbox("hello")
}
}
But in "crossBtnTapped" method I am getting nil value for that delegate.
can anyone please tell me what I am doing wrong?

You must have the instance of CustomCheckBoxWithCross in your other class, where you have implemented the protocol. Set delegate property of CustomCheckBoxWithCross instance to self in that file.

I ran to this error several times before, add if delegate is not nil condition.
#IBAction func crossBtnTapped(sender: AnyObject) {
if delegate != {
delegate!.deleteCustomCheckbox("hello")
}
}

Related

Call to IBOutlet in custom UIView from another class

I am looking for a way to refer to the IBOutlet variable in a custom class UIView, from another class. I found layoutSubviews, but each change only works on the first call, and not on each subsequent call. Thanks for help!
ViewController class:
var SB = StatusBar()
SB.update(1)
SB.update(2)
SB.update(3)
StatusBar class:
class StatusBar: UIView {
#IBOutlet var view: UIView!
#IBOutlet weak var label: UILabel!
var ActualStatus: Int!
required init?(coder: NSCoder) {
super.init(coder: coder)
xibSetup()
}
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
}
func update(status) {
ActualStatus = status
self.layoutSubviews()
}
override func layoutSubviews() {
super.layoutSubviews()
label.text = ActualStatus
}
func xibSetup() {
view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = [UIView.AutoresizingMask.flexibleWidth, UIView.AutoresizingMask.flexibleHeight]
addSubview(view)
}
func loadViewFromNib() -> UIView {
let bundle = Bundle(for: type(of:self))
let nib = UINib(nibName: "StatusBar", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
return view
}
}
Result: label.text is 1, change only works on the first call

Passing data from UIViewController to Custom UIView with XIB

I have the following swift file which controls a xib file
import UIKit
protocol SelectProfile: class {
func selectionUp(id: Int, selected: Bool)
}
class Component: UIView {
#IBOutlet weak var name: UILabel!
#IBOutlet weak var selection: UIView!
var selected: Bool = false
var profileId: Int = 6
weak var delegate: SelectProfile?
#IBAction func selProfile(_ sender: Any) {
selected = !selected
selection.isHidden = !selected
delegate?.selectionUp(id: profileId, selected: selected)
}
let nibName = "Component"
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
func commonInit() {
guard let view = loadViewFromNib() else { return }
view.frame = self.bounds
self.addSubview(view)
selection.isHidden = true
name.text = String(profileId)
}
func loadViewFromNib() -> UIView? {
let nib = UINib(nibName: nibName, bundle: nil)
return nib.instantiate(withOwner: self, options: nil).first as? UIView
}
}
In my UIViewController where I want to interact with the component I have the following code (shortened for brevity)
import UIKit
class Home: UIViewController, SelectProfile {
#IBOutlet weak var profileComponent: Component!
func selectionUp(id: Int, selected: Bool) {
print(id, selected)
}
override func viewDidLoad() {
profileComponent.delegate = self
profileComponent.profileId = 2
}
}
My delegate works nicely and I'm able to change the values for IBOutlets but I can't pass a value to variables. This line doesn't pass the data to my xib profileComponent.profileId = 2.
It seems like I have an issue with initialization of the xib but I don't know how to fix it.
The viewDidLoad of controller is called after view's init, so when you change profileId as you do, it is changed, but not reflected anywhere.
I assume the following, at least, missed:
var profileId: Int = 6 {
didSet {
name.text = String(profileId)
// call delegate here if needed as well
}
}

Xib, Label text Change

How do I work with a Label that hangs on a xib?
lblName.text = "Label Text"
I am getting error associated with
unexpectedly found nil while unwrapping an Optional value
You should update your custom View class in the following way.
First of all, open View.xib file set File's Owner custom class to View like the image in given below
after set UILabel IBOutlets like the image given below
After that open View.swift file and paste the code given below
class View: UIView {
private var view: UIView!
#IBOutlet weak var name: UILabel!
#IBOutlet weak var firstname: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
xibSetup()
}
//FIXME:- Set up
func xibSetup() {
view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]
addSubview(view)
}
func loadViewFromNib() -> UIView {
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "View", bundle: bundle)
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
return view
}
}
Now you can variable of View class in ViewController.

Hide Custom View UIButton From UIViewController Class

Actually i have a Custom view with two button, and i want to hide it at runtime through UIViewController , So i don't get any exact thing to hide that button from UIViewcontroller class
Here is my CustomView class,
import UIKit
class BottomButtonUIView: UIView {
#IBOutlet weak var btnNewOrder: UIButton!
#IBOutlet weak var btnChat: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
}
// MARK: init
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
if self.subviews.count == 0 {
setup()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
func setup() {
if let view = Bundle.main.loadNibNamed("BottomButtonUIView", owner: self, options: nil)?.first as? BottomButtonUIView {
view.frame = bounds
view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
addSubview(view)
}
}
#IBAction func btnOrderNowClick(_ sender: Any) {
let VC1 = StoryBoardModel.orderDeatalStoryBord.instantiateViewController(withIdentifier: "NewOrderViewController") as! NewOrderViewController
VC1.isPush = false
let navController = UINavigationController(rootViewController: VC1) // Creating a navigation controller with VC1 at the root of the navigation stack.
let currentController = getCurrentVC.getCurrentViewController()
currentController?.present(navController, animated:true, completion: nil)
}
#IBAction func btnChatNowClick(_ sender: Any) {
}
func getCurrentViewController() -> UIViewController? {
if let rootController = UIApplication.shared.keyWindow?.rootViewController {
var currentController: UIViewController! = rootController
while( currentController.presentedViewController != nil ) {
currentController = currentController.presentedViewController
}
return currentController
}
return nil
}
}
I set it to UIView in StoryBoard, and then I create outlet of that view,
#IBOutlet weak var viewBottmNewOrder: BottomButtonUIView!
Now i want to hide btnNewOrder from UIViewcontroller class but when i use
viewBottmNewOrder.btnNewOrder.isHidden = true it cause null exception, Please do need full answer.
Please don't do like that. The required init(coder aDecoder: NSCoder) will call a lot of times when the BottomButtonUIView created from xib. And your custom view will look like:
[BottomButtonUIView [ BottomButtonUIView [btnNewOrder, btnChat]]].
So when you access to btnNewOrder like that:
viewBottmNewOrder.btnNewOrder it will null.
I think you should add your custom view in viewDidLoad of your `UIViewController'.

Where to set UiTextField delegate method in custom UiView

Error occurs when I set UITextField delegate.
My code is:
import UIKit
class UserAlertVC: UIView , UITextFieldDelegate {
/*
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
}
*/
override init(frame: CGRect) {
super.init(frame: frame)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
self.addBehavior()
}
func addBehavior (){
print("Add all the behavior here")
userNameTxtField.delegate = self
passwordTxtField.delegate = self
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
return true
}
func textFieldDidBeginEditing(textField: UITextField) {
}
#available(tvOS 10.0, *)
func textFieldDidEndEditing(textField: UITextField, reason: UITextFieldDidEndEditingReason) {
}
#IBAction func actionOnCancel(sender: UIButton) {
self .removeFromSuperview()
}
#IBAction func actionOnProceed(sender: UIButton) {
self .removeFromSuperview()
UserAlertVC.showAlertForUser()
}
#IBOutlet var userNameTxtField: UITextField!
#IBOutlet var passwordTxtField: UITextField!
static func showAlertForUser() {
let alert = NSBundle.mainBundle().loadNibNamed("KeyboardViewController", owner: self, options: nil)!.last as! UIView
let windows = UIApplication.sharedApplication().windows
let lastWindow = windows.last
alert.frame = UIScreen.mainScreen().bounds
lastWindow?.addSubview(alert)
}
}
Error message is:
fatal error: unexpectedly found nil while unwrapping an Optional value
I have used Custom Alert View using XIB.pls suggest any solution.
Firstly take a look at life cycle of the view. Depending on this it is possible to highlight that method awakeFromNib is quite suitable because:
The nib-loading infrastructure sends an awakeFromNib message to each
object recreated from a nib archive, but only after all the objects in
the archive have been loaded and initialized. When an object receives
an awakeFromNib message, it is guaranteed to have all its outlet and
action connections already established.
Make sure to put an #IBOutlet for the .Xib content view, also you need to add the Nib code. Last, make sure in your ViewController you set your UIView Outlet to be UserAlertVC and you add the awakeFromNib method. Please find attached the code. Let me know if you need further help.
Here is the code related to the .xib file.
import UIKit
class UserAlertVC: UIView, UITextFieldDelegate {
//MARK: - Outlets
#IBOutlet var contentView: UIView!
#IBOutlet var userNameTxtField: UITextField!
#IBOutlet var passwordTxtField: UITextField!
//MARK: - Loads
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
commonInit()
}
//MARK: - Functions
func commonInit() {
Bundle.main.loadNibNamed("UserAlertVC", owner: self, options: nil)
userNameTxtField.delegate = self
passwordTxtField.delegate = self
contentView.translatesAutoresizingMaskIntoConstraints = false
addSubview(contentView)
// add constraints programmatically
}
// add the rest of your code
}
Here is the code related to the ViewController.
class ViewController: UIViewController {
//MARK: - Outlets
#IBOutlet weak var userAlertVC: UserAlertVC!
//MARK: - Loads
override func viewDidLoad() {
super.viewDidLoad()
}
override func awakeFromNib() {
super.awakeFromNib()
}
}