2016-03-31 13 views
5

にジェネリッククラスから継承したクラスを使用しているとき、それは今自体から継承するジェネリッククラスFetchedResultsTableViewController<TResultType, TCellType>から継承するよう、私は最近、UITableViewControllerからの単純な継承から私のクラスBookTableViewControllerをリファクタリングUITableViewController「インターフェイスビルダーファイルで不明なクラス」ストーリーボード

クラスの宣言は次のようになります。ストーリーボード、カスタムクラスとモジュールで

class BookTableViewController: FetchedResultsTableViewController<Book, BookTableViewCell> { 

    override func viewDidLoad() { 
     // breakpoints in here do not catch! 
    } 

} 

class FetchedResultsTableViewController<TResultType, TCellType: UITableViewCell>: 
    UITableViewController, NSFetchedResultsControllerDelegate { 

    // implementation here 

} 

は、両方のセットであり、私示唆、BookTableViewControllerクラスのコードにジャンプするには、矢印をクリックすることができますストーリーボードがクラスに正しくリンクされていること。しかし、私は、アプリケーションを実行しようとすると、クラスが認識されない - viewDidLoad()でコードが実行されない、と私のアプリ実行しているとき、私は、次のログに記録されたメッセージを受信します。

Interface Builderのファイルで不明なクラス_TtC12Reading_List23BookTableViewControllerを。

私はXCode 7.3(Swift 2.2)を実行しています。これはStoryboardsのバグでの制限ですか、何かを見逃しましたか?

ありがとうございます!

UPDATE

いくつかの実験をした後、一般的な継承ではなく、クラスのアクセスに関連すると思われるん。定義された以下のクラスでは:(ジェネリッククラスでも動作しませんが、ストーリーボードでの型引数を指定する方法はありませんよう、)

import Foundation 
import UIKit 

// Both of these classes are accessible by the Storyboard 
class FirstInheritance : UITableViewController{} 
class SecondInheritance : FirstInheritance{} 

// The generic class is also accessible 
class GenericViewController<T> : UITableViewController{} 

// But this class is not accessible... 
class ConcreteViewController : GenericViewController<String>{} 

ConcreteViewControllerを除くすべてのクラスは、ストーリーボードのクラスオートコンプリートで提案されています。

+0

は、それがストーリーボードがFetchedResultsTableViewControllerについて知らないことは可能ですか? –

+0

あなたのコメントに基づいて、私はストーリーボードのクラスフィールドが 'FetchedResultsTableViewController'を自動完成したが、' BookTableViewController'に自動補完していないことに気付きました。 (もちろん、型引数を指定することはできないので、 'FetchedResultsTableViewController'は機能しません)。 質問の更新で、より簡単な動作例を作成しました。例[here](https://github.com/AndrewBennet/GenericTableView)も参照してください。私はこれがストーリーボードの限界だと思っています... –

+0

ああ、はい、それは限界です。基本的に同じ質問がここで尋ねられました:http://stackoverflow.com/a/32899800。私は代わりにデフォルトの動作のためのタイプリアーゼと拡張機能を持つプロトコルを使ってみるかもしれません。 –

答えて

4

ゲームには少し遅れてしまいますが、この情報はスレッドにぶつかる人にとって便利です。

実際、私が言うことができる限り、スウィフト3のように、ストーリーボードでジェネリック医薬品のいくつかの種類のサポートが今やあります。

私はUIViewControllerを拡張して一般的な基本クラスを作成し、その汎用クラスのいくつかのサブクラスを制約し、ストーリーボードで使用しました。私の驚きに、完璧に動作

class GenericParent: UIViewController { 
    // Has a few, non-generic members ... 
} 

class ActualGenericClass<T>: GenericParent { 
    // There are more generic members in the actual class 
    var adapter: Adapter<T> = Adapter() 
} 

// This class is usable in Interface Builder; 
// although auto-complete won't show it, fully writing down 
// the class name works 
class SpecificInstanceOfActualGenericClass: ActualGenericClass<Int> { 
    @IBOutlet weak var tableView: UITableView! 
} 

実際のコードを怒鳴る指定されているものと同様のレイアウトになっています!

一方、次の例では、動作していないよう:

class GenericCell<T>: UITableViewCell { 
    var node: T? = nil 
} 
class SpecificCell: GenericCell<Int> { 
    @IBOutlet weak var coolTitleLabel: UILabel! 
} 

前と同じように、明示的に(セルのダイナミックプロトタイプに)Interface Builderの上のセルのクラス名を書くことでクラスを設定し、テーブルビューセル、およびアウトレットが表示されます。

しかし、実行時に、セルの動的プロトタイプを含むUIViewControllerをインスタンス化すると、セルをデキューするときに「インタフェースビルダーファイルの不明なクラス」という警告が表示され、Appがクラッシュします。

ので@Andewベネット、という声明:

ストーリーボードは、一般的なクラス

から継承するクラスは、あなたではあるが、それ以上の100%真実ではないようサポートしていません。少なくとも右にあった。私はこれを取り除くことができたのは初めてですが、部分的だけど!

私はいくつかのことがうまくいけば、他のものはうまくいかないが、それは何もないよりも優れている。

これは、Javaでとても気に簡単です...

2

ストーリーボードは、ジェネリッククラスから継承するクラスを直接的または間接的にサポートしていません。ストーリーボードのジェネリッククラスを継承するクラスを使用すると、実行時にそのクラスが不明であることを示すエラーが発生します。

代替はtypealiasesと拡張子のプロトコルを使用することである。

protocol MyProtocol { 
    associatedtype genericType1 
    associatedtype genericType2 

    func myFunc(argument1: genericType1, argument2: genericType2) 
} 

extension MyProtocol { 
    func defaultFunc(argument1: genericType1){ 
     // default implementation here 
    } 
} 

次のようにプロトコルが使用される:

class NonGenericClass: MyProtocol { 
    typealias genericType1 = Int 
    typealias genericType2 = String 

    func myFunc(argument1: genericType1, argument2: genericType2){ 
     // specific implementation here 
    } 
} 

クラスNonGenericClassMyProtocol拡張のすべての機能を有している(中この場合、defaultFunc(argument1: Int))。

プロトコルMyProtocolはまた、他のプロトコルから継承することができ、そしてそれら機能の実装は、MyProtocolに拡張定義することができます。したがって、プロトコルは、それに準拠する任意のクラスを、標準的な実装で、別のプロトコルにも適合させることができる。

ただし、これには、プロトコル内からクラス関数の標準オーバーライドを指定できないという制限があります。

関連する問題