7015


ボタンが押されるとカスタムダイアログを表示するといったプログラムを組んでいるのですが、  
ルートの`ViewController`に`Main.Storyboard`にあるダイアログ用の`ViewController`を表示させるにはどうすればよろしいでしょうか？色々と調べていても実装例が少なく、下記のサイトを参考にしているのですがうまくいきません。（特に`objc_setAssociatedObject`というところで躓いてしまってます。。。）  
<https://codeiq.jp/magazine/2014/05/9493/>

どなたかカスタムダイアログの表示のさせ方が分かる方がいればご教授いただきたいです。  
すみませんが、よろしくお願いします。


CC BY-SA 3.0
2015-02-24T05:11:23.987
7007
2015-02-24T07:49:43.330
5210
question
objective-c storyboard dialog
iOSでのカスタムダイアログの表示


参考ページでは`UIWindow`を使用しているようなので、  
おそらくやりたい事とは異なると思いますが、参考程度になれば幸いです。  
※すみません、参考先はあまり読んでいません。

単純に`Storyboard`上の`ViewController`を表示させるだけなら下記のようなコードで可能です。

[code]

    - (IBAction)touchUp:(UIButton *)sender
    {
        UIStoryboard* sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
        CustomDialogViewController* vc = [sb instantiateViewControllerWithIdentifier:NSStringFromClass([CustomDialogViewController class])];
        [self presentViewController:vc animated:YES completion:nil];
    }
    
[/code]

ただ、これだと背景が真っ黒になってしまいますので、  
別案として`UIViewController`ではなく`UIView`を使用する方法もあります。

[code]

    - (IBAction)touchUpAdd:(UIButton *)sender
    {
        CustomDialogView* view = [CustomDialogView loadFromNib];
        view.delegate = self;
        view.frame = self.view.frame;
        view.alpha = 0.0f;
        [self.view addSubview:view];
        [UIView animateWithDuration:0.3f
                         animations:^{
                             view.alpha = 1.0f;
                         }
                         completion:nil];
    }
    
[/code]

こちらの方法だと背景に呼び出し元の`ViewController`を残すことが可能ですが、  
`Storyboard`ではなく`xib`を用意する必要があります（`xib`を作るのが嫌であれば全部コードで書くことも可能です）。

・UIViewControllerの場合  
![UIViewController](https://i.stack.imgur.com/jLWG6.png)

・UIViewの場合  
![UIView](https://i.stack.imgur.com/MpiO1.png)

----- 追記 -----  
`loadFromNib`は下記のような実装です。  
`xib`から読み込む場合のお決まりのような感じ（細部が若干異なる場合はあります）なので、  
`UIView`のカテゴリで用意しておくと、いちいち書かなくて良いので楽です。

[code]

    +(id)loadFromNib
    {
        return [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class])
                                              owner:nil
                                            options:nil]
                firstObject];
    }
    
[/code]

`view.delegate`はとりあえず消してしまっても動きに問題はありません。  
Objective-CのDelegateに関しては下記の質問が参考になると思います。  
[Objective-C の Delegateとは？](https://ja.stackoverflow.com/questions/4930)

`xib`の作成方法はご認識の通りで問題ありません。  
作成後に`xib`のアイデンティティインスペクタでCustom Classを紐付けるのを忘れないように気をつけて下さい。

念のための補足事項として、ダイアログ（CustomView）を閉じる際は、  
`removeFromSuperview`を使用します。  
※見えなくするだけなら`alpha`や`hidden`でも大丈夫だと思います。


CC BY-SA 3.0
2015-02-24T06:44:37.687
7015
2015-02-24T07:49:43.330
2017-04-13T12:52:39.113
-1
3516
7007
answer


つまづいているところの説明

[code]

    objc_setAssociatedObject
    
[/code]

> // ウィンドウのオーナーとしてアプリ自身に括りつけとく  
>  objc_setAssociatedObject([UIApplication sharedApplication],
> &kAssocKey_Window, window, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

上記の意味はシングルトンのインスタンス`[UIApplication
sharedApplication]`に`&kAssocKey_Window`というキー名で`window`というオブジェクトデータを`nonatomic,retain`の属性で保持する。という内容です。

`window`を取り出したい時には下記のようにします。(取り出したwinは多分UIWindowクラス型)

[code]

    id win = objc_getAssociatedObject([UIApplication sharedApplication],&kAssocKey_Window);
    
[/code]

上記は特殊なデータ保持の方法で、通常であれば各クラスで定義したプロパティに保持するようなデータをインスタンスに対して直接保持させることができます。  
この機能を使えば標準のフレームワーク内の各クラス(UIApplication,NSStringなどなんでも良い)の **インスタンス** に直接
**オブジェクトデータを保持できます** 。

利用シーンとして、カテゴリなどでは通常はインスタンス変数を追加できないですが、この機能を使えば擬似的にプロパティを追加することができます。

下記をインポートすると使えます。

[code]

    objc/runtime.h
    
[/code]


CC BY-SA 3.0
2015-02-24T07:08:56.767
7016
2015-02-24T07:08:56.767
7364
7007
answer