1

So Im trying to create a UIBarButtonItem with a custom UIView by subclassing it like so.

import UIKit
import SnapKit

class LocationManager: UIBarButtonItem {

    let createdView = UIView()
    lazy var currentCityLabel: UILabel = {
        let currentCityLabel = UILabel()
        currentCityLabel.text = "Philadelphia, PA"
        guard let customFont = UIFont(name: "NoirPro-SemiBold", size: 20) else {
            fatalError("""
        Failed to load the "CustomFont-Light" font.
        Make sure the font file is included in the project and the font name is spelled correctly.
        """
            )
        }
        currentCityLabel.adjustsFontForContentSizeCategory = true
        return currentCityLabel
    }()

    lazy var downArrow: UIImageView = {
        let downArrow = UIImageView()
        downArrow.contentMode = .scaleAspectFit
        downArrow.image = UIImage(named: "downArrow")
        return downArrow
    }()
    override init() {
        super.init()
        setupViews()
    }

    @objc func setupViews(){
        customView = createdView

        createdView.addSubview(currentCityLabel)
        currentCityLabel.snp.makeConstraints { (make) in
            make.left.equalTo(createdView.snp.left)
            make.top.bottom.equalTo(createdView)
        }

        createdView.addSubview(downArrow)
        downArrow.snp.makeConstraints { (make) in
            make.left.equalTo(currentCityLabel.snp.right).offset(5)
        }
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

However, when I create it and assign it in my viewController I see nothing

import UIKit

class ViewController: UICollectionViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        setupViews()
    }

    @objc func setupViews(){
        guard let collection = collectionView else {
            return
        }
        collection.backgroundColor = .white
        let customLeftBar = LocationManager()
        self.navigationController?.navigationItem.leftBarButtonItem = customLeftBar
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

I've looked at other post and none seem to quite match my situation. I'm beginning to think it is because I didn't give the UIView a frame but I am not exactly sure how I would do that in this instance if that is the case. Anyone see anything I don't that could potentially help me solve this problem. Also setting a target doesn't work I tried two different ways and none of them triggers a thing

  @objc func setupBarButtonItems(){
        let customLeftBar = LocationManager()
        customLeftBar.action = #selector(self.leftBarPressed)
        customLeftBar.target = self
        customLeftBar.customView?.isUserInteractionEnabled = true
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.leftBarPressed))
        customLeftBar.customView?.addGestureRecognizer(tapGesture)
        navigationItem.leftBarButtonItem = customLeftBar
    }


    @objc func leftBarPressed(){
        print("left bar tapped")
    }
0

1 Answer 1

5

Change your adding line from

self.navigationController?.navigationItem.leftBarButtonItem = customLeftBar

to

self.navigationItem.leftBarButtonItem = customLeftBar

When add the barItem, you need to add it via navigationItem of the ViewController, not NavigationController

EDITED for add the action

Your custom UIBarButtonItem is a Custom View's BarButtonItem, so the target and selector will not working.

You can add your custom action by adding a button into your customView, and send the action via closure

Init your closure

var didSelectItem: (() -> Void)?

Add the create button code in your @objc func setupViews()

    let button = UIButton(type: .custom)
    createdView.addSubview(button)
    button.snp.makeConstraints { (maker) in
        maker.top.bottom.leading.trailing.equalTo(createdView)
    }
    // button.backgroundColor = UIColor.cyan // uncomment this line for understand about the barbuttonitem's frame

    button.addTarget(self, action: #selector(didTap(_:)), for: .touchUpInside)

and add the function

@objc func didTap(_ button: UIButton) {
    print("Did tap button")
}

In your viewController, you can get the tap action by

customLeftBar.didSelectItem = { [weak self] in
    self?.leftBarPressed()
}

Unfortunately, your barbuttonitem's default frame is 30x30, so you must be set the frame for your barbuttonitem. If not, you can only catch the tap action in 30x30 area (uncomment the code for see it)

Sign up to request clarification or add additional context in comments.

5 Comments

also why when i try to add a target to the custom view does it just not work
@HiDungLing what do you mean? I don't understand what you want to ask. Do you mean you want to add a action to the BarItem?
@HiDungLing If you have additional problems, please ask a new question
why would i wait a whole hour and thirty minutes when i can just ask it now
any ideas @QuocNguyen

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.