Объединение расширения и пользовательского класса в UIButton создает проблемы

У меня есть класс и расширение для UIButton. Пользовательский класс, убирающий заголовок и отображающий индикатор загрузки по клику (LoadingButton). - Расширение, объявляющее пользовательскую функцию для применения градиента к кнопке и т. д.

Оба работают, но вызов функции typeMain() для кнопки класса LoadingButton связан с проблемой — заголовок кнопки не удаляется, поэтому кнопка загрузки отображается поверх заголовка.

Как я могу объединить оба решения этой проблемы?

Кстати: button.typeMain() вызывают viewDidLoad().

Кнопка загрузки:

class LoadingButton: UIButton {
var originalButtonText: String?
var activityIndicator: UIActivityIndicatorView!

func showLoading() {
    originalButtonText = self.titleLabel?.text
    self.setTitle("", for: .normal)

    if (activityIndicator == nil) {
        activityIndicator = createActivityIndicator()
    }

    showSpinning()
}

func hideLoading() {
    self.setTitle(originalButtonText, for: .normal)
    activityIndicator.stopAnimating()
}

private func createActivityIndicator() -> UIActivityIndicatorView {
    let activityIndicator = UIActivityIndicatorView()
    activityIndicator.hidesWhenStopped = true
    activityIndicator.color = .white
    return activityIndicator
}

private func showSpinning() {
    activityIndicator.translatesAutoresizingMaskIntoConstraints = false
    self.addSubview(activityIndicator)
    centerActivityIndicatorInButton()
    activityIndicator.startAnimating()
}

private func centerActivityIndicatorInButton() {
    let xCenterConstraint = NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: activityIndicator, attribute: .centerX, multiplier: 1, constant: 0)
    self.addConstraint(xCenterConstraint)

    let yCenterConstraint = NSLayoutConstraint(item: self, attribute: .centerY, relatedBy: .equal, toItem: activityIndicator, attribute: .centerY, multiplier: 1, constant: 0)
    self.addConstraint(yCenterConstraint)
}

Расширение для настройки каждой кнопки:

extension UIButton {

func typeMain() {
    self.translatesAutoresizingMaskIntoConstraints = false
    let height = UIScreen.main.bounds.height * 0.07
    let width = UIScreen.main.bounds.width * 0.9
    self.heightAnchor.constraint(equalToConstant: height).isActive = true
    self.widthAnchor.constraint(equalToConstant: width).isActive = true

    layoutIfNeeded()

    self.addCharacterSpacing()
    self.tintColor = UIColor.white
    let color = UIColor(red: 11/255, green: 95/255, blue: 244/255, alpha: 1)
    let sndColor = UIColor(red: 106/255, green: 178/255, blue: 255/255, alpha: 1)

    self.layer.cornerRadius = self.frame.size.height / 5.0

    self.applyGradient(colours: [color, sndColor], locations: [0.0, 1.0])

    let shadowSize : CGFloat = 2.0
    self.layer.shadowColor = UIColor(red: 106/255, green: 178/255, blue: 255/255, alpha: 1).cgColor
    self.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
    self.layer.shadowOpacity = 0.4
    let shadowPath = UIBezierPath(rect: CGRect(x: -shadowSize / 2,
                                               y: shadowSize,
                                               width: self.frame.size.width + shadowSize,
                                               height: self.frame.size.height + shadowSize))
    self.layer.shadowPath = shadowPath.cgPath
    self.layer.shadowRadius = 5
    self.layer.masksToBounds = false
}

Расстояние между символами

extension UILabel {
func addCharacterSpacing(kernValue: Double = 0.5) {
    if let labelText = text, labelText.count > 0 {
        let attributedString = NSMutableAttributedString(string: labelText)
        attributedString.addAttribute(NSAttributedString.Key.kern, value: kernValue, range: NSRange(location: 0, length: attributedString.length - 1))
        attributedText = attributedString
    }
}

IIRC viewDidLoad вызывается только один раз для экземпляра UIViewController. Достаточно ли этого для ваших потребностей/ожиданий использования функции typeMain в вашем расширении? Мне кажется, что вам нужен собственный подкласс UIView (а не подкласс UIButton), который работает как кнопка, но делает совсем другие вещи.

Aaron 30.05.2019 17:38

Показать addCharacterSpacing метод

RajeshKumar R 30.05.2019 17:39

@RajeshKumarR см. редактирование.

Tom 30.05.2019 17:44
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
31
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В вашем пользовательском классе используется заголовок кнопки, а в методе расширения — кнопка с атрибутомTitle. Обновите свой собственный класс, чтобы сохранить ссылку на attributeTitle.

class LoadingButton: UIButton {
    var originalButtonText: String?
    var attributedButtonText: NSAttributedString?
    var activityIndicator: UIActivityIndicatorView!

    func showLoading() {
        originalButtonText = self.titleLabel?.text
        attributedButtonText = self.attributedTitle(for: .normal)
        self.setTitle("", for: .normal)
        self.setAttributedTitle(NSAttributedString(string: ""), for: .normal)

        if (activityIndicator == nil) {
            activityIndicator = createActivityIndicator()
        }            
        showSpinning()
    }        
    func hideLoading() {
        self.setAttributedTitle(attributedButtonText, for: .normal)
        self.setTitle(originalButtonText, for: .normal)
        activityIndicator.stopAnimating()
    }     
}

К сожалению, это не удалит заголовок кнопки при выполнении showLoading().

Tom 30.05.2019 18:08

Другие вопросы по теме