0

I have a UIButton extension to make some of my buttons have a round shape:

extension UIButton {
    override open var intrinsicContentSize: CGSize {
      let originalContentSize = super.intrinsicContentSize
      let height = originalContentSize.height + 5
      layer.cornerRadius = height / 2
      layer.masksToBounds = true
      return CGSize(width: originalContentSize.width + 35, height: height)
    }
}

This works as intended for the buttons within my views. However, I also have some buttons in my navigation bars, which have been affected by this extension and now appear in their containers with extra padding that is rather unsightly.

This is how I usually create my navigation bar buttons:

private func navBarButton() -> UIBarButtonItem {
    let button = UIBarButtonItem(image: UIImage(named: "x"), style: .plain, target: self, action: #selector(x))
    button.tintColor = .black
    return button
}

Before I added my extension to the UIButton class, my navbar buttons used to look like this:

enter image description here

Now, they look like this:

enter image description here

which I do not want. How do I make my navbar buttons go back to what they looked like before adding my extension?

Swifty
  • 839
  • 2
  • 15
  • 40
  • if you want do it for 1 button, you don't need override func, you need create new and call it from button you want to change – canister_exister Nov 08 '18 at 17:54
  • I am doing it for 5 buttons, and on top of that I have 3 buttons in the navbars, which I do not want to apply this extension to. – Swifty Nov 08 '18 at 17:55
  • after you create extension call it from each button you want to edit, it will looks like myButton1.customContentSize(), myButton2.customContentSize(), myButton3.customContentSize() – canister_exister Nov 08 '18 at 17:57
  • when you override func in extension it will automatically work on all buttons you have, in your case you need create func in extension. check this https://stackoverflow.com/questions/43718510/swift-3-add-uibutton-extension-to-viewcontroller – canister_exister Nov 08 '18 at 18:00
  • Ah, I believe I understand where I was going wrong, thank you! – Swifty Nov 08 '18 at 18:12

2 Answers2

1

Change your extension from an override to a static function so it only happens when you explicitly instantiate one:

extension UIButton {
    static func createAsRound(size: CGSize) -> UIButton {
        let button = UIButton(type: .system)
        button.frame = CGRect(origin: CGPoint.zero, size: size)
        button.layer.cornerRadius = size.height/2
        button.layer.masksToBounds = true
        return button
    }
}

Usage:

let myButton = UIButton.createAsRound(size: CGSize(width: 40, height: 40))

EDIT. If you are using auto layout:

In your extension, add to 'createAsRound`

button.translatesAutoresizingMaskIntoConstraints = false

Then add another method that will only be called as needed:

func makeRound() {
    button.layer.cornerRadius = self.frame.height/2
    self.setNeedsDisplay()
}

This edit is untested code. I'll edit as needed. (The first code I've used many times and with auto layout).

Obviously the one line of code to add is, well, actually just a convenience. Once you set the auto mask flag you're telling iOS to use auto layout. Setting a "frame" versus setting explicit origin/size constraints - particularly if using layout anchors can be done in the extension as long as you've already instantiated the button's superview.

Dynamically changing the size? Once you glean the UIViewController hierarchy, it should be simple. One like place is viewDidLayoutSubviews where the instantiated UIButton should have had auto layout compute it's frame... at which point you just make it round.

This may not exactly fit your needs, but it should be a good start to creating exactly a round UIButton only when you want to.

  • Thank you for your answer. I see what you are doing there and it would be perfect if only it was not using `frame`, because I am using AutoLayout and my coworker told me that frames and AutoLayout should not be used together. I would like to know if there is a way for me to modify your code to work with AutoLayout. – Swifty Nov 08 '18 at 20:59
  • Thanks! Looking forward to it – Swifty Nov 08 '18 at 21:20
0

Why not to use an explicit class that will do exactly what you need?

class RoundedButton: UIButton {

    open override var intrinsicContentSize: CGSize {

        let originalContentSize = self.intrinsicContentSize
        let height = originalContentSize.height + 5
        layer.cornerRadius = height / 2
        layer.masksToBounds = true

        return CGSize(width: originalContentSize.width + 35, height: height)
    }
}
iPav
  • 101
  • 1
  • 7