2017-02-06 3 views
4

次のように指定します。ジェネリッククラスは、デリゲートコールを具象サブクラスに転送しません

protocol EntityType { 
    var displayString: String { get } 
} 

extension String: EntityType { 
    var displayString: String { return self } 
} 

class GenericListViewController<Entity>: UIViewController, UITableViewDataSource, UITableViewDelegate where Entity: EntityType { 
    let items: [Entity] 

    let tableView: UITableView 

    init(items: [Entity]) { 
     self.items = items 
     self.tableView = UITableView() 

     super.init(nibName: nil, bundle: nil) 
    } 

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

    override func loadView() { 
     super.loadView() 

     tableView.translatesAutoresizingMaskIntoConstraints = false 
     view.addSubview(tableView) 

     NSLayoutConstraint.activate([ 
      tableView.topAnchor.constraint(equalTo: view.topAnchor), 
      tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), 
      tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), 
      tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor) 
     ]) 

     tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell") 
     tableView.dataSource = self 
     tableView.delegate = self 

    } 

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return items.count 
    } 

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) 
     cell.textLabel?.text = items[indexPath.row].displayString 

     return cell 
    } 

// func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 
//   
// } 
} 

class StringListViewController: GenericListViewController<String> { 
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 
     print("selected: \(items[indexPath.row])") 
    } 
} 

は、なぜ具体的なサブクラスで呼び出されていないtableView:didSelectRowAt:れますか?非ジェネリック型や親クラスに実装があり、サブクラスがそれをオーバーライドする場合、これは正常に動作します。これは期待された行動か、スウィフトバグですか、何か不足していますか?

答えて

1

可能性のあるバグのようです。私は、SwiftジェネリックスがObjective-Cランタイムには表示されないという事実と関連があるかもしれないと推測しています。したがって、GenericListViewController<Entity>に直接実装されたメソッドが呼び出されていても、SwiftとObj +オーバーライドを解明しようとするランタイム。間違いなくバグレポートの価値がある。

厳密なOOPでは、抽象スーパークラスは一般的にプロトコル自体に準拠していないことに注意してください。それらは単にデフォルト実装を提供するだけです。プロトコルの準拠を宣言し、欠落している実装を記入することは、依然として具体的なサブクラスに任されています。

上記のコードの場合は、GenericListViewController<Entity>クラスは、UITableViewDataSourceまたはUITableViewDelegateに準拠しないでください。具体的なサブクラスが(オーバーライドが必要な場合を除いて)それらのメソッド実装を書き直すことなく適合できるようにするデフォルトのメソッド実装を提供するだけです。 StringListViewControllerは、2つのプロトコルに準拠していることを宣言するものである必要があります。これを行うためにコードを変更すると、実際には期待どおりに動作します。

これは、Swift/Obj-C interopのバグを発見した可能性があるという事実は変わりません。私はあなたが現在を持っていることがであるべきだと信じていますが、それはプロトコル適合を扱う厳格なOOP方法ではありません。

+0

ダニエルありがとう、私はフィードバックに感謝し、私は同意します。私は最終的にこの考え方を再構築すべきですが、今この行動は私に不思議です。それは間違いなく相互運用に関係しているようです。 –

+0

今日、同じ問題で時間が無駄になった。どこでこれを報告できますか? –

+0

@ r-dent https://bugs.swift.org –

関連する問題