20

how could I get the frame of a rightbarbuttonItem in swift? I found this : UIBarButtonItem: How can I find its frame? but it says cannot convert NSString to UIView, or cannot convert NSString to String :

let str : NSString = "view" //or type String
let theView : UIView = self.navigationItem.rightBarButtonItem!.valueForKey("view")//or 'str'

The goal is to remove the rightBarButtonItem, add an imageView instead, and move it with a fadeOut effect.

Thanks

Community
  • 1
  • 1
Paul
  • 6,108
  • 14
  • 72
  • 128

3 Answers3

39

You should try it like:

var barButtonItem = self.navigationItem.rightBarButtonItem!
var buttonItemView = barButtonItem.valueForKey("view")

var buttonItemSize = buttonItemView?.size

Edit (Swift 3):

var barButtonItem = self.navigationItem.rightBarButtonItem!
let buttonItemView = barButtonItem.value(forKey: "view") as? UIView
var buttonItemSize = buttonItemView?.size
jarora
  • 5,384
  • 2
  • 34
  • 46
Christian
  • 22,585
  • 9
  • 80
  • 106
5

In Swift4, XCode9

    for view in (self.navigationController?.navigationBar.subviews)! {
        if let findClass = NSClassFromString("_UINavigationBarContentView") {
            if view.isKind(of: findClass) {
                if let barView = self.navigationItem.rightBarButtonItem?.value(forKey: "view") as? UIView {
                    let barFrame = barView.frame
                    let rect = barView.convert(barFrame, to: view)
                }
            }
        }
    }
ePing Tu
  • 51
  • 1
  • 1
  • 1
    @Aerox try to call this in viewDidAppear() method – Hosny Nov 20 '17 at 12:06
  • @Aerox you can also try calling this in `viewDidLayoutSubviews`, but you should be careful to avoid calling it more that it needs to be called. – ThomasW Jan 11 '18 at 03:19
4
import UIKit

class ViewController: UIViewController {

    let customButton = UIButton(type: .system)

    override func viewDidLoad() {
        super.viewDidLoad()

        customButton.setImage(UIImage(named: "myImage"), for: .normal)
        self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: customButton)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        print(self.customButton.convert(self.customButton.frame, to: nil))
    }
}

You must use UIBarButtonItem objects created with customView for this; UIBarButtonItem objects created the regular way don't have enough information exposed. It's important that the frame be looked up after the parent UINavigationController's UINavigationBar has completely laid out its entire subview tree. For most use cases, the visible UIViewController's viewDidAppear is a good enough approximation of this.

Dan Stenmark
  • 591
  • 6
  • 11