3

カスタムテーブルビューとカスタムビューコントローラーを実装するとします(これは主にUITableViewControllersの動作を模倣しますが、プログラムで初期化すると...

@interface Foo : MyCustomTableViewController ...

Foo *foo = [[Foo alloc] init];

...は:の代わりにfoo.view一種のクラスです:MyCustomTableViewUITableView

// MyCustomTableView.h

@protocol MyTableViewDelegate <NSObject, UITableViewDelegate>

// ...

@end

@protocol MyTableViewDataSource <NSObject, UITableViewDataSource>

// ...

@end

@interface MyCustomTableView : UITableView

// ...

@end

// MyCustomTableViewController.h

@interface MyCustomTableViewController : UIViewController

// ...

@end

プログラムでサブクラス化するか、Interface Builderでカスタムクラスタイプをに設定してカスタムnibファイルから両方initのインスタンスを作成して使用できるように、メソッドを正しい順序/方法でどのように実装/オーバーライドする必要がありますか?MyCustomTableViewMyCustomTableViewControllerMyCustomTableView

これがまさにUITableView現在の方法(主にUIKit)であることに注意することが重要です。開発者は、プログラムで、またはペン先から作成することによって、File ownerメインviewまたはより複雑な階層のサブビューに関係なく、作成して使用できます。データソースまたはデリゲートを割り当てれば、準備は完了です...

これまでのところ、サブクラスMyCustomTableViewControllerを作成すると、これを機能させることができました。ここで、のインスタンスを作成し、メソッドMyCustomTableViewに割り当てます。しかし、、、、、、または他の何かがどのように動作するかを理解できませんでした。私はライフサイクルチェーンで迷子になり、毎回黒いビュー/画面になってしまいます。self.viewloadViewinitWithNibName:bundle:initWithCoder:awakeFromNibawakeAfterUsingCoder:

ありがとう。

4

3 に答える 3

0

UITableViewControllerがInterfaceBuilderに接続されているかどうかに関係なく、テーブルをロードする方法は本当に謎ですが、その動作をシミュレートするためのかなり良い方法を思いつきました。

MKMapViewを含む再利用可能なビューコントローラーでこれを実現したかったので、ビューの背景色をチェックすることでそれを実現するための秘訣を見つけました。

これが難しい理由は、self.viewを呼び出すと、ストーリーボードにデフォルトのUIViewが存在しない場合はロードまたはロードされるためです。ユーザーが実際にビューを設定しなかった場合、これら2つのステップの間にあるかどうかを判断する方法はありませんでした。つまり、ストーリーボードに由来するトリックには色があり、デフォルトでは無色です。

これで、コードまたはストーリーボードで使用でき、マップが設定されているかどうかさえ気にしないmapViewControllerができました。かなりクール。

- (void)viewDidLoad
{
    [super viewDidLoad];

    //magic to work without a view set in the storboard or in code.
    //check if a view has been set in the storyboard, like what UITableViewController does.
    //check if don't have a map view
    if(![self.view isKindOfClass:[MKMapView class]]){
        //check if the default view was loaded. Default view always has no background color.
        if([self.view isKindOfClass:[UIView class]] && !self.view.backgroundColor){
            //switch it for a map view
            self.view = [[MKMapView alloc] initWithFrame:CGRectZero];
            self.mapView.delegate = self;
        }else{
            [NSException raise:@"MapViewController didn't find a map view" format:@"Found a %@", self.view.class];
        }
    }
于 2013-12-09T07:55:10.227 に答える
-1

このようなクラスを作成するときに使用した戦略は、カスタム初期化コードをできるだけ遅く延期することでした。セットアップを待つviewDidLoadviewWillAppear実行でき、カスタムコードや同様のメソッドを記述できない場合initinitWithNibName:bundle:オブジェクトは親クラスと同じように初期化され、どのようにインスタンス化されたかはわかりません。init多くの場合、これらのメソッドをオーバーライドせずにクラスを作成することができます。

初期化コードをメソッドに配置する必要がある場合init、戦略は、初期化コードの1つのバージョンのみを記述し、それを別のメソッドに配置してから、すべてのinitメソッドをオーバーライドすることです。オーバーライドされたメソッドは、それ自体のスーパークラスバージョンを呼び出し、成功を確認してから、内部初期化メソッドを呼び出します。

これらの戦略が失敗し、このクラスのオブジェクトがインスタンス化される方法に実際に違いが生じる場合は、さまざまなinitメソッドごとにカスタムメソッドを記述します。

于 2012-09-21T14:47:54.527 に答える
-1

これが私が自分の問題を解決した方法です:

- (void)loadView
{
    if (self.nibName) {
        // although docs states "Your custom implementation of this method should not call super.", I am doing it instead of loading from nib manually, because I am too lazy ;-)
        [super loadView];
    }
    else {
        self.view = // ... whatever UIView you'd like to create
    }
}
于 2012-09-21T15:18:18.347 に答える