@IBInspectable ile enum?


87

@IBInspectableAşağıdaki resimde gördüğünüz gibi eleman oluşturmak istiyorum :

görüntü açıklamasını buraya girin

Benim fikrim, enum gibi bir şeyi tür olarak kullanmak @IBInspectable, ancak durum böyle değil gibi görünüyor, böyle bir öğenin nasıl uygulanacağına dair herhangi bir fikir?

DÜZENLE:

Görünüşe göre @IBInspectableyalnızca şu türleri destekliyor:

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

serseri


Bir tür geçici çözüm, ayarlamak istediğiniz değerin önüne incelenebilir bir hesaplanmış özellik koymaktır. Elbette, Interface Builder'da numaralandırılmış değerlerin bir açılır menüsü olarak sihirli bir şekilde görünmeyecek; ancak en azından incelenebilir bir değer tanımlayabilir ve bunu bir numaralandırma ayarlamak için kullanabilirsiniz.
matt

8
Bu yıl WWDC'de, Geliştirici Araçları laboratuvarındaki bir Apple mühendisine bunu sordum. Harika bir özellik olacağını kabul ettiğini, ancak şu anda mümkün olmadığını söyledi. Yaptığım bugreport.apple.com'da bir radar dosyalamamı önerdi . 15505220 numaralı sorunun bir kopyası olarak kapatıldı, ancak insanlara benzer sorunları koymalarını şiddetle tavsiye ederim. Yeterli sayıda insan şikayet ederse bu konular genellikle ele alınır.
Will Clarke



SwiftUI ve Xcode 11'deki yeni Canvas ile, bu hiçbir zaman Apple'ın yol haritasında olmayacak gibi görünüyor
Ben Leggiero

Yanıtlar:


27

Bu mümkün değil (şimdilik). Yalnızca Kullanıcı Tanımlı Çalışma Zamanı Nitelikleri bölümünde gördüğünüz türleri kullanabilirsiniz .

Apple'ın belgesinden :

IBInspectable niteliğini, Interface Builder tarafından desteklenen herhangi bir tür için sınıf bildirimindeki, sınıf uzantısındaki veya kategorideki herhangi bir özelliğe ekleyebilirsiniz: boole, tamsayı veya kayan nokta sayısı, dize, yerelleştirilmiş dize, dikdörtgen, nokta, boyut , renk, aralık ve sıfır.


2
Bir enum kullanmak istediğimde, enum değerlerine açık atamalar veriyorum (= 1, = 2, vb.). Ve işleyicide, IB'deki değer enum'daki değerlerden biri değilse bir iddia eklerim. Numaralandırmaların desteklenmemesi sinir bozucu, ancak bu numara onları en azından daha kullanışlı hale getiriyor.
Zev Eisenberg

Enum bir tamsayıdır.
Amin Negm-Awad

23

Bunun için başka bir çözüm, numaralandırma özelliğinin arabirim oluşturucuya nasıl göründüğünü değiştirmektir. Örneğin:

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

Bu, FontWeight adlı bir numaralandırmayı varsayar. Numaralandırmaların ve ham tam sayı değerlerinin Objective-C'de bir şekilde birbirinin yerine kullanılabileceği gerçeğine dayanır. Bunu yaptıktan sonra, ideal olmayan ancak çalışan ve aynı özelliği programlı olarak kullanırken küçük bir miktar tür güvenliğini koruyan özellik için Arabirim oluşturucuda bir tamsayı belirtebilirsiniz.

Bu, ayrı bir tamsayı özelliği bildirmekten daha iyi bir alternatiftir çünkü aynı şeyi başarmak için de kullanılabilecek ikinci bir tamsayı özelliğini işlemek için fazladan mantık yazmanıza gerek yoktur.

Ancak bu Swift ile çalışmaz çünkü bir tamsayıdan bir numaralandırmaya örtük olarak çeviremeyiz. Çözme ile ilgili herhangi bir düşünce takdir edilecektir.


2
Bunun
Swift'de

7

Bunu Inspectable NSInteger değeri kullanarak yapıyorum ve numaralandırmayı ayarlamasına izin vermek için ayarlayıcıyı geçersiz kılıyorum. Bu, bir açılır liste kullanmama sınırlamasına sahiptir ve enum değerlerinizi değiştirirseniz, arabirim seçenekleri eşleşecek şekilde güncellenmez.

Misal.

Başlık Dosyasında:

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

...

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

Uygulama dosyasında:

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

Geçerli bir değere ayarlandığından emin olmak için isteğe bağlı olarak oraya biraz mantık ekleyebilirsiniz.


Bunun neden reddedildiğinden emin değilim. Sorunu aşmanın iyi bir yolu gibi görünüyor.
Fogmeister

Teşekkürler @Fogmeister - Aslında şu anda bu uygulamayı bir uygulamanın içinde kullanıyorum :)
Matthew Cawley

4

Sikhapol doğru, numaralandırmalar henüz xCode 9'da desteklenmiyor. En güvenli yaklaşımın, numaralandırmaları dizeler olarak kullanmak ve bir "gölge" (özel) IBInspectable var uygulamak olduğuna inanıyorum. Burada, Interface Builder'ın (hızlı 4) içinde özel bir simge (PaintCode kullanılarak yapılır) ile stilize edilebilen bir barbutton öğesini temsil eden bir BarBtnPaintCode öğesi örneği.

Arayüz derlemesinde sadece dizeyi girersiniz (enum değeriyle aynıdır), bu da onu net tutar (sayı giriyorsanız kimse ne anlama geldiğini bilmiyor)

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 ile uygulanan harika çözüm, sorunsuz. Bunu kullanırsanız, hikaye tahtalarında ve xibs'de türlerini doğru yazarken dikkatli olun
MindBlower3

1

@Sikhapol'un yanıtladığı gibi, bu mümkün değil. Bunun için kullandığım geçici çözüm, IBInspectablesınıfımda bir sürü bool'a sahip olmak ve sadece arayüz oluşturucuda bir tane seçmek. Birden fazla olanın ayarlanmadığı ek güvenlik NSAssertiçin, her biri için ayarlayıcıya bir ekleyin .

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

Bu biraz sıkıcı ve biraz özensiz bir IMO, ancak düşünebildiğim bu tür davranışları gerçekleştirmenin tek yolu bu


1

Bir'in tanımlayıcılarının enumçalışma zamanında Objective-C'deki hiç kimse için mevcut olmadığını eklemek istiyorum . Yani onu herhangi bir yerde sergileme imkanı olamaz.


1

Benim çözümüm şuydu:

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

IB'nin kendisinde, keyboardType alanında bir int ayarlamanız gerekecek

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.