ビュー階層を作成していないときにviewWillAppear
で問題が発生している人々に関する多くの投稿を読んだことがありますjust right。私の問題は、それが何を意味するのか理解できないことです。
RootViewController
を作成し、そのコントローラーでaddSubView
を呼び出すと、追加されたビューがviewWillAppear
イベントに結び付けられることが期待されます。
すべてのレベルでviewWillAppear
イベントを正常に受信する複雑なプログラムビュー階層の例はありますか?
Appleのドキュメントの状態:
警告:View Controllerに属するビューがView階層に直接追加された場合、View Controllerはこのメッセージを受け取りません。ビューをビュー階層に挿入または追加し、それにビューコントローラーがある場合は、関連するビューコントローラーにこのメッセージを直接送信する必要があります。 View Controllerにこのメッセージを送信しないと、関連するアニメーションが表示されなくなります。
問題は、彼らがこれを行う方法を説明していないことです。 「直接」とはどういう意味ですか?ビューを「間接的に」どのように追加しますか?
私はCocoaとiPhoneにかなり慣れていないので、基本的なHello WorldがらくたのほかにApple.
Navigation Controllerを使用してそのデリゲートを設定すると、view {Will、Did} {Appear、Disappear}メソッドは呼び出されません。
代わりに、Navigation Controllerデリゲートメソッドを使用する必要があります。
navigationController:willShowViewController:animated:
navigationController:didShowViewController:animated:
この同じ問題に遭遇しました。サブビューとして追加する前に、View ControllerにviewWillAppear
メッセージを送信するだけです。 (表示されるようにアニメーション化されているかどうかをView Controllerに伝えるBOOLパラメータが1つあります。)
[myViewController viewWillAppear:NO];
メトロノームの例のRootViewController.mを見てください。
(実際、Appleのサンプルプロジェクトは素晴らしいと感じました。HelloWorldよりも多くのことがあります;)
私はついにこれが機能する解決策を見つけました!
それの要点は、navコントロールのデリゲートをそれが含まれるviewcontrollerに設定し、UINavigationControllerDelegate
と2つのメソッドを実装することだと思います。ブリリアント!私はとても興奮して、最終的に解決策を見つけました!
私は同じ問題を抱えていました。私のアプリケーションには2つのNavigation Controllerがあり、それぞれに同じView Controllerをプッシュすると、1つのケースで機能し、他のケースでは機能しませんでした。つまり、最初のUINavigationController
でまったく同じView Controllerをプッシュすると、viewWillAppear
が呼び出されましたが、2番目のNavigation Controllerでプッシュされたときは呼び出されませんでした。
その後、私はこの投稿に出会いました INavigationControllerはviewWillAppear/viewWillDisappearメソッドを呼び出す必要があります
そして、私の2番目のナビゲーションコントローラーがviewWillAppear
を再定義したことに気付きました。コードをスクリーニングすると、私が電話していないことがわかりました
[super viewWillAppear:animated];
私はそれを追加し、それは働いた!
ドキュメントには次のように書かれています:
このメソッドをオーバーライドする場合、実装のある時点でsuperを呼び出す必要があります。
私はNavigation Controllerを使用しています。別のレベルのデータに降りる、またはカスタムビューを表示する場合は、次を使用します。
[self.navigationController pushViewController:<view> animated:<BOOL>];
これを行うと、viewWillAppear
関数が起動します。私は実際にaddSubView
メソッドを呼び出していないので、これが「間接的」とみなされると思います。 Navigation Controllerを使用しているかどうかはわかりませんが、これがアプリケーションに100%適用できるかどうかはわかりませんが、手がかりになるかもしれません。
まず、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
がウィンドウレベルにあり、ドキュメントがこれをバックアップしているように見えることが非常に重要だと思います。
それが明確であり、さらに質問に答えられることを願っています。
ビューは、[view addSubview:subview]
を呼び出すことで「直接」追加されます。ビューは、サブビューを交換するタブバーやナビゲーションバーなどの方法によって「間接的に」追加されます。
[view addSubview:subviewController.view]
を呼び出すときはいつでも、[subviewController viewWillAppear:NO]
(または場合によってはYES)を呼び出す必要があります。
ゲームのサブスクリーンに独自のカスタムルートビュー管理システムを実装したときに、この問題が発生しました。 viewWillAppearへの呼び出しを手動で追加すると、問題が解決しました。
これを行う正しい方法は、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];
}
答えは受け入れられず、人々(私がしたように)がここに着陸するので、バリエーションを与えます。それが元の問題かどうかはわかりませんが。 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ファイルにはビューがあり、このビューの下には、イメージとコントローラーを配置するコンテナー(別のビュー)のラベルがあります。以下にその外観を示します。これはクライアントの仕事であったため、いくつかのことをスクランブルしなければなりませんでした。
IOS 13に感謝します。
ViewWillDisappear
、ViewDidDisappear
、ViewWillAppear
およびViewDidAppear
は、iOS 13の表示モードコントローラーで呼び出されません。画面全体をカバーします。
クレジットは Arek Holko になります。彼は本当に私の一日を救った。
プッシュおよびポップビューコントローラーにこのコードを使用します。
押す:
[self.navigationController pushViewController:detaiViewController animated:YES];
[detailNewsViewController viewWillAppear:YES];
ポップ:
[[self.navigationController popViewControllerAnimated:YES] viewWillAppear:YES];
..そしてそれは私のためにうまく機能します。
よくある間違いは次のとおりです。ビューは1つ、UIView* a
、および別のUIView* b
。サブビューとしてbをaに追加します。 bでviewWillAppearを呼び出そうとしても、aのサブビューであるため、起動されません。
[self.navigationController setDelegate:self];
ルートビューコントローラーにデリゲートを設定します。
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デリゲートプロパティに割り当てます。
サブビューを追加しても、必ずしもビューが表示されるとは限らないため、クラスのメソッドへの自動呼び出しはありません。
「直接」とは、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をいただければ幸いです。
これが誰にも役立つ場合。 ViewWillAppear
がUITableViewController
で発火しないという同様の問題がありました。いろいろと遊んだ後、問題は、私のUINavigationController
を制御しているUITableView
がルートビューにないことであることに気付きました。これを修正すると、今ではチャンピオンのように機能しています。
私は自分でこの問題を抱えていましたが、それを修正するのに丸3時間(うち2回はグーグル)かかりました。
助けになったのは、単純にデバイス/シミュレーターからアプリを削除し、クリーンアップしてから再実行するでした。
役立つことを願っています
私はこれについて100%確信していませんが、ビュー階層にビューを直接追加することは、新しいView Controllerをプッシュする代わりに、View Controllerのビューで-addSubview:
(たとえば、[viewController.view addSubview:anotherViewController.view]
)を呼び出すことを意味すると思いますNavigation Controllerのスタックに。
ViewWillAppearはUIViewControllerクラスのオーバーライドメソッドなので、subViewを追加してもviewWillAppearは呼び出されませんが、viewControllerからPush、pop、show、setFrontまたはpopToRootViewControllerを提示すると、提示されたviewControllerのviewWillAppearが呼び出されます。
この問題を解決するクラスを作成しました。これをNavigation Controllerのデリゲートとして設定し、View Controllerにシンプルな1つまたは2つのメソッドを実装します-Viewが表示されようとしているとき、またはNavigationController経由で表示されたときに呼び出されます
私の場合、それはios 12.1エミュレーターの奇妙なバグでした。実際のデバイスで起動すると消えました。
私の場合、問題はカスタム遷移アニメーションにありました。設定されている場合modalPresentationStyle = .custom
viewWillAppear
は呼び出されません
カスタム遷移アニメーションクラスでは、メソッドを呼び出す必要があります:beginAppearanceTransition
およびendAppearanceTransition