Pregunta

Me gustaría reemplazar UILabel's setText método pero no estoy seguro de que:

A) es posible, y
B) si tal vez hay una mejor manera de lograr lo que estoy tratando de lograr.

Tengo una subclase de UIView que tiene un UILabel la propiedad como uno de sus sub-vistas.Me gustaría saber cuando el UILabel's de la propiedad "text" de los cambios, así que puedo ajustar el tamaño de la parte redondeada de la rect detrás de él.Si yo soy dueño de UILabel Yo acababa de reemplazar setText...pero UILabel es de Apple y su aplicación está oculto.

Así que, ¿cómo debo ir sobre esto?

¿Fue útil?

Solución

Puede utilizar Key-Value Observing seguimiento de los cambios en la UILabel.text de la propiedad.El enfoque implica tres pasos:

1) Registrarse para observar la propiedad, cuando se carga la vista

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

2) Recibir una notificación acerca de los cambios:

- (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) De-registro de la observación cuando usted no está interesado más:

[label removeObserver:inspector forKeyPath:@"text"];

Otros consejos

Las subclases de UILabel puede anular el método setText con bastante facilidad. No estoy realmente seguro de por qué esto todavía no se ha incluido como una respuesta legítima en esta cuestión de 4 años.

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

    [self sizeToFit];
}

Matt respuesta es bueno para Objective-C, pero no funciona en Swift (normal, no existía cuando respondió), la respuesta aceptada de notnoop trabaja en Swift, a pesar de que es más complicado, sólo para dar otra idea en rápida se puede utilizar el 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")
        }
      }
  }

En base a la respuesta Drix, creo que este es un enfoque más correcto (utilizando set en lugar de 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
        }
    }
}

¿Usted apenas está utilizando un rectángulo redondeado como el fondo para la etiqueta? Si ese es el caso, se puede ver en el uso UIImage stretchableImageWithLeftCapWidth: topCapHeight. Esto tomará una imagen que ha creado que tiene una sección de la parte superior izquierda y repitiendo con una anchura que especifique y lo estira a su anchura de forma automática.

Si no es así, por valor-clave de observación es el camino a seguir. Sólo para cubrir otra opción - esto es como "jugar con fuego", como dijo que Apple programador Evan muñeca en una de sus conferencias de Stanford - se puede utilizar el método swizzling intercambiar una implementación del método para otro.

void method_exchangeImplementations(Method m1, Method m2);

En este caso, desea modificar la implementación de setText, pero también desea llamar la setText original en UILabel. Por lo que podría intercambiar con setText setTextAndUpdateSize, y en el interior setTextAndUpdateSize hacer lo que hace setText originalmente además añadir un poco más. Si está confundido o piensa que esto es una mala idea, probablemente lo es. Se puede obtener un objeto Método para pasar a method_exchangeImplementations llamando class_getInstanceMethod ([clase NSString], @selector (methodName).

Una vez que su swizzle método ha sido llamado una vez, dentro de su nuevo método a continuación, puede llamar a la vieja implementación de setText desde dentro de la nueva usando, sí, setTextAndUpdateSize. Es confuso y no se recomienda, pero funciona. Un buen ejemplo se puede encontrar en el código de ejemplo revelador.

I sacó del Método Swizzling en Swift 2.0. Cambiar la fuente de toda la aplicación mediante el canje de la aplicación del método setText de la etiqueta.

Copiar el código en delegado de la aplicación y el uso del customSetText hacer cambios a nivel de aplicación

   // 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)
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top