@IBInspectable กับ enum?


87

ฉันต้องการสร้าง@IBInspectableองค์ประกอบตามที่คุณเห็นในภาพด้านล่าง:

ป้อนคำอธิบายภาพที่นี่

ความคิดของฉันคือใช้บางอย่างเช่น enum เป็นประเภทสำหรับ@IBInspectableแต่ดูเหมือนว่าจะไม่ใช่ในกรณีนี้มีความคิดอย่างไรที่จะใช้องค์ประกอบเช่นนี้

แก้ไข:

ดูเหมือนว่า@IBInspectableรองรับเฉพาะประเภทเหล่านี้:

  • Int
  • CGFloat
  • Double
  • String
  • Bool
  • CGPoint
  • CGSize
  • CGRect
  • UIColor
  • UIImage

คนเกียจคร้าน


วิธีแก้ปัญหาเฉพาะหน้าคือการใส่คุณสมบัติที่คำนวณได้ที่ตรวจสอบได้หน้าค่าที่คุณต้องการตั้งค่า แน่นอนว่ามันจะยังไม่ปรากฏเป็นเมนูป๊อปอัพของค่าที่แจกแจงใน Interface Builder อย่างน่าอัศจรรย์ แต่อย่างน้อยคุณสามารถกำหนดค่าที่ตรวจสอบได้และใช้เพื่อกำหนด enum
แมต

8
ที่ WWDC ปีนี้ฉันถามวิศวกรของ Apple ในห้องปฏิบัติการ Developer Tools เกี่ยวกับเรื่องนี้ เขาบอกว่าเขาเห็นด้วยว่ามันจะเป็นคุณสมบัติที่ยอดเยี่ยม แต่ตอนนี้ยังไม่สามารถทำได้ เขาแนะนำให้ฉันส่งเรดาร์ที่bugreport.apple.comซึ่งฉันทำ มันถูกปิดเนื่องจากเป็นปัญหาที่ซ้ำกัน 15505220 แต่ฉันขอแนะนำเป็นอย่างยิ่งให้ผู้ที่ใส่ปัญหาที่คล้ายกัน สิ่งเหล่านี้มักจะได้รับการแก้ไขหากมีคนบ่นมากพอ
Will Clarke

1
คำถามนี้แตกต่างจากstackoverflow.com/questions/27432736/…อย่างไร
SwiftArchitect

อาจซ้ำกันได้ของHow to create an IBInspectable of type enum
SwiftArchitect

และด้วย SwiftUI และ Canvas ใหม่ใน Xcode 11 ดูเหมือนว่าสิ่งนี้จะไม่อยู่ในแผนงานของ Apple
Ben Leggiero

คำตอบ:


27

เป็นไปไม่ได้ (สำหรับตอนนี้) คุณสามารถใช้ชนิดที่คุณเห็นในผู้ใช้กำหนด Runtime คุณสมบัติส่วน

จากเอกสารของ Apple :

คุณสามารถแนบแอ็ตทริบิวต์ IBInspectable กับคุณสมบัติใด ๆ ในการประกาศคลาสส่วนขยายคลาสหรือหมวดหมู่สำหรับประเภทใด ๆ ที่รองรับโดยแอ็ตทริบิวต์รันไทม์ที่กำหนดของ Interface Builder: บูลีนจำนวนเต็มหรือจำนวนทศนิยมสตริงสตริงที่แปลเป็นภาษาท้องถิ่นสี่เหลี่ยมผืนผ้าจุดขนาด , สี, ช่วงและศูนย์


2
เมื่อฉันต้องการใช้ enum ฉันจะกำหนดค่า enum ที่ชัดเจน (= 1, = 2 ฯลฯ ) และในตัวจัดการฉันเพิ่มการยืนยันถ้าค่าจาก IB ไม่ใช่ค่าใดค่าหนึ่งจาก enum น่ารำคาญที่ไม่รองรับ enums แต่เคล็ดลับนี้ทำให้ใช้งานได้มากขึ้นอย่างน้อยที่สุด
Zev Eisenberg

enum คือจำนวนเต็ม
Amin Negm-Awad

23

วิธีแก้ไขอีกประการหนึ่งสำหรับสิ่งนี้คือการเปลี่ยนแปลงลักษณะที่คุณสมบัติการแจงนับปรากฏต่อตัวสร้างอินเทอร์เฟซ ตัวอย่างเช่น:

#if TARGET_INTERFACE_BUILDER
@property (nonatomic, assign) IBInspectable NSInteger fontWeight;
#else
@property (nonatomic, assign) FontWeight fontWeight;
#endif

สิ่งนี้ถือว่า enum เรียกว่า FontWeight มันขึ้นอยู่กับข้อเท็จจริงที่ว่า enums และค่าจำนวนเต็มดิบสามารถใช้แทนกันได้ใน Objective-C หลังจากทำเช่นนี้คุณสามารถระบุจำนวนเต็มในตัวสร้างอินเทอร์เฟซสำหรับคุณสมบัติที่ไม่เหมาะ แต่ใช้งานได้และยังคงรักษาความปลอดภัยของประเภทไว้เล็กน้อยเมื่อใช้คุณสมบัติเดียวกันในเชิงโปรแกรม

นี่เป็นทางเลือกที่ดีกว่าการประกาศคุณสมบัติจำนวนเต็มแยกกันเนื่องจากคุณไม่จำเป็นต้องเขียนตรรกะเพิ่มเติมเพื่อจัดการคุณสมบัติจำนวนเต็มที่สองซึ่งสามารถใช้เพื่อทำสิ่งเดียวกันให้สำเร็จได้

อย่างไรก็ตามสิ่งนี้ใช้ไม่ได้กับ Swift เพราะเราไม่สามารถโยนจากจำนวนเต็มไปเป็น enum โดยปริยายได้ ความคิดในการแก้ปัญหาใด ๆ ที่จะได้รับการชื่นชม


2
ฉันคิดว่าสิ่งนี้ใช้ได้ผลใน Swift จริงๆ แต่ในการทดสอบเพิ่มเติม ... ไม่
Dan Rosenstark

7

ฉันทำสิ่งนี้โดยใช้ค่า NSInteger ที่ตรวจสอบได้และแทนที่ตัวตั้งค่าเพื่ออนุญาตให้ตั้งค่า enum สิ่งนี้มีข้อ จำกัด ในการไม่ใช้รายการป๊อปอัปและหากคุณเปลี่ยนค่า enum ตัวเลือกอินเทอร์เฟซจะไม่อัปเดตให้ตรงกัน

ตัวอย่าง.

ในไฟล์ส่วนหัว:

typedef NS_ENUM(NSInteger, LabelStyle)
{
    LabelStyleContent = 0, //Default to content label
    LabelStyleHeader,
};

...

@property LabelStyle labelStyle;
@property (nonatomic, setter=setLabelAsInt:) IBInspectable NSInteger labelStyleLink;

ในไฟล์การนำไปใช้งาน:

- (void)setLabelAsInt:(NSInteger)value
{
    self.labelStyle = (LabelStyle)value;
}

คุณสามารถเลือกที่จะเพิ่มตรรกะในนั้นเพื่อให้แน่ใจว่าถูกตั้งค่าเป็นค่าที่ถูกต้อง


ไม่แน่ใจว่าเหตุใดจึงโหวตไม่ลง ดูเหมือนจะเป็นวิธีที่ดีในการแก้ไขปัญหา
Fogmeister

ขอบคุณ @Fogmeister - ฉันกำลังใช้การใช้งานนี้ในแอพอยู่ในขณะนี้ :)
Matthew Cawley

4

Sikhapol ถูกต้องยังไม่รองรับ enums และยังไม่มีใน xCode 9 ฉันเชื่อว่าวิธีที่ปลอดภัยที่สุดคือการใช้ enums เป็นสตริงและใช้ IBInspectable var "shadow" (ส่วนตัว) นี่คือตัวอย่างของรายการ BarBtnPaintCode ซึ่งแสดงถึงรายการ barbutton ที่สามารถจัดสไตล์ด้วยไอคอนที่กำหนดเอง (ซึ่งทำได้โดยใช้ PaintCode) ภายใน Interface Builder (swift 4)

ในการสร้างอินเทอร์เฟซคุณเพียงแค่ป้อนสตริง (เหมือนกับค่า enum) ซึ่งจะทำให้ชัดเจน (ถ้าคุณป้อนตัวเลขไม่มีใครรู้ว่าหมายถึงอะไร)

class BarBtnPaintCode: BarBtnPaintCodeBase {

    enum TypeOfButton: String {
        case cancel
        case ok
        case done
        case edit
        case scanQr
        //values used for tracking if wrong input is used
        case uninitializedLoadedFromStoryboard
        case unknown
    }

    var typeOfButton = TypeOfButton.uninitializedLoadedFromStoryboard

    @IBInspectable private var type : String {
        set {
            typeOfButton = TypeOfButton(rawValue: newValue) ?? .unknown
            setup()
        }
        get {
            return typeOfButton.rawValue
        }
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    init(typeOfButton: TypeOfButton, title: String? = nil, target: AnyObject?, action: Selector) {
        super.init()
        self.typeOfButton = typeOfButton
        setup()
        self.target = target
        self.action = action
        self.title  = title
    }

    override func setup() {
        //same for all
        setTitleTextAttributes([NSAttributedStringKey.font : UIFont.defaultFont(size: 15)],for: UIControlState.normal)
        //depending on the type
        switch typeOfButton {
        case .cancel  :
            title = nil
            image = PaintCode.imageOfBarbtn_cancel(language: currentVisibleLanguage)
        case .ok      :
            title = nil
            image = PaintCode.imageOfBarbtn_ok(language: currentVisibleLanguage)
        case .done    :
            title = nil
            image = PaintCode.imageOfBarbtn_done(language: currentVisibleLanguage)
        case .edit    :
            title = nil
            image = PaintCode.imageOfBarbtn_edit(language: currentVisibleLanguage)
        case .uninitializedLoadedFromStoryboard :
            title = nil
            image = PaintCode.imageOfBarbtn_unknown
            break
        case .unknown:
            log.error("BarBtnPaintCode used with unrecognized type")
            title = nil
            image = PaintCode.imageOfBarbtn_unknown
            break
        }

    }

}

โซลูชันที่ยอดเยี่ยมที่ใช้กับ Swift 4 ไม่มีปัญหา หากคุณใช้สิ่งนี้โปรดระวังประเภทการสะกดที่ถูกต้องในสตอรีบอร์ดและ xibs
MindBlower3

1

อย่างที่ @sikhapol ตอบนี่ไม่ได้ วิธีแก้ปัญหาที่ฉันใช้สำหรับสิ่งนี้คือการมีIBInspectableบูลจำนวนมากในชั้นเรียนของฉันและเพียงแค่เลือกหนึ่งในตัวสร้างอินเทอร์เฟซ เพื่อความปลอดภัยเพิ่มเติมที่ไม่ได้ตั้งค่าหลายรายการให้เพิ่มNSAssertตัวตั้งค่าสำหรับแต่ละตัว

- (void)setSomeBool:(BOOL)flag
{
    if (flag)
    {
        NSAssert(!_someOtherFlag && !_someThirdFlag, @"Only one flag can be set");
    }
}

นี่เป็น IMO ที่น่าเบื่อเล็กน้อยและค่อนข้างเลอะเทอะ แต่เป็นวิธีเดียวที่จะทำให้เกิดพฤติกรรมแบบนี้ที่ฉันคิดได้


1

ฉันต้องการเพิ่มว่าตัวระบุของ an enumไม่พร้อมใช้งานในรันไทม์สำหรับทุกคนใน Objective-C ดังนั้นจึงไม่สามารถแสดงได้ทุกที่


1

วิธีแก้ปัญหาของฉันคือทำ:

@IBInspectable  
var keyboardType = UIKeyboardType.default.rawValue {
        didSet { 
             textField.keyboardType = UIKeyboardType(rawValue: keyboardType)! 
        }
}

ใน IB เองคุณจะต้องตั้งค่า int ในฟิลด์ keyboardType

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.