2016-11-19 8 views
0

Obj-Cの@property (nonatomic) NSArray <SomeProtocol>* items;をミラーリングする最善の方法は、項目がUIViewのサブクラスです。以下の例ではプロトコルに準拠したUIViewサブクラスの素早い配列

、私はすべてのプロトコルに準拠していることUIKit成分(例えばUILabelUIButton、など)の配列を格納したいのですが、しかし、これはエラーにProtocol can only be used as a generic constraint because it has Self or associated type requirements

を与えるいくつかの代替の方法は何ですかこれをモデル化するのか?

例の遊び場:

import UIKit 

/// Protocol representing a form field model 
protocol FieldRepresentable {} 

/// Protocol representing a form UI control 
protocol FormControllable { 
    associatedtype FieldRepresentable 

    init(model: FieldRepresentable) 

    var model: FieldRepresentable { get } 
} 

/// Example label model 
class FormLabelElement: FieldRepresentable {} 

/// Example label UI control 
class FormLabel: UILabel, FormControllable { 

    required init(model: FormLabelElement) { 
     self.model = model 

     super.init(frame: CGRect.zero) 
    } 

    let model: FormLabelElement 

    required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } 
} 

/// Example form 
class Form: UIView { 

    // Error here 
    var fields: [FormControllable]? 

} 
+0

おそらくこの記事は助けになるかもしれません:https://milen.me/writings/swift-generic-protocols/ – nebs

+0

あなたのプロトコルを ':class'として宣言する必要があります。構造体ではなくオブジェクト – Paulw11

答えて

0

ネイト・クックはそれがFormControllableから関連するタイプを削除し、そのinit failableを作ることであろうアプローチする一つの簡単なっぽい道

を示唆しました。それぞれの準拠型は、基本的には、渡された特定のFieldRepresentable型で何をすべきかを知っていることを検証する必要があります。私はそのアプローチの最終版がされてしまったあなたは型の安全性/発現の少しを失うと思うが、不均一な配列

を持っている能力を獲得します:

import UIKit 

/// Protocol representing a form field model that is used to instantiate a UI control 
protocol FieldRepresentable: class {} 

/// Protocol representing a form UI control 
protocol FormControllable: class { 
    init?(model: FieldRepresentable) 
} 

/// Example label model 
class FormLabelElement: FieldRepresentable {} 

/// Example label UI control 
class FormLabel: UILabel, FormControllable { 

    required init?(model: FieldRepresentable) { 
     guard let model = model as? FormLabelElement else { return nil } 
     self.model = model 

     super.init(frame: CGRect.zero) 
    } 

    let model: FormLabelElement 

    required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } 
} 

/// Example form 
class Form: UIView { 
    var fields = [FormControllable]() 
} 

// Create a form 
let form = Form() 
let labelModel = FormLabelElement() 
let labelField = FormLabel(model: labelModel)! 
form.fields.append(labelField) 
print(form.fields) 

form.fields.forEach { (field) in 
    if field is FormLabel { 
     print("We have a label field") 
    } 
} 

お使いのモデルのプロトコルは十分に一般的なものであれば

あるいは、Soroushは

ひとつのアイデアは、theresのセット番号以来、列挙型にあなたのフィールド表現のタイプを作ることである提案しましたフォームフィールド要素のタイプの

は、次に、あなたはちょうどあなたがフィールドデータの例配列を取り、フォーム要素の配列にそれらをマッピングすることができ

とフォーム要素に列挙型を回す大きなスイッチを必要とする

関連する問題