Переопределить метод setText UILabel? - PullRequest
4 голосов
/ 08 августа 2009

Я бы хотел переопределить метод UILabel setText, но я не уверен, что:

A) возможно, и
B) если возможно есть лучший способ достичь того, чего я пытаюсь достичь.

У меня есть подкласс UIView, у которого свойство UILabel является одним из его подвидов. Я хотел бы знать, когда изменяется свойство "text" UILabel, чтобы я мог настроить размер скругленного прямоугольника позади него. Если бы я владел UILabel, я бы просто переопределил setText ... но UILabel принадлежит Apple, и его реализация скрыта.

Итак, как мне быть с этим?

Ответы [ 6 ]

10 голосов
/ 26 сентября 2013

Подклассы UILabel могут легко переопределить метод setText. Я не совсем уверен, почему это еще не было включено в качестве законного ответа на этот 4-летний вопрос.

- (void) setText:(NSString *)text
{
    [super setText:text];

    [self sizeToFit];
}
10 голосов
/ 08 августа 2009

Вы можете использовать Key-Value Observing для отслеживания изменений свойства UILabel.text. Подход включает три этапа:

1) Регистрация для просмотра свойства, когда вы загружаете представление

[label addObserver:inspector
             forKeyPath:@"text"
                 options:(NSKeyValueObservingOptionNew |
                            NSKeyValueObservingOptionOld)
                    context:NULL];

2) Получение уведомления о любых изменениях:

- (void)observeValueForKeyPath:(NSString *)keyPath
              ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    if ([keyPath isEqual:@"text"]) {
        // put your logic here
    }
    // be sure to call the super implementation
    // if the superclass implements it
    [super observeValueForKeyPath:keyPath
                ofObject:object
                 change:change
                 context:context];
}

3) Отмена регистрации наблюдения, когда вы больше не заинтересованы:

[label removeObserver:inspector forKeyPath:@"text"];
6 голосов
/ 04 ноября 2014

Матовый ответ хорош для Objective-C, но не работает в Swift (нормально, его не было, когда он отвечал), принятый ответ от notnoop работает в Swift, даже если он сложнее, просто чтобы дать другую идею в swift, вы можете использовать didSet :

class MyLabel: UILabel {

  override var text: String? {
      didSet {
        if let text = text {
          println("the new text is: \(text)")
        } else {
          println("the text has been set to nil")
        }
      }
  }
3 голосов
/ 29 января 2016

На основании ответа Дрикс, я думаю, что это более правильный подход (использование set вместо didSet):

class UnreadCountLabel: UILabel {

    override var text: String? {
        set {
            if let newValue = newValue where !newValue.isEmpty {
                super.text = "  \(newValue)  "
                self.hidden = false
            } else {
                super.text = newValue
                self.hidden = true
            }
        }

        get {
            return super.text
        }
    }
}
2 голосов
/ 08 августа 2009

Вы просто используете скругленный прямоугольник в качестве фона для метки? Если это так, вы можете изучить использование UIIMage stretchableImageWithLeftCapWidth: topCapHeight. При этом будет создано созданное вами изображение с повторяющимся участком слева и сверху с указанной вами шириной, которое автоматически растянется до вашей ширины.

Если нет, то наблюдение Key-Value - это путь. Просто чтобы охватить другой вариант - это похоже на «игру с огнем», как сказал программист Apple Эван Долл в одной из своих лекций в Стэнфорде, - вы можете использовать метод swizzling для замены реализации одного метода на другую.

void method_exchangeImplementations(Method m1, Method m2);

В этом случае вы хотите настроить реализацию setText, но вы также хотите вызвать оригинальный setText в UILabel. Таким образом, вы можете обмениваться setText с setTextAndUpdateSize, а внутри setTextAndUpdateSize делать то, что изначально делает setText, и добавлять немного больше. Если вы смущены или думаете, что это плохая идея, возможно, это так. Вы можете получить объект Method для передачи в method_exchangeImplementations, вызвав class_getInstanceMethod ([NSSTring class], @selector (methodName).

Как только ваш метод swizzle был вызван один раз, внутри вашего нового метода вы можете вызвать старую реализацию setText из новой, используя, да, setTextAndUpdateSize. Это сбивает с толку и не рекомендуется, но это работает. Хороший пример можно найти в коде примера разработчика.

0 голосов
/ 30 декабря 2015

Я вытащил метод Swizzling в Swift 2.0. Изменение шрифта всего приложения путем замены реализации метки setText метки.

Скопируйте код в делегат приложения и используйте customSetText для изменения уровня приложения

   // MARK: - Method Swizzling

extension UILabel {
    public override class func initialize() {
        struct Static {
            static var token: dispatch_once_t = 0
        }

        // make sure this isn't a subclass
        if self !== UILabel.self {
            return
        }

        dispatch_once(&Static.token) {
            let originalSelector = Selector("setText:")
            let swizzledSelector = Selector("customSetText:")

            let originalMethod = class_getInstanceMethod(self, originalSelector)
            let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)

            let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))

            if didAddMethod {
                class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
            } else {
                method_exchangeImplementations(originalMethod, swizzledMethod)
            }
        }
    }

    // MARK: - Custom set text method for UI Label

    func customSetText(text: String) {
        self.customSetText(text)
        //set custom font to all the labels maintaining the size UILabel
        self.font = UIFont(name: "Lato-LightItalic", size: self.font.pointSize)
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...