しょぼしょぼプログラマ雑記

自分のための備忘録。 開発記録など掲載してます。 質問・ご意見・ご感想等はTwitter ( https://twitter.com/yun_hokuto ) までお気軽にどうぞ。

PopoverにNavigationControllerを使用する方法

iPadでPopover内にNavigationControllerのTableViewでネスト(ドリルダウン)するUIの作成方法についてです。

少々長いですが、お付き合いください。 

※今回の説明ではDelegateやStoryBoardから作るControllerViewインスタンスについては言及しません。

※Delegateがよくわからない場合はこちらを、StoryBoardから作るControllerViewインスタンスについてはこちらをご覧ください。

 

 

イメージ図

f:id:yun_hokuto:20120908073848p:plain

f:id:yun_hokuto:20120908073901p:plain

 

では早速作っていきましょう。

今回もSingle View Applicationで制作します。

 

StoryBoardにNavigationControllerを配置します。

f:id:yun_hokuto:20120908075509j:plain

 

できたTableViewControllerを削除

f:id:yun_hokuto:20120908080244j:plain

 

代わりに(親になる)VIewControllerを作成

f:id:yun_hokuto:20120908080514j:plain

 

NavigationControllerを右クリックしながらViewControllerへコネクションし、

出てくる黒いポップアップから「root view controller」を選択する。

f:id:yun_hokuto:20120908080804j:plain

 

ViewControllerにあるNavigationBar以外の余った領域にTableViewを配置

※TableViewControllerではありません。

f:id:yun_hokuto:20120908081150j:plain

 

さらにStoryBoardに(子になる)ViewControllerを配置し、領域一杯にTableViewを配置する。

f:id:yun_hokuto:20120908081625j:plain

 

 配置した2つのViewControllerにUIViewControllerを設定し、

各TableViewのPropertyをヘッダーに追加する。

※設定の仕方がわからない人は過去の記事を参照

 

ここで一つ目のポイント

NavigationControllerにはIdentifierのみ設定する」ということです。

CustomClassを設定しないようにしてください。

 

StoryBoardの設定はここまで。

次はプログラムです。

ポイントとなる部分のみ記載します。

 

・ViewController.m

@interfaceViewController ()

    @property (strong, nonatomic) UIPopoverController *povc;

@end

@implementation MainViewController

@synthesize povc;

 

 

- (IBAction)touchUpBUtton:(id)sender {

     NSMutableDictionary *dic = [[NSMutableDictionaryalloc]initWithCapacity:0];

    [dic setObject:[NSArrayarrayWithObjects:@"value1_1", @"value1_2", @"value1_3", nil] forKey:@"key1"];

    [dic setObject:[NSArrayarrayWithObjects:@"value2_1", @"value2_2", @"value2_3", nil] forKey:@"key2"];

    [dic setObject:[NSArrayarrayWithObjects:@"value3_1", @"value3_2", @"value3_3", nil] forKey:@"key3"];

    if(self.povc == nil){

       UINavigationController *nvc = [self.storyboardinstantiateViewControllerWithIdentifier:@"NavigationViewController"];

        ParentTableViewController *ptvc = (ParentTableViewController*)nvc.visibleViewController;

        [ptvc set__viewDictionary:dic];

        ptvc.delegate = self;

 

        [nvc setNavigationBarHidden:NOanimated:NO];

        [nvc popToRootViewControllerAnimated:YES];

        self.povc = [[UIPopoverControlleralloc]initWithContentViewController:nvc];

        self.povc.popoverContentSize = CGSizeMake(500, 300);

        self.povc.delegate = self;

    }

 

    if(self.povc.popoverVisible == YES) {

        [self.povcdismissPopoverAnimated:YES];

        self.povc = nil;

    } else {

        [self.povcpresentPopoverFromRect:((UIButton*)sender).frameinView:self.view         permittedArrowDirections:UIPopoverArrowDirectionUpanimated:YES];

    }

}

 

・ParentViewController.m

 

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

    [tableView deselectRowAtIndexPath:indexPath animated:NO];

    ChildViewController *childViewController = [self.storyboardinstantiateViewControllerWithIdentifier:@"ChildViewController"];

    childViewController.delegate = self;

 

    [childViewController.view setBounds:CGRectMake(0, 0, 500, 300)];

    [[selfnavigationController] pushViewController:childViewController animated:YES];

}

  

ParentViewControllerがNavigationControllerによって最初に表示されます。

なので、NavigationControllerをインスタンス化させた後、表示しているViewControllerという意味で

ParentViewControllerをインスタンス化します。

 

ここで2つ目のポイント

このとき「ParentViewControllerのDelegateをViewControllerとしておくこと」です。

 

そしてParentViewControllerのセルがタップされたとき、

pushという形でインスタンス化したChildViewControllerを設定。

そのときにセッターで配列を渡してあげれば自動的に表示される、というわけです。

あとはChileViewControllerのDelegate先をParentViewControllerに設定するわけです。

 

f:id:yun_hokuto:20120908094617p:plain

 

なぜこのような事をするのかというと、

NavigationControllerが間にあるせいで、通常のDelegateが繋げないからです。

(NavigationControllerのCustomClassを手で作れる人なら話は別)

これでChildViewControllerでどのセルが押されたかをViewControllerに伝える事ができます。

 

さらに、これにはもう一つメリットがあります。

それは「ChildViewControllerのセルやボタンが選択されたとき、Popoverを閉じることができる。」ということです。

 

PopoverはViewControllerがプロパティを保持&表示をしています。

閉じるタイミングを伝えないと、セルやBarButtonを押した際にPopoverを消す事ができません。

この方法ならDelegateが呼ばれた段階でPopoverをViewControllerから決してあげることができる、という訳です。

 

以上がNavigationControllerをPopoverにする際の簡易手順でした。

乱文で申し訳ありません。。。