Swift, confusion with UIBarButtonItem

若如初见. 提交于 2020-12-12 10:12:05

问题


I began to learn Swift recently. When I tried to make my first App I got confused with UIBarButtonItem. If I put let UIBarButtonItem initialization outside the viewDidLoad() function, nothing happens when I press the Next Button.

class ViewController: UIViewController, UITextFieldDelegate {
    let rightBarButton: UIBarButtonItem = UIBarButtonItem(title: "Next", style: .plain, target: self, action: #selector(onClickNext(button:)))

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = .white

        self.navigationItem.rightBarButtonItem = rightBarButton
    }

    func onClickNext(button: UIBarButtonItem) {
        print("should push view controller")
    }
}

However, when I put the initialization into the viewDidLoad() function, the output area does output the sentense that I set in the onClickNext(button:) function.

class ViewController: UIViewController, UITextFieldDelegate {
    var rightBarButton: UIBarButtonItem?

    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.backgroundColor = .white

        self.rightBarButton = UIBarButtonItem(title: "Next", style: .plain, target: self, action: #selector(onClickNext(button:)))
        self.navigationItem.rightBarButtonItem = rightBarButton
    }

    func onClickNext(button: UIBarButtonItem) {
        print("should push view controller")
    }
}

Also, I I found that when I put the initialization outside the viewDidLoad() function, and I add a UITextField to viewController, the rightBarButton works if I touch the textfield before I press the button.

That make me confused. What is the mechanism?


回答1:


Well, maybe you are missing how a ViewController works inside.

First, viewDidLoad is the area were you usually setup or initialize any view or properties of the view. This method is also called only once during the life of the view controller object. This means that self already exists.

Knowing this, is important to understand what a let property does, (from Apple)

A constant declaration defines an immutable binding between the constant name and the value of the initializer expression; after the value of a constant is set, it cannot be changed. That said, if a constant is initialized with a class object, the object itself can change, but the binding between the constant name and the object it refers to can’t.

Even though the upper area is where you declare variables and constants, is usually meant for simple initialization, it's an area for just telling the VC that there is an object that you want to work with and will have a class global scope, but the rest of functionality will be added when the view hierarchy gets loaded (means that the object does not depends of self, for example, when adding target to a button, you are referring to a method inside of self)....this variables or constants are called Stored Properties

In its simplest form, a stored property is a constant or variable that is stored as part of an instance of a particular class or structure. Stored properties can be either variable stored properties (introduced by the var keyword) or constant stored properties (introduced by the let keyword).

And finally, you have a lazy stored property that maybe can be applied for what you want:

A lazy stored property is a property whose initial value is not calculated until the first time it is used. You indicate a lazy stored property by writing the lazy modifier before its declaration.

Solution: create a lazy var stored property or add his properties inside ViewDidLoad (when self already exists)

lazy private var doneButtonItem : UIBarButtonItem = {
    [unowned self] in
    return UIBarButtonItem(title: "Next", style:UIBarButtonItemStyle.Plain, target: self, action: #selector(onClickNext(button:)))
    }()

OR

let rightBarButton: UIBarButtonItem?

override func viewDidLoad() {
        super.viewDidLoad()
        rightBarButton = UIBarButtonItem(title: "Next", style: .plain, target: self, action: #selector(onClickNext(button:)))
}



回答2:


import UIKit


    class ViewController: UIViewController {

        var  btnName = UIButton()



        override func viewDidLoad() {
            super.viewDidLoad()
            btnName.setImage(UIImage(named: "imagename"), for: .normal)
            btnName.frame = CGRect(x:0,y: 0,width: 30,height: 30)
            btnName.addTarget(self, action: #selector(addTargetActionForButton(:_)), for: .touchUpInside)

            let rightBarButton = UIBarButtonItem(customView: btnName)
            self.navigationItem.rightBarButtonItem = rightBarButton

        }

        func addTargetActionForButton(_ sender : UIButton){


        }
    }



回答3:


Your are taking let variable out side of viewDidLoad You can not take let global variable. if you want to take let than you need to declare inside viewDidLoad. Fore more info let and var check this link What is the difference between `let` and `var` in swift?

 override func viewDidLoad() {

  let rightBarButton: UIBarButtonItem  = UIBarButtonItem(title: "Next", style: .plain, target: self, action: #selector(onClickNext(button:)))

    super.viewDidLoad()
    self.view.backgroundColor = .white

    self.navigationItem.rightBarButtonItem = rightBarButton


}



回答4:


UIBatButtonItem may contain UIButton

above example image have UINavigationItem which contains LeftBarButtonItems ([UIBarButton]), and RightBarButtonItems([UIBarButtonItem]), each UIBarButtonItem contain UIButton

we can customise the UIButton to specify how to display in View And we can connect button action directly to the UIButton



来源:https://stackoverflow.com/questions/45408498/swift-confusion-with-uibarbuttonitem

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!