web-dev-qa-db-ja.com

iPhoneビューが表示されない

ビュー階層を作成していないときにviewWillAppearで問題が発生している人々に関する多くの投稿を読んだことがありますjust right。私の問題は、それが何を意味するのか理解できないことです。

RootViewControllerを作成し、そのコントローラーでaddSubViewを呼び出すと、追加されたビューがviewWillAppearイベントに結び付けられることが期待されます。

すべてのレベルでviewWillAppearイベントを正常に受信する複雑なプログラムビュー階層の例はありますか?

Appleのドキュメントの状態:

警告:View Controllerに属するビューがView階層に直接追加された場合、View Controllerはこのメッセージを受け取りません。ビューをビュー階層に挿入または追加し、それにビューコントローラーがある場合は、関連するビューコントローラーにこのメッセージを直接送信する必要があります。 View Controllerにこのメッセージを送信しないと、関連するアニメーションが表示されなくなります。

問題は、彼らがこれを行う方法を説明していないことです。 「直接」とはどういう意味ですか?ビューを「間接的に」どのように追加しますか?

私はCocoaとiPhoneにかなり慣れていないので、基本的なHello WorldがらくたのほかにApple.

114
chzk

Navigation Controllerを使用してそのデリゲートを設定すると、view {Will、Did} {Appear、Disappear}メソッドは呼び出されません。

代わりに、Navigation Controllerデリゲートメソッドを使用する必要があります。

navigationController:willShowViewController:animated:
navigationController:didShowViewController:animated:
54
mmalc

この同じ問題に遭遇しました。サブビューとして追加する前に、View ControllerにviewWillAppearメッセージを送信するだけです。 (表示されるようにアニメーション化されているかどうかをView Controllerに伝えるBOOLパラメータが1つあります。)

[myViewController viewWillAppear:NO];

メトロノームの例のRootViewController.mを見てください。

(実際、Appleのサンプルプロジェクトは素晴らしいと感じました。HelloWorldよりも多くのことがあります;)

29
lajos

私はついにこれが機能する解決策を見つけました!

INavigationControllerDelegate

それの要点は、navコントロールのデリゲートをそれが含まれるviewcontrollerに設定し、UINavigationControllerDelegateと2つのメソッドを実装することだと思います。ブリリアント!私はとても興奮して、最終的に解決策を見つけました!

18
Chris

私は同じ問題を抱えていました。私のアプリケーションには2つのNavigation Controllerがあり、それぞれに同じView Controllerをプッシュすると、1つのケースで機能し、他のケースでは機能しませんでした。つまり、最初のUINavigationControllerでまったく同じView Controllerをプッシュすると、viewWillAppearが呼び出されましたが、2番目のNavigation Controllerでプッシュされたときは呼び出されませんでした。

その後、私はこの投稿に出会いました INavigationControllerはviewWillAppear/viewWillDisappearメソッドを呼び出す必要があります

そして、私の2番目のナビゲーションコントローラーがviewWillAppearを再定義したことに気付きました。コードをスクリーニングすると、私が電話していないことがわかりました

[super viewWillAppear:animated];

私はそれを追加し、それは働いた!

ドキュメントには次のように書かれています:

このメソッドをオーバーライドする場合、実装のある時点でsuperを呼び出す必要があります。

8
Antoine

私はNavigation Controllerを使用しています。別のレベルのデータに降りる、またはカスタムビューを表示する場合は、次を使用します。

[self.navigationController pushViewController:<view> animated:<BOOL>];

これを行うと、viewWillAppear関数が起動します。私は実際にaddSubViewメソッドを呼び出していないので、これが「間接的」とみなされると思います。 Navigation Controllerを使用しているかどうかはわかりませんが、これがアプリケーションに100%適用できるかどうかはわかりませんが、手がかりになるかもしれません。

5
Josh Gagnon

まず、Appleドキュメンテーション。これは正しい動作のためのキーです。

次に、canを使用して通知を手動で転送するためにUITabBarDelegate/UINavigationBarDelegateを使用しますが、ビュー呼び出しの階層全体を正しく動作させるには、手動で呼び出す必要がありました

[tabBarController viewWillAppear:NO];
[tabBarController viewDidAppear:NO];

そして

[navBarController viewWillAppear:NO];
[navBarController viewDidAppear:NO];

..それぞれのコントローラーにView Controllerをセットアップする前に一度だけ(割り当ての直後)。それ以降、子View Controllerでこれらのメソッドを正しく呼び出しました。

私の階層は次のようなものです。

window
    UITabBarController (subclass of)
        UIViewController (subclass of) // <-- manually calls [navController viewWill/DidAppear
            UINavigationController (subclass of)
                UIViewController (subclass of) // <-- still receives viewWill/Did..etc all the way down from a tab switch at the top of the chain without needing to use ANY delegate methods

初めてtab/navコントローラーで上記のメソッドを呼び出すだけで、すべてのイベントが正しく転送されることが保証されました。 UINavigationBarDelegate/UITabBarControllerDelegateメソッドから手動で呼び出す必要がなくなりました。

サイドノート:不思議なことに、うまくいかなかった場合、プライベートメソッド

- (void)transitionFromViewController:(UIViewController*)aFromViewController toViewController:(UIViewController*)aToViewController 

..動作中の実装のコールスタックから見ることができ、通常はviewWill/Did..メソッドですが、上記を実行するまでは呼び出されませんでした。

ただし、UITabBarControllerがウィンドウレベルにあり、ドキュメントがこれをバックアップしているように見えることが非常に重要だと思います。

それが明確であり、さらに質問に答えられることを願っています。

4
Sam

ビューは、[view addSubview:subview]を呼び出すことで「直接」追加されます。ビューは、サブビューを交換するタブバーやナビゲーションバーなどの方法によって「間接的に」追加されます。

[view addSubview:subviewController.view]を呼び出すときはいつでも、[subviewController viewWillAppear:NO](または場合によってはYES)を呼び出す必要があります。

ゲームのサブスクリーンに独自のカスタムルートビュー管理システムを実装したときに、この問題が発生しました。 viewWillAppearへの呼び出しを手動で追加すると、問題が解決しました。

3
AndrewS

これを行う正しい方法は、UIViewController包含APIを使用することです。

- (void)viewDidLoad {
     [super viewDidLoad];
     // Do any additional setup after loading the view.
     UIViewController *viewController = ...;
     [self addChildViewController:viewController];
     [self.view addSubview:viewController.view];
     [viewController didMoveToParentViewController:self];
}
3
Hari Kunwar

答えは受け入れられず、人々(私がしたように)がここに着陸するので、バリエーションを与えます。それが元の問題かどうかはわかりませんが。 Navigation Controllerをサブビューとして別のビューに追加する場合、次のようにviewWillAppear/Dissappearなどのメソッドを自分で呼び出す必要があります。

- (void) viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [subNavCntlr viewWillAppear:animated];
}

- (void) viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    [subNavCntlr viewWillDisappear:animated];
}

例を完成させるだけです。このコードは、ViewControllerに表示されます。ViewControllerでは、ビューに配置したビューにNavigation Controllerを作成して追加しました。

- (void)viewDidLoad {

    // This is the root View Controller
    rootTable *rootTableController = [[rootTable alloc]
                 initWithStyle:UITableViewStyleGrouped];

    subNavCntlr = [[UINavigationController alloc]   
                  initWithRootViewController:rootTableController];

    [rootTableController release];

    subNavCntlr.view.frame = subNavContainer.bounds;

    [subNavContainer addSubview:subNavCntlr.view];

    [super viewDidLoad];
}

.hは次のようになります

@interface navTestViewController : UIViewController <UINavigationControllerDelegate> {
    IBOutlet UIView *subNavContainer;
    UINavigationController *subNavCntlr;
}

@end

Nibファイルにはビューがあり、このビューの下には、イメージとコントローラーを配置するコンテナー(別のビュー)のラベルがあります。以下にその外観を示します。これはクライアントの仕事であったため、いくつかのことをスクランブルしなければなりませんでした。

alt text

3
hol

IOS 13に感謝します。

ViewWillDisappearViewDidDisappearViewWillAppearおよびViewDidAppearは、iOS 13の表示モードコントローラーで呼び出されません。画面全体をカバーします。

クレジットは Arek Holko になります。彼は本当に私の一日を救った。

enter image description here

2
BilalReffas

プッシュおよびポップビューコントローラーにこのコードを使用します。

押す:

[self.navigationController pushViewController:detaiViewController animated:YES];
[detailNewsViewController viewWillAppear:YES];

ポップ:

[[self.navigationController popViewControllerAnimated:YES] viewWillAppear:YES];

..そしてそれは私のためにうまく機能します。

2

よくある間違いは次のとおりです。ビューは1つ、UIView* a、および別のUIView* b。サブビューとしてbをaに追加します。 bでviewWillAppearを呼び出そうとしても、aのサブビューであるため、起動されません。

2
giuseppe
[self.navigationController setDelegate:self];

ルートビューコントローラーにデリゲートを設定します。

1
Gaurav

Swiftの場合。最初にviewWillAppearで呼び出したいものを呼び出すプロトコルを作成します

protocol MyViewWillAppearProtocol{func myViewWillAppear()}

次に、クラスを作成します

class ForceUpdateOnViewAppear: NSObject, UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool){
    if let updatedCntllr: MyViewWillAppearProtocol = viewController as? MyViewWillAppearProtocol{
        updatedCntllr.myViewWillAppear()
    }
}

}

3番目に、ForceUpdateOnViewAppearのインスタンスを、Navigation Controllerにアクセスできる適切なクラスのメンバーにし、Navigation Controllerが存在する限り存在するようにします。たとえば、Navigation ControllerのルートView Controller、または作成または表示するクラスです。次に、ForceUpdateOnViewAppearのインスタンスをできるだけ早くNavigation Controllerデリゲートプロパティに割り当てます。

1
Vadim Motorine

サブビューを追加しても、必ずしもビューが表示されるとは限らないため、クラスのメソッドへの自動呼び出しはありません。

1
winston

「直接」とは、xcodeの「Navigation Application」テンプレートと同じようにフックすることで、UINavigationControllerをアプリケーションのUIWindowの唯一のサブビューとして設定することです。

UINavigationControllerでこれらのコントローラーのプッシュ/ポップ時にオブジェクトViewControllersで呼び出されるWill/Did/Appear/Disappearメソッドを取得できる唯一の方法は、そのテンプレートを使用することです。ここでの回答にある他のソリューションはどれもうまくいきませんでした。たとえば、RootControllerに実装し、(子)NavigationControllerに渡すなどです。これらの関数(will/did/appear/disappear)は、トップレベルVC、「ログイン」、およびnavigationVCを表示/非表示にしたときにのみRootControllerで呼び出され、Navigation ControllerのサブVCではありません。 Nav VCに「パススルー」します。

UINavigationControllerのデリゲート機能を使用して、アプリでフォローアップ機能を必要とする特定のトランジションを検索しましたが、それは機能しますが、消える機能と表示される機能の両方を「シミュレート」するには、少し作業が必要です。

また、今日何時間もこの問題に頭を打ち込んだ後、動作させるのは原則の問題です。カスタムRootControllerと子ナビゲーションを使用する動作中のコードスニペットVCをいただければ幸いです。

1
Bogatyr

これが誰にも役立つ場合。 ViewWillAppearUITableViewControllerで発火しないという同様の問題がありました。いろいろと遊んだ後、問題は、私のUINavigationControllerを制御しているUITableViewがルートビューにないことであることに気付きました。これを修正すると、今ではチャンピオンのように機能しています。

1
Andrew

私は自分でこの問題を抱えていましたが、それを修正するのに丸3時間(うち2回はグーグル)かかりました。

助けになったのは、単純にデバイス/シミュレーターからアプリを削除し、クリーンアップしてから再実行するでした。

役立つことを願っています

1
Finn Gaida

私はこれについて100%確信していませんが、ビュー階層にビューを直接追加することは、新しいView Controllerをプッシュする代わりに、View Controllerのビューで-addSubview:(たとえば、[viewController.view addSubview:anotherViewController.view])を呼び出すことを意味すると思いますNavigation Controllerのスタックに。

1
Martin Gordon

ViewWillAppearはUIViewControllerクラスのオーバーライドメソッドなので、subViewを追加してもviewWillAppearは呼び出されませんが、viewControllerからPush、pop、show、setFrontまたはpopToRootViewControllerを提示すると、提示されたviewControllerのviewWillAppearが呼び出されます。

0
Abu Ul Hassan

この問題を解決するクラスを作成しました。これをNavigation Controllerのデリゲートとして設定し、View Controllerにシンプルな1つまたは2つのメソッドを実装します-Viewが表示されようとしているとき、またはNavigationController経由で表示されたときに呼び出されます

コードを示す要点はこちら

0
GregJaskiewicz

私の場合、それはios 12.1エミュレーターの奇妙なバグでした。実際のデバイスで起動すると消えました。

0
coldembrace

私の場合、問題はカスタム遷移アニメーションにありました。設定されている場合modalPresentationStyle = .customviewWillAppearは呼び出されません

カスタム遷移アニメーションクラスでは、メソッドを呼び出す必要があります:beginAppearanceTransitionおよびendAppearanceTransition

0
ober