IBI प्रकार का IBInspectable कैसे बनाएं


83

enumहै एक अंतरफलक बिल्डर परिभाषित क्रम विशेषता। निम्नलिखित इंटरफ़ेस बिल्डर के गुण निरीक्षक में नहीं दिखता है:

enum StatusShape:Int {
    case Rectangle = 0
    case Triangle = 1
    case Circle = 2
}
@IBInspectable var shape:StatusShape = .Rectangle

दस्तावेज़ीकरण से: आप किसी भी संपत्ति के लिए IBInspectable विशेषता को क्लास डिक्लेरेशन, क्लास एक्सटेंशन, या किसी भी प्रकार के लिए संलग्न कर सकते हैं जो इंटरफ़ेस बिल्डर द्वारा निर्धारित रनटाइम विशेषताओं द्वारा समर्थित है: बूलियन, पूर्णांक या फ्लोटिंग पॉइंट नंबर, स्ट्रिंग, स्थानीय स्ट्रिंग, आयत। , बिंदु, आकार, रंग, सीमा और शून्य।

प्रश्न: मैं enumइंटरफ़ेस बिल्डर के गुण निरीक्षक में कैसे देख सकता हूं ?


1
उस सूची में एनम कहाँ है? आप क्यों सोचेंगे कि आप एक एनम का उपयोग कर सकते हैं?
पॉलव

13
यह अच्छा होगा enumकि मैं सीधे आई बी आई से एक मामला चुन सकता हूं, या एक UIFont, जैसे कि देशी UIKit ऑब्जेक्ट कर सकते हैं।
स्विफ्टआर्किटेक्ट

जवाबों:


76

स्विफ्ट 3

@IBInspectable var shape:StatusShape = .Rectangle केवल इंटरफ़ेस बिल्डर में एक रिक्त प्रविष्टि बनाता है:

आईबी में उपलब्ध नहीं है

एक एडेप्टर का उपयोग करें, जो स्विफ्ट और इंटरफ़ेस बिल्डर के बीच एक सेतु का काम करेगा ।
shapeAdapterआईबी से निरीक्षण योग्य है:

   // IB: use the adapter
   @IBInspectable var shapeAdapter:Int {
        get {
            return self.shape.rawValue
        }
        set( shapeIndex) {
            self.shape = StatusShape(rawValue: shapeIndex) ?? .Rectangle
        }
    }

आईबी में उपलब्ध है

सशर्त संकलन दृष्टिकोण (उपयोग करते हुए #if TARGET_INTERFACE_BUILDER) के विपरीत , shapeचर का प्रकार लक्ष्य के साथ नहीं बदलता है, संभवतः shape:NSIntegerबनाम shape:StatusShapeभिन्नताओं के साथ सामना करने के लिए आगे स्रोत कोड परिवर्तन की आवश्यकता होती है :

   // Programmatically: use the enum
   var shape:StatusShape = .Rectangle

पूरा कोड

@IBDesignable
class ViewController: UIViewController {

    enum StatusShape:Int {
        case Rectangle
        case Triangle
        case Circle
    }

    // Programmatically: use the enum
    var shape:StatusShape = .Rectangle

    // IB: use the adapter
    @IBInspectable var shapeAdapter:Int {
        get {
            return self.shape.rawValue
        }
        set( shapeIndex) {
            self.shape = StatusShape(rawValue: shapeIndex) ?? .Rectangle
        }
    }
}

H GitHub पर इस समाधान का पता लगाएं ।


आप shapeAsIntएक संगृहीत संपत्ति के बजाय एक संग्रहीत संपत्ति के रूप में क्यों रख रहे हैं?
nhgrif

सही। आप writeonlyहालांकि एक संपत्ति नहीं बना सकते हैं ... लेकिन एक गणना की गई संपत्ति आपके संग्रहीत संपत्ति की तरह बैकिंग इंस्टेंस चर नहीं बनाती है।
nhgrif

@Nhgrif द्वारा प्रस्तावित नो बैकिंग स्टोर समाधान जोड़ा गया ।
स्विफ्टआर्किटेक्ट

1
माफ़ करना मेरे डाउनवोट। मुझे लगा कि मेरे पास TARGET_INTERFACE_BUILDER के साथ काम करने का हल है लेकिन मुझे गुमराह किया गया। क्षमा करें, एसओ पर यहां शुभकामनाएं
डैन रोसेनस्टार्क

2017 के लिए तेजी से आगे बढ़ रही यह समस्या अभी भी वही है?
NoSixties

41

अपने निरीक्षण योग्य एनामों को ints के साथ सेट करने के बजाय, आप उन्हें स्ट्रिंग्स के साथ भी सेट कर सकते हैं। हालांकि ड्रॉपडाउन के रूप में काफी बेहतर नहीं है, कम से कम यह विकल्प पठनीयता के कुछ स्तर प्रदान करता है।

केवल स्विफ्ट विकल्प:

// 1. Set up your enum
enum Shape: String {
    case Rectangle = "rectangle" // lowercase to make it case-insensitive
    case Triangle = "triangle"
    case Circle = "circle"
}


// 2. Then set up a stored property, which will be for use in code
var shape = Shape.Rectangle // default shape


// 3. And another stored property which will only be accessible in IB (because the "unavailable" attribute prevents its use in code)
@available(*, unavailable, message: "This property is reserved for Interface Builder. Use 'shape' instead.")
@IBInspectable var shapeName: String? {
    willSet {
        // Ensure user enters a valid shape while making it lowercase.
        // Ignore input if not valid.
        if let newShape = Shape(rawValue: newValue?.lowercased() ?? "") {
            shape = newShape
        }
    }
}

यह भी संभव है कि यह उद्देश्य-सी के साथ काम करने के लिए मिल सकता है, साथ ही एक एनुइमर में इनिशियलाइज़र जोड़कर। हालाँकि, संकलक केवल आपके आईबी-केवल गुणों के लिए "अनुपलब्ध" त्रुटि को स्विफ्ट कोड में दिखाएगा।

Obj-C संगतता के साथ स्विफ्ट विकल्प:

@objc enum Shape: Int {
    case None
    case Rectangle
    case Triangle
    case Circle

    init(named shapeName: String) {
        switch shapeName.lowercased() {
        case "rectangle": self = .Rectangle
        case "triangle": self = .Triangle
        case "circle": self = .Circle
        default: self = .None
        }
    }
}

var shape = Shape.Rectangle // default shape

@available(*, unavailable, message: "This property is reserved for Interface Builder. Use 'shape' instead.")
@IBInspectable var shapeName: String? {
    willSet {
        if let newShape = Shape(rawValue: newValue?.lowercased() ?? "") {
            shape = newShape
        }
    }
}

2
मुझे Swift Onlyसंस्करण पसंद है : यह आईबी में सादे अंग्रेजी के लिए अनुमति देता है ।
स्विफ्टआर्किटेक्ट

क्या किसी को पता है कि इस पद्धति का उपयोग करके आईबी में स्ट्रिंग्स के ड्रॉपडाउन के रूप में प्रस्तुत किए गए विकल्पों को कैसे प्राप्त किया जाए?
ऐरोवे

मैं यह जानना चाहूंगा कि यदि संभव हो तो इसे ड्रॉपडाउन कृपया का उपयोग करके कैसे प्राप्त किया जाए।
वाएल

19

मुझे स्विफ्ट सिंटैक्स याद नहीं है, लेकिन यह है कि मैंने इसे ओब्ज-सी में हल कैसे किया

#if TARGET_INTERFACE_BUILDER
@property (nonatomic) IBInspectable NSInteger shape;
#else
@property (nonatomic) StatusShape shape;
#endif

1
एकमात्र जगह जो मेरे पास सशर्त विधानसभा है वह घोषणा में एक जगह है। कोई भी सशर्त असेंबली कहीं और नहीं है क्योंकि एक enum obj-c में पूर्णांक मान है। हटाने के लिए एक जगह जब सेब इसे ठीक करता है (यह मानते हुए कि वे करेंगे।)
जेसन बॉबीयर

यह एक मजाकिया और भयानक समाधान है, और यहां उल्लेख किया गया है nshipster.com/ibinspectable-ibdesignable
Dan Rosenstark

7

2020 के लिए - @SwiftArchitect उत्तर आज के लिए अपडेट किया गया:

यहाँ आज के सभी वाक्यविन्यास के साथ एक विशिष्ट पूर्ण उदाहरण है

यहाँ छवि विवरण दर्ज करें

import UIKit

@IBDesignable class ClipLabels: UILabel {
    
    enum Side: Int { case left, right }
    
    var side: Side = .left {
        didSet {
            common()
        }
    }
    
    @available(*, unavailable, message: "IB only")
    @IBInspectable var leftRight01: Int {
        get {
            return self.side.rawValue
        }
        set(index) {
            self.side = Side(rawValue: index) ?? .left
        }
    }
    

और सिर्फ उपयोग का एक उदाहरण ...

switch side {
    case .left:
        textColor = .red
    case .right:
        textColor = .green
    }

इस महत्वपूर्ण स्विफ्ट / iOS QA के लिए,

• @SwiftArchitect का बहुत पुराना उत्तर पूरी तरह से सही है लेकिन

• मैंने अभी इसे अपडेट किया है और महत्वपूर्ण "अनुपलब्ध" चीज़ को जोड़ा है, जो अब स्विफ्ट में संभव है।


4

यह एक पुराना धागा है लेकिन उपयोगी है। मैंने अपने जवाब को तेज करने के लिए अनुकूलित किया है 4.0 और Xcode 9.0 - स्विफ्ट 4 की इस समस्या के साथ अपने छोटे मुद्दे हैं। मेरे पास enum प्रकार के साथ एक @IBInspectable चर है और Xcode 9.0 खुश नहीं है, मुझे यह दिखाते हुए कि "संपत्ति @IBInspectable को चिह्नित नहीं किया जा सकता क्योंकि इसका प्रकार Objective-c में प्रतिनिधित्व नहीं कर सकता है"

@ एम्पोराइसे इस समस्या का उत्तर देता है (स्विफ्ट 3 के लिए) भाग में; स्टोरीबोर्ड के लिए एक संपत्ति का उपयोग करना लेकिन बाकी कोड के लिए एक सीधा एनम। नीचे एक अधिक पूर्ण कोड सेट है जो आपको दोनों मामलों में काम करने के लिए एक संपत्ति देता है।

enum StatusShape: Int {
  case Rectangle = 0
  case Triangle = 1
  case Circle = 2
}
var _shape:StatusShape = .Rectangle  // this is the backing variable

#if TARGET_INTERFACE_BUILDER
  @IBInspectable var shape: Int {    // using backing variable as a raw int

    get { return _shape.rawValue }
    set {
      if _shape.rawValue != newValue {
        _shape.rawValue = newValue
      }
    }
}
#else
var shape: StatusShape {  // using backing variable as a typed enum
  get { return _shape }
  set {
    if _shape != newValue {
      _shape = newValue
    }
  }
}
#endif

2

SwiftArchitect के आधार पर स्विफ्ट 3 समाधान

enum StatusShape: Int {
    case rectangle, triangle, circle
}
var statusShape: StatusShape = .rectangle
#if TARGET_INTERFACE_BUILDER
@IBInspectable var statusShapeIB: Int {
    get { 
        return statusShape.rawValue 
    }
    set { 
        guard let statusShape = StatusShape(rawValue: newValue) else { return }
        self.statusShape = statusShape
    }
}   //convenience var, enum not inspectable
#endif

2
यदि आप इस आईबी-निरीक्षण योग्य संपत्ति को एक #if TARGET_INTERFACE_BUILDERब्लॉक में लपेटते हैं, तो यह केवल इंटरफ़ेस बिल्डर में रेंडरिंग को प्रभावित करेगा, न कि रन टाइम पर। इससे अप्रत्याशित व्यवहार की संभावना होगी और आपको हमेशा कंसोल में चेतावनी मिलेगी:Failed to set (statusShapeIB) user defined inspected property ...: this class is not key value coding-compliant for the key statusShapeIB.
मिशा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.