2009-08-07 16 views
4

Ich mag UILabel außer Kraft zu setzen 's setText Methode, aber ich bin mir nicht sicher, dass:UILabels setText-Methode überschreiben?

A) es möglich ist, und
B) wenn vielleicht ist es eine bessere Art und Weise zu erreichen, was ich Ich versuche es zu erreichen.

Ich habe eine Unterklasse von UIView, die eine UILabel Eigenschaft als eine seiner Unteransichten hat. Ich würde gerne wissen, wenn sich die "Text" -Eigenschaft der UILabel ändert, so dass ich die Größe des abgerundeten Rechtecks ​​dahinter anpassen kann. Wenn ich im Besitz UILabel wäre, würde ich gerade setText überschreiben ... aber UILabel ist Apples und seine Implementierung ist versteckt.

Also, wie soll ich darüber gehen?

Antwort

10

Sie können Key-Value Observing verwenden, um Änderungen an der Eigenschaft UILabel.text zu verfolgen. Der Ansatz umfasst drei Schritte:

1) Registrieren der Eigenschaft zu beobachten, wenn Sie die Ansicht laden

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

2) Empfangen einer Benachrichtigung über Änderungen:

- (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- Registrierung der Beobachtung, wenn Sie nicht mehr interessiert sind:

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

Ist es möglich, einen Key Value Observer zu einem Unterklasse-Uilabel zum Beispiel in InitWithFrame hinzuzufügen: dann beobachten Sie diesen Wert in der gleichen Unterklasse uilabel? Ich erhalte den folgenden Fehler, wenn ich es versuche: 'An -observeValueForKeyPath: ofObject: change: context: Nachricht wurde empfangen, aber nicht bearbeitet. –

2

Verwenden Sie nur eine Runde d Rechteck als Hintergrund für das Label? Wenn dies der Fall ist, können Sie die Verwendung von UIIMage dreachableImageWithLeftCapWidth: topCapHeight untersuchen. Dadurch wird ein von Ihnen erstelltes Bild mit einem linken und oberen sich wiederholenden Abschnitt mit der von Ihnen angegebenen Breite erstellt und automatisch auf Ihre Breite gedehnt.

Wenn nicht, ist Key-Value-Beobachtung der richtige Weg. Nur um eine andere Option zu behandeln - das ist wie "Spielen mit Feuer", wie der Apple-Programmierer Evan Doll in einer seiner Stanford-Vorlesungen sagte - man kann Method Swizzling verwenden, um eine Methoden-Implementierung gegen eine andere auszutauschen.

void method_exchangeImplementations(Method m1, Method m2); 

In diesem Fall sollten Sie die Implementierung von setText optimieren, aber Sie wollen auch die ursprüngliche setText in UILabel nennen. So könntest du setText mit setTextAndUpdateSize austauschen, und innerhalb von setTextAndUpdateSize tust du, was setText ursprünglich tut, und füge etwas mehr hinzu. Wenn Sie verwirrt sind oder denken, dass dies eine schlechte Idee ist, ist es wahrscheinlich. Sie können ein Method-Objekt durch Aufruf von class_getInstanceMethod ([NSSTring-Klasse], @selector (Methodenname)) an

übergeben. Sobald Ihre Methode swizzle einmal aufgerufen wurde, können Sie innerhalb der neuen Methode die alte Implementierung von aufrufen setTextAndUpdateSize.Es ist verwirrend und nicht zu empfehlen, aber es funktioniert.Ein gutes Beispiel finden Sie in the developer sample code.

+0

Dies ist ein interessanter Ansatz, von dem ich nicht wusste ... aber in diesem Fall Ich denke, ich bleibe beim Mainstream ... Gut zu wissen. Danke. – Meltemi

+0

Subclassing und ist eine viel einfachere Möglichkeit zum Überschreiben einer Methode, es sei denn, Sie können die Klasse des UILabel nicht steuern. –

10

Unterklassen von UILabel kann die setText-Methode ziemlich leicht überschreiben.Ich bin nicht wirklich sicher, warum dies noch nicht als legitime Antwort auf diese 4 Jahre alte Frage enthalten ist.

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

    [self sizeToFit]; 
} 
+0

Ich musste 'sizeToFit' entfernen, um meins zur Arbeit zu bringen, sonst wäre der Text nicht sichtbar. – Joey

+0

Müssten Sie nicht UILabel ableiten, damit diese Lösung funktioniert? – tentmaking

+0

@eleven Ja, dies ist für Unterklasse 'UILabel's nur. –

6

Matt Antwort für Objective-C gut ist, funktioniert aber nicht in Swift (normal, es nicht existierte, als er beantwortet), die akzeptierte Antwort von notnoop funktioniert in schnellen, obwohl es komplizierter, nur um eine andere Idee in schnellen geben Sie das didSet verwenden:

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") 
     } 
     } 
    } 
0

ich zog die Methode Swizzling in Swift 2.0. Ändern der Schriftart der gesamten Anwendung durch Austauschen der Implementierung der setText-Methode des Labels.

Kopieren Sie den Code in AppDelegate und verwenden Sie die customSetText Anwendungsebene zu machen ändert

// 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) 
    } 
} 
3

Basierend auf Drix Antwort, ich denke, das ist ein richtiger Ansatz (mit set statt didSet):

+1

Das sollte richtige Antwort sein, wenn Sie Swift verwenden. – krlb

Verwandte Themen