14

Für diejenigen, die nicht wissen, worüber ich spreche, hat Xcode 6.0 neue Funktionen hinzugefügt, IBDesignable und IBInspectable.Können Sie IBidable-Eigenschaften mit Kategorien/Erweiterungen zu UIView hinzufügen?

Wenn Sie Ihre benutzerdefinierten Ansichten mit IBInspectable-Eigenschaften kennzeichnen, werden diese Eigenschaften im IB-Informationsfenster "Attribute" angezeigt.

Wenn Sie eine benutzerdefinierte UIView-Unterklasse mit IBDesignable kennzeichnen, kompiliert Xcode Ihre Ansichten und ruft den Code auf, um Ihre Ansichtsobjekte im Xcode-Fenster zu rendern, damit Sie sehen können, wie sie aussehen.

Die Technik zum Hinzufügen von IBDesignable und IBInspectable-Attributen zu benutzerdefinierten Ansichten ist in Swift und Objective-C ziemlich identisch. IBInspectable-Eigenschaften werden unabhängig von der Sprache, in der Sie sie definieren, im Attribute Inspector von Interface Builder angezeigt.

Ich habe eine Kategorie von UIView in Objective-C und eine Erweiterung von UIView in Swift erstellt, die die borderWidth-, cornerRadius-, borderColor- und layerBackgroundColor-Eigenschaften des zugrunde liegenden Layers der Ansicht als Eigenschaften der Ansicht heraufstufen. Wenn Sie die Eigenschaft ändern, gibt die Erweiterung/Kategorie die Konvertierung nach Bedarf ein und leitet die Änderung an den Layer weiter.

Der IBInspectable Teil funktioniert gut. Ich sehe und kann die neuen Eigenschaften im IB-Attribute-Inspektor einstellen.

Ich hätte letzte Woche schwören können, dass das IBDesignable-Attribut für meine Ansichtskategorie/-erweiterung ebenfalls funktionierte und ich mein benutzerdefiniertes UIView-Kategorierendering in IB mit seinen geänderten Ebenenattributen sehen konnte. Diese Woche funktioniert es nicht.

War ich halluzinieren?

Können Kategorien/Erweiterungen bestehender Systemklassen ihre benutzerdefinierte Benutzeroberfläche im Interface Builder erstellen, wenn sie mit IBDesignable eingerichtet sind?

+0

Ja, Sie können ... ich glaube. Welcher Teil funktioniert nicht? Sie können die Eigenschaften im Eigenschafteninspektor nicht festlegen? Oder Sie können sie im Inspektor festlegen, aber die Ansicht wird nicht aktualisiert, um die Änderungen zu berücksichtigen? – nhgrif

+0

Hmm, ich nehme das zurück. Es sieht so aus, als ob ich die Eigenschaften im Eigenschafteninspektor anzeigen kann, sie werden jedoch beim Interface Builder nicht aktualisiert. Wenn ich jedoch kompiliere und laufe, werden die Eigenschaften * angewendet. – nhgrif

+0

@nhgrif, ich hätte klarer sein sollen. Das ist richtig. Die Eigenschaften erscheinen im Inspektor, ich kann ihre Werte einstellen, und sie arbeiten dann im laufenden Programm. Die Ansicht spiegelt jedoch nicht die Änderungen im IB-Fenster wider. –

Antwort

20

Seit dem Stellen dieser Frage habe ich gelernt, dass @IBDesignable für Klassenerweiterungen nicht funktioniert. Sie können das Tag hinzufügen, es hat jedoch keine Auswirkungen.

+2

ist es einfach traurig, oder? – Fattie

+1

Werke: pod 'UIView-IBDesignable' – avishic

+1

Nein, es nicht. Ich habe es gerade jetzt getestet. Linke Ansicht ist eine Unterklasse von UIView, rechts - reine UIView. Sie haben die gleichen Attribute. http://imgur.com/a/o5Dwn Noch auf der Suche nach der Entscheidung – Dren

-3

Dieser Codeblock funktioniert gut für mich.

import UIKit 

public extension UIView { 
    @IBInspectable public var cornerRadius: CGFloat { 
     get { 
      return layer.cornerRadius 
     } 
     set { 
      layer.cornerRadius = newValue 
      layer.masksToBounds = newValue > 0 
     } 
    } 
} 

HINWEIS Es könnte funktionieren nicht, wenn sie von einem Rahmen importiert. Ich versuche jetzt den Grund herauszufinden.

+0

War das die Antwort auf deine Frage, Duncan? – Ducky

+0

Diese Antwort zeigt '@ IBInspectable', das OP hat bereits festgestellt, dass er gut funktioniert. Er fragt speziell nach '@ IBDesignable'. –

1

@IBDesignable Arbeit mit UIView Erweiterung nur in benutzerdefinierten Klasse.Zum Beispiel. UILabel ist eine Standardunterklasse von UIView. Es wird dort nicht funktionieren, aber wenn Sie eine benutzerdefinierte Klasse namens MyUILabel Unterklasse UILabel erstellen. Weisen Sie die MyUILabel-Klasse dem Label zu, an dem Sie arbeiten. Dann funktioniert Ihr Eckenradius in der UIView-Erweiterung von diesem MyUILabel. (Ich denke, die erste Woche, die es für Sie arbeitet, ist, weil Sie mit einigen benutzerdefinierten Klasse beschäftigen.)

0

Ich habe diese Arbeit für meinen Anwendungsfall gemacht, indem ich eine @ IBDesignable UIView, die ich als die Draufsicht in eingestellt habe Mein Blick Controller. Mein besonderer Anwendungsfall ist, dass der Stil von ClassyKit im Interface Builder in den UIKit-Standardansichten sichtbar gemacht wird, ohne dass dafür nur eine Unterklasse erstellt werden muss.

Hier ist ein Beispiel dafür, wie man es einrichten könnte:

// in Interface Builder set the class of your top view controller view to this 
@IBDesignable class DesignableView: UIView { 
} 

extension UIView { 
    open override func prepareForInterfaceBuilder() { 
     subviews.forEach { 
      $0.prepareForInterfaceBuilder() 
     } 
    } 
} 

extension UILabel { 
// just an example of doing something 
    open override func prepareForInterfaceBuilder() { 
     layer.cornerRadius = 8 
     layer.masksToBounds = true 
     backgroundColor = .red 
     textColor = .green 
    } 
} 
+0

Sigh, es sieht so aus, als ob IB die Laufzeitattribute nicht auf die nicht-designierbaren Klassen setzt ein Nichtstarter für meinen Gebrauch. Alles schien zunächst in meinem Anwendungsfall zu funktionieren, aber ich habe nur ein Stylesheet mit einem Selektor in der View-Klasse und nicht mit einem bestimmten Stil getestet - was von einem Laufzeitattribut abhängt. –

0

kann ich es unten mit Code funktioniert, aber die Nebenwirkung ist, dass einige Male IB-Agent in Storyboard stürzt ab, weil es zu Aktualisieren Sie zu viele UI-Elemente. Der Neustart von Xcode behebt das Problem vorübergehend bis zum nächsten Absturz. Vielleicht ist das das Problem OP

@IBDesignable 
extension UIView 
{ 

    @IBInspectable 
    public var cornerRadius: CGFloat 
    { 
     set (radius) { 
      self.layer.cornerRadius = radius 
      self.layer.masksToBounds = radius > 0 
     } 

     get { 
      return self.layer.cornerRadius 
     } 
    } 

    @IBInspectable 
    public var borderWidth: CGFloat 
    { 
     set (borderWidth) { 
      self.layer.borderWidth = borderWidth 
     } 

     get { 
      return self.layer.borderWidth 
     } 
    } 

    @IBInspectable 
    public var borderColor:UIColor? 
    { 
     set (color) { 
      self.layer.borderColor = color?.cgColor 
     } 

     get { 
      if let color = self.layer.borderColor 
      { 
       return UIColor(cgColor: color) 
      } else { 
       return nil 
      } 
     } 
    } 
} 

konfrontiert Deshalb habe ich wo Klausel hinzufügen versuche Subklassen zu verringern, die diese Funktionalität erweitern soll: Generic IBDesginables UIView extension