BarButtonItem (Картинка + текст) программно

swift

#1

Сегодня столкнулся с необходимостью создать BarButtonItem в котором будет картинка и текст!может кому будет полезно, или может кто подскажет лучше вариант!
Моя реализация:

Cоздаем функцию:

func createCustomButtonFromBarButtonItem(title: String, image: String, selector: Selector, reverse: Bool) -> UIBarButtonItem {
    let button = UIButton(type: .system)
    button.setImage(UIImage(named: image), for: .normal)
    let titleString = reverse ?  title + " " : " " + title
    button.setTitle(titleString, for: .normal)
    button.addTarget(self, action: selector, for: .touchUpInside)
    if reverse {
        button.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
        button.titleLabel?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
        button.imageView?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
    }
    button.sizeToFit()
    let barItem = UIBarButtonItem(customView: button)
    
    return barItem
}

Параметры в ней:
title - текст кнопки
image - имя картинки
selector - функция по нажатию на кнопку
reverse - положение картинки (false : картинка потом текст, true - наоборот)

Вызов:

 navigationItem.setRightBarButton(createCustomButtonFromBarButtonItem(title: "История", image: "next1", selector: #selector(ViewController.rightButtonTapped), reverse: true) , animated: true)

ну и не забываем про функцию на которую указывает селектор:

func rightButtonTapped (sender:UIButton) {
    print("rightButtonTapped")
}

Может кому пригодиться!Если кто-то знает другую реализацию прошу поделиться.


#2

Я бы сделал немного подругому:

extension UIBarButtonItem {
    convenience init(title: String, image: UIImage, target: Any, selector: Selector, reverse: Bool) {
        let button = UIButton(type: .system)
        let imageSize = CGSize(width: 22, height: 22)
        button.setImage(image.scale(to: imageSize), for: .normal)
        let titleString = reverse ?  title + " " : " " + title
        button.setTitle(titleString, for: .normal)
        button.addTarget(target, action: selector, for: .touchUpInside)
        
        if reverse {
            button.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
            button.titleLabel?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
            button.imageView?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
        }
        button.sizeToFit()

        self.init(customView: button)
    }
}

extension UIImage {
    func scale(to size: CGSize) -> UIImage {
        if self.size != size {
            UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
            self.draw(in: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(size.width), height: CGFloat(size.height)))
            let newImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return newImage!
        } else { return self }
    }
}

#3

Были у меня мысли в сторону extension, но как-то руки не дошли))