iPhone viewWillAppear ไม่เริ่มทำงาน


116

ฉันได้อ่านโพสต์มากมายเกี่ยวกับผู้ที่มีปัญหาviewWillAppearเมื่อคุณไม่ได้สร้างลำดับชั้นมุมมองของคุณอย่างถูกต้อง ปัญหาของฉันคือฉันคิดไม่ออกว่ามันหมายถึงอะไร

หากฉันสร้างRootViewControllerและเรียกaddSubViewใช้คอนโทรลเลอร์นั้นฉันคาดว่ามุมมองที่เพิ่มเข้ามาจะเชื่อมต่อกับviewWillAppearเหตุการณ์ต่างๆ

ใครมีตัวอย่างของลำดับชั้นของมุมมองแบบเป็นโปรแกรมที่ซับซ้อนซึ่งรับviewWillAppearเหตุการณ์ในทุกระดับได้สำเร็จหรือไม่?

สถานะเอกสารของ Apple:

คำเตือน: หากมุมมองที่เป็นของตัวควบคุมมุมมองถูกเพิ่มลงในลำดับชั้นของมุมมองโดยตรงตัวควบคุมมุมมองจะไม่ได้รับข้อความนี้ หากคุณแทรกหรือเพิ่มมุมมองไปยังลำดับชั้นของมุมมองและมีตัวควบคุมมุมมองคุณควรส่งข้อความนี้ไปยังตัวควบคุมมุมมองที่เกี่ยวข้องโดยตรง การไม่ส่งตัวควบคุมมุมมองข้อความนี้จะป้องกันไม่ให้แสดงภาพเคลื่อนไหวที่เกี่ยวข้อง

ปัญหาคือพวกเขาไม่ได้อธิบายวิธีการทำเช่นนี้ "โดยตรง" หมายความว่าอย่างไร คุณ "ทางอ้อม" เพิ่มมุมมองอย่างไร

ฉันค่อนข้างใหม่สำหรับ Cocoa และ iPhone ดังนั้นคงจะดีถ้ามีตัวอย่างที่เป็นประโยชน์จาก Apple นอกเหนือจากเรื่องไร้สาระ Hello World พื้นฐาน


ฉันมีปัญหานี้จนกระทั่งฉันตระหนักว่าฉันเข้าใจผิดเกี่ยวกับการใช้คลาสย่อย UIViewController โดยทั่วไป ลองดูคำถามนี้ stackoverflow.com/questions/5691226/…
averydev

7
โปรดระวัง !!! ไม่มีจริงบน iOS 5 อีกต่อไป !!! โทร viewWillAppear และ viewDidAppear โดยอัตโนมัติ
Vilém Kurz

คำตอบ:


55

หากคุณใช้ตัวควบคุมการนำทางและตั้งค่าผู้รับมอบสิทธิ์เมธอดมุมมอง {Will, Did} {Appear, Disappear} จะไม่ถูกเรียกใช้

คุณต้องใช้วิธีการมอบหมายตัวควบคุมการนำทางแทน:

navigationController:willShowViewController:animated:
navigationController:didShowViewController:animated:

2
ฉันไม่ได้ตั้งค่าตัวแทนของตัวควบคุมการนำทางและวิธีนี้ยังไม่ได้รับการเรียก อย่างไรก็ตามฉันตั้งค่าแล้วฉันใช้วิธีที่คุณกล่าวถึงข้างต้น ขอบคุณ
Dimitris

ฉันเห็นสิ่งเดียวกันกับ Dimitris
jkp

7
ฉันเพิ่งทดสอบสิ่งนี้ใน iOS4 และ iOS5: นี่ไม่เป็นความจริง: การตั้งค่าตัวแทนของ navigationController จากนั้นดันมุมมองไปที่มันจะเริ่มการทำงาน viewWillAppear: ฯลฯ
DaGaMs

Swift 3: func navigationController (_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {} AND func navigationController (_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {}
Naloiko Eugene

28

ฉันพบปัญหาเดียวกันนี้ เพียงส่งviewWillAppearข้อความไปยังตัวควบคุมมุมมองของคุณก่อนที่คุณจะเพิ่มเป็นมุมมองย่อย (มีพารามิเตอร์ BOOL หนึ่งตัวที่บอกตัวควบคุมมุมมองว่ากำลังเคลื่อนไหวเพื่อให้ปรากฏหรือไม่)

[myViewController viewWillAppear:NO];

ดู RootViewController.m ในตัวอย่างเครื่องเมตรอนอม

(จริงๆแล้วฉันพบว่าโครงการตัวอย่างของ Apple นั้นยอดเยี่ยมมีมากกว่า HelloWorld มากมาย)


3
ที่จริงคุณควรเรียก viewWillAppear หลังจากที่คุณเพิ่มลงในมุมมองย่อย มิฉะนั้น IBOutlets / IBActions จะไม่ต่อสาย
4thSpace

2
ใช่หลังจากนั้น สร้างมุมมองย่อยจาก XIB แล้ว viewWillAppear ไม่ได้ถูกเรียก เรียกมันด้วยตัวเองและทุกอย่างทำงานได้ดี
JOM

ขอบคุณ! นี่คือสิ่งที่ถูกต้องสำหรับฉัน ฉันเพิ่มมุมมองย่อยด้วยตนเองผ่านทาง[scrollView addSubview:controller.view];. ฉันเพิ่มบรรทัด[controller viewWillAppear:NO];หลังจากนั้นและ voila! ทำงานอย่างมีเสน่ห์
Rob S.

ในความเป็นไปได้ทั้งหมดนี่เป็นเพราะ UIViewController ของคุณกำลังควบคุมมุมมองซึ่งเป็นมุมมองย่อยของมุมมองที่ควบคุมโดย UIViewController อื่น นี่ไม่ใช่รูปแบบการออกแบบที่ตั้งใจไว้ สำหรับคำอธิบายเพิ่มเติมโปรดดูที่โพสต์นี้ stackoverflow.com/questions/5691226/…
averydev

6
โปรดระวัง !!! ไม่มีจริงบน iOS 5 อีกต่อไป !!! เรียก viewWillAppear และ viewDidAppear โดยอัตโนมัติ หากคุณเรียกมันด้วยตนเองระบบจะเรียกสองครั้ง
Vilém Kurz

18

ในที่สุดฉันก็พบวิธีแก้ปัญหานี้ได้ผล!

UINavigationControllerDelegate

ฉันคิดว่าส่วนสำคัญของมันคือการตั้งค่าผู้รับมอบสิทธิ์การควบคุมการนำทางของคุณไปยังตัวควบคุมมุมมองที่มีอยู่และใช้งานUINavigationControllerDelegateและเป็นสองวิธี ยอดเยี่ยม! ฉันตื่นเต้นมากในที่สุดฉันก็พบวิธีแก้ปัญหา!


วิธีกำหนด rootviewcontroller เป็น delegate สำหรับ navigationcontroller
Gargo

1
มันไม่ทำงาน! พยายามย่อขนาดแอปและขยายให้ใหญ่ที่สุด
Vyachaslav Gerchicov

8

ฉันเพิ่งมีปัญหาเดียวกัน ในแอปพลิเคชันของฉันฉันมีตัวควบคุมการนำทาง 2 ตัวและการผลักตัวควบคุมมุมมองเดียวกันในแต่ละตัวใช้งานได้ในกรณีเดียวไม่ใช่อีกตัวหนึ่ง ผมหมายถึงว่าเมื่อผลักดันตัวควบคุมมุมมองที่แน่นอนเดียวกันในครั้งแรกUINavigationController, viewWillAppearถูกเรียก แต่ไม่เมื่อผลักดันในการควบคุมการนำทางที่สอง

จากนั้นฉันก็เจอโพสต์นี้UINavigationController ควรเรียกเมธอด viewWillAppear / viewWillDisappear

viewWillAppearและตระหนักว่าควบคุมการนำฉันที่สองได้สร้างนิยามใหม่ การตรวจสอบรหัสแสดงว่าฉันไม่ได้โทร

[super viewWillAppear:animated];

ฉันเพิ่มเข้าไปแล้วมันใช้งานได้!

เอกสารระบุว่า:

หากคุณลบล้างวิธีนี้คุณต้องเรียกใช้ super ณ จุดหนึ่งในการนำไปใช้งาน


สิ่งเดียวกันที่นี่ ยุ่งโดยไม่โทรหาซุปเปอร์.
olivaresF

5

ฉันใช้ตัวควบคุมการนำทาง เมื่อฉันต้องการลงไปสู่ระดับข้อมูลอื่นหรือแสดงมุมมองที่กำหนดเองของฉันฉันใช้สิ่งต่อไปนี้:

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

เมื่อฉันทำสิ่งนี้ฉันจะได้รับviewWillAppearฟังก์ชั่นเพื่อเริ่มการทำงาน ฉันคิดว่าสิ่งนี้เข้าข่ายเป็น "ทางอ้อม" เพราะฉันไม่ได้เรียกaddSubViewวิธีการจริงด้วยตัวเอง ฉันไม่ทราบว่าสิ่งนี้ใช้ได้กับแอปพลิเคชันของคุณ 100% หรือไม่เนื่องจากฉันไม่สามารถบอกได้ว่าคุณกำลังใช้ตัวควบคุมการนำทางหรือไม่ แต่อาจให้เบาะแส


5

ขอบคุณ iOS 13

ViewWillDisappear, ViewDidDisappear, ViewWillAppearและ ViewDidAppearจะไม่ได้รับการเรียกบนตัวควบคุมมุมมองการนำเสนอบน iOS 13 ซึ่งใช้นำเสนอกิริยาใหม่ที่ไม่ครอบคลุมทั้งหน้าจอ

เครดิตจะไปArek Holko เขาช่วยวันของฉันจริงๆ

ใส่คำอธิบายภาพที่นี่


4

ประการแรกแถบแท็บควรอยู่ที่ระดับรากกล่าวคือเพิ่มลงในหน้าต่างตามที่ระบุไว้ในเอกสารของ Apple นี่คือกุญแจสำคัญสำหรับพฤติกรรมที่ถูกต้อง

ประการที่สองคุณสามารถใช้UITabBarDelegate/ UINavigationBarDelegateเพื่อส่งต่อการแจ้งเตือนด้วยตนเองได้ แต่ฉันพบว่าเพื่อให้ลำดับชั้นของการเรียกดูทั้งหมดทำงานได้อย่างถูกต้องสิ่งที่ฉันต้องทำคือโทรด้วยตนเอง

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

และ

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

.. เพียงครั้งเดียวก่อนที่จะตั้งค่าตัวควบคุมมุมมองบนคอนโทรลเลอร์ที่เกี่ยวข้อง (ทันทีหลังจากการจัดสรร) จากนั้นมันเรียกวิธีการเหล่านี้อย่างถูกต้องบนตัวควบคุมมุมมองเด็ก

ลำดับชั้นของฉันเป็นดังนี้:

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

เพียงแค่เรียกใช้วิธีการที่กล่าวถึงบนตัวควบคุมแท็บ / การนำทางในครั้งแรกทำให้มั่นใจได้ว่าเหตุการณ์ทั้งหมดได้รับการส่งต่ออย่างถูกต้อง มันทำให้ฉันต้องโทรหาพวกเขาด้วยตนเองจากUINavigationBarDelegate/ UITabBarControllerDelegatemethod

Sidenote: อยากรู้อยากเห็นเมื่อมันไม่ได้ผลวิธีการส่วนตัว

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

.. ซึ่งคุณสามารถดูได้จาก callstack ในการนำไปใช้งานโดยปกติจะเรียกใช้viewWill/Did..method แต่ไม่ดำเนินการจนกว่าฉันจะดำเนินการด้านบน (แม้ว่าจะถูกเรียก)

ฉันคิดว่ามันสำคัญมากที่UITabBarControllerจะต้องอยู่ที่ระดับหน้าต่างและเอกสารดูเหมือนจะสำรองข้อมูลนี้

หวังว่าจะชัดเจน (ish) ยินดีที่จะตอบคำถามเพิ่มเติม


3

เนื่องจากไม่มีการยอมรับคำตอบและผู้คน (เช่นเดียวกับฉัน) ก็มาถึงที่นี่ฉันจึงให้การเปลี่ยนแปลงของฉัน แม้ว่าฉันไม่แน่ใจว่านั่นเป็นปัญหาเดิม เมื่อตัวควบคุมการนำทางถูกเพิ่มเป็นมุมมองย่อยไปยังมุมมองอื่นคุณต้องเรียกใช้วิธีการ viewWillAppear / Dissappear เป็นต้นด้วยตัวคุณเองดังนี้:

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

    [subNavCntlr viewWillAppear:animated];
}

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

    [subNavCntlr viewWillDisappear:animated];
}

เพียงเพื่อให้ตัวอย่างสมบูรณ์ รหัสนี้ปรากฏใน ViewController ของฉันที่ฉันสร้างและเพิ่มตัวควบคุมการนำทางลงในมุมมองที่ฉันวางไว้บนมุมมอง

- (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 ฉันมีมุมมองและด้านล่างมุมมองนี้ฉันมีป้ายกำกับรูปภาพและคอนเทนเนอร์ (มุมมองอื่น) ที่ฉันใส่คอนโทรลเลอร์ไว้นี่คือลักษณะที่ปรากฏ ฉันต้องแย่งของบางอย่างเพราะนี่เป็นงานของลูกค้า

ข้อความแสดงแทน


3

ผู้ชมที่มีการเพิ่ม "โดยตรง" [view addSubview:subview]โดยการเรียก มุมมองจะถูกเพิ่ม "ทางอ้อม" โดยวิธีต่างๆเช่นแถบแท็บหรือแถบนำทางที่สลับมุมมองย่อย

ทุกครั้งที่โทร[view addSubview:subviewController.view]คุณควรโทร[subviewController viewWillAppear:NO](หรือใช่แล้วแต่กรณีของคุณ)

ฉันมีปัญหานี้เมื่อฉันใช้ระบบจัดการมุมมองรูทที่กำหนดเองสำหรับหน้าจอย่อยในเกม การเพิ่มการโทรไปที่ viewWillAppear ด้วยตนเองช่วยแก้ปัญหาของฉัน


3

วิธีที่ถูกต้องในการทำเช่นนี้คือใช้ UIViewController containment 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];
}

นี่เป็นวิธีแก้ปัญหาสมัยใหม่ที่ถูกต้อง (iOS 9,8,7) นอกจากนี้หากคุณกำลังเปลี่ยนตัวควบคุมมุมมองแบบฝังทันทีคุณจะต้องเรียกใช้ [viewController willMoveToParentViewController: nil]; [viewController.view removeFromSuperview]; [viewController removeFromParentViewController];
Eli Burke

1
ในกรณีนี้viewWillAppear:อาจยังไม่ถูกเรียก
Vyachaslav Gerchicov

2

ฉันใช้รหัสนี้สำหรับตัวควบคุมแบบพุชและป็อปวิว:

ผลักดัน:

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

ป๊อป:

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

.. และมันก็ใช้ได้ดีสำหรับฉัน


2

ข้อผิดพลาดที่พบบ่อยมากมีดังนี้ คุณมีมุมมองหนึ่งและอีกคนหนึ่งUIView* a UIView* bคุณเพิ่ม b ลงใน a เป็นมุมมองย่อย หากคุณพยายามเรียก viewWillAppear ใน b จะไม่มีการเริ่มทำงานเนื่องจากเป็นมุมมองย่อยของไฟล์


2

iOS 13 บิตแอปของฉันไว้ที่นี่ หากคุณสังเกตเห็นการเปลี่ยนแปลงพฤติกรรมใน iOS 13 ให้ตั้งค่าสิ่งต่อไปนี้ก่อนที่คุณจะผลักดัน:

yourVC.modalPresentationStyle = UIModalPresentationFullScreen;

คุณอาจต้องตั้งค่าใน. สตอรี่บอร์ดของคุณในตัวตรวจสอบคุณสมบัติ (ตั้งค่าการนำเสนอเป็นแบบเต็มหน้าจอ)

สิ่งนี้จะทำให้แอปของคุณทำงานเหมือนใน iOS เวอร์ชันก่อน ๆ


1

ฉันไม่แน่ใจ 100% ในเรื่องนี้ แต่ฉันคิดว่าการเพิ่มมุมมองไปยังลำดับชั้นมุมมองโดยตรงหมายถึงการเรียก-addSubview:ใช้มุมมองของตัวควบคุมมุมมอง (เช่น[viewController.view addSubview:anotherViewController.view]) แทนที่จะผลักตัวควบคุมมุมมองใหม่ไปยังสแต็กของตัวควบคุมการนำทาง


1

ฉันคิดว่าการเพิ่มมุมมองย่อยไม่จำเป็นต้องหมายความว่ามุมมองจะปรากฏขึ้นดังนั้นจึงไม่มีการเรียกใช้เมธอดของคลาสโดยอัตโนมัติที่จะ


1

ฉันคิดว่าสิ่งที่พวกเขาหมายถึง "โดยตรง" คือการเชื่อมโยงสิ่งต่าง ๆ เช่นเดียวกับเทมเพลต xcode "แอปพลิเคชันการนำทาง" ซึ่งตั้งค่า UINavigationController เป็นมุมมองย่อยเดียวของ UIWindow ของแอปพลิเคชัน

การใช้เทมเพลตนั้นเป็นวิธีเดียวที่ฉันสามารถเรียกใช้เมธอด Will / Did / Appear / Disappear ที่เรียกบนวัตถุ ViewControllers เมื่อกด / ปรากฏตัวควบคุมเหล่านั้นใน UINavigationController ไม่มีวิธีแก้ปัญหาอื่นใดในคำตอบที่นี่ที่ใช้ได้ผลสำหรับฉันรวมถึงการนำไปใช้ใน RootController และส่งผ่านไปยัง NavigationController (ลูก) ฟังก์ชันเหล่านั้น (จะ / ไม่ / ปรากฏ / หายไป) ถูกเรียกเฉพาะใน RootController ของฉันเมื่อแสดง / ซ่อน VC ระดับบนสุด "การเข้าสู่ระบบ" และการนำทาง VC ของฉันไม่ใช่ VCs ย่อยในตัวควบคุมการนำทางดังนั้นฉันจึงไม่มีโอกาส "ส่งผ่าน" ไปยัง Nav VC

ฉันลงเอยด้วยการใช้ฟังก์ชันผู้ร่วมประชุมของ UINavigationController เพื่อค้นหาการเปลี่ยนเฉพาะที่ต้องการฟังก์ชันการติดตามผลในแอปของฉันและใช้งานได้ แต่ต้องทำงานอีกเล็กน้อยเพื่อให้ได้ทั้งฟังก์ชันที่หายไปและปรากฏขึ้น "จำลอง"

มันเป็นเรื่องของหลักการที่จะทำให้มันใช้งานได้หลังจากต่อสู้กับปัญหานี้เป็นเวลาหลายชั่วโมงในวันนี้ ข้อมูลโค้ดที่ใช้งานได้โดยใช้ RootController ที่กำหนดเองและ VC การนำทางเด็กจะได้รับการชื่นชมมาก


1

ในกรณีนี้ช่วยทุกคน ฉันมีปัญหาคล้าย ๆ กันที่ฉันViewWillAppearไม่ได้ยิงไฟล์UITableViewController. หลังจากเล่นไปเรื่อยๆ ฉันก็รู้ว่าปัญหาคือสิ่งUINavigationControllerที่ควบคุมของฉันUITableViewไม่ได้อยู่ในมุมมองรูท เมื่อแก้ไขแล้วตอนนี้ก็ใช้งานได้เหมือนแชมป์


คุณช่วยแบ่งปัน "วิธีการ" ที่คุณทำนั้นได้ไหม
Brabbeldas

1

ฉันเพิ่งมีปัญหานี้ด้วยตัวเองและฉันใช้เวลา 3 ชั่วโมงเต็ม (2 ที่ googling) ในการแก้ไข

สิ่งที่ช่วยได้คือเพียงแค่ลบแอปออกจากอุปกรณ์ / โปรแกรมจำลองล้างแล้วเรียกใช้อีกครั้งจำลองสะอาดและทำงานแล้วอีกครั้ง

หวังว่าจะช่วยได้


1
[self.navigationController setDelegate:self];

ตั้งค่าผู้รับมอบสิทธิ์เป็นตัวควบคุมมุมมองรูท


1

สำหรับ 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()
    }
}

}

ประการที่สามทำให้อินสแตนซ์ของ ForceUpdateOnViewAppear เป็นสมาชิกของคลาสที่เหมาะสมซึ่งมีสิทธิ์เข้าถึงตัวควบคุมการนำทางและมีอยู่ตราบเท่าที่มีตัวควบคุมการนำทางอยู่ อาจเป็นตัวอย่างเช่นตัวควบคุมมุมมองรูทของตัวควบคุมการนำทางหรือคลาสที่สร้างหรือนำเสนอ จากนั้นกำหนดอินสแตนซ์ของ ForceUpdateOnViewAppear ให้กับคุณสมบัติตัวแทนของตัวควบคุมการนำทางโดยเร็วที่สุด


0

ในกรณีของฉันปัญหาคือเกี่ยวกับภาพเคลื่อนไหวการเปลี่ยนที่กำหนดเอง เมื่อตั้งค่าmodalPresentationStyle = .custom viewWillAppearไม่ถูกเรียก

ในคลาสแอนิเมชั่นการเปลี่ยนแปลงที่กำหนดเองต้องการวิธีการโทร: beginAppearanceTransitionและendAppearanceTransition


0

ในกรณีของฉันนั่นเป็นเพียงข้อผิดพลาดแปลก ๆ ในโปรแกรมจำลอง iOS 12.1 หายไปหลังจากเปิดตัวบนอุปกรณ์จริง.


0

ฉันได้สร้างคลาสที่ช่วยแก้ปัญหานี้ เพียงแค่ตั้งค่าเป็นตัวแทนของตัวควบคุมการนำทางของคุณและใช้วิธีง่ายๆหนึ่งหรือสองวิธีในตัวควบคุมมุมมองของคุณซึ่งจะถูกเรียกเมื่อมุมมองกำลังจะแสดงหรือถูกแสดงผ่าน NavigationController

นี่คือ GIST ที่แสดงรหัส


0

ViewWillAppear เป็นวิธีการแทนที่ของคลาส UIViewController ดังนั้นการเพิ่มมุมมองย่อยจะไม่เรียก viewWillAppear แต่เมื่อคุณนำเสนอให้ผลักดันป๊อปแสดง setFront หรือ popToRootViewController จาก viewController จากนั้น viewWillAppear สำหรับ viewController ที่นำเสนอจะถูกเรียก


0

ปัญหาของฉันคือไม่ได้เรียก viewWillAppear เมื่อคลายจากการทำต่อ คำตอบคือการโทรไปที่ viewWillAppear (จริง) ในการคลายการทำต่อใน View Controller ที่คุณทำต่อกลับไป

@IBAction func คลาย (สำหรับคลายเส้น: UIStoryboardSegue, ViewController laterVC: Any) {

   viewWillAppear(true)
}

-2

ฉันไม่แน่ใจว่านี่เป็นปัญหาเดียวกับที่ฉันแก้ไข
ในบางครั้ง method จะไม่ทำงานด้วยวิธีปกติเช่น "[self methodOne]"

ลอง

- (void)viewWillAppear:(BOOL)animated
{
    [self performSelector:@selector(methodOne) 
           withObject:nil afterDelay:0];
}

ปัญหาviewWillAppearไม่ได้ถูกเรียกเลย
Vyachaslav Gerchicov

-3

คุณควรมี UIViewController 1 ตัวที่ใช้งานได้ตลอดเวลา มุมมองย่อยใด ๆ ที่คุณต้องการจัดการควรเป็นแบบนั้น - subVIEWS - เช่น UIView

ฉันใช้เทคนิคง่ายๆในการจัดการลำดับชั้นมุมมองของฉันและยังไม่พบปัญหาตั้งแต่ฉันเริ่มทำสิ่งต่างๆด้วยวิธีนี้ มี 2 ​​ประเด็นสำคัญ:

  • ควรใช้ UIViewController เพียงตัวเดียวเพื่อจัดการ "ค่าของหน้าจอ" ของแอปของคุณ
  • ใช้ UINavigationController เพื่อเปลี่ยนมุมมอง

"a screen's worth" หมายถึงอะไร จุดประสงค์ค่อนข้างคลุมเครือเล็กน้อย แต่โดยทั่วไปแล้วจะเป็นคุณลักษณะหรือส่วนของแอปของคุณ หากคุณมีหน้าจอสองสามหน้าที่มีภาพพื้นหลังเหมือนกัน แต่มีภาพซ้อนทับ / ป๊อปอัปต่างกัน ฯลฯ นั่นควรเป็นตัวควบคุมมุมมอง 1 ตัวและมุมมองเด็กหลายมุมมอง คุณไม่ควรพบว่าตัวเองทำงานกับคอนโทรลเลอร์ 2 มุมมอง โปรดทราบว่าคุณยังสามารถสร้างอินสแตนซ์ UIView ในตัวควบคุมมุมมองเดียวและเพิ่มเป็นมุมมองย่อยของตัวควบคุมมุมมองอื่นได้หากคุณต้องการให้พื้นที่บางส่วนของหน้าจอแสดงในตัวควบคุมหลายมุมมอง

สำหรับ UINavigationController - นี่คือเพื่อนที่ดีที่สุดของคุณ! ปิดแถบนำทางและระบุ NO สำหรับภาพเคลื่อนไหวและคุณมีวิธีที่ยอดเยี่ยมในการสลับหน้าจอตามต้องการ คุณสามารถพุชและตัวควบคุมมุมมองป๊อปได้หากอยู่ในลำดับชั้นหรือคุณสามารถเตรียมอาร์เรย์ของตัวควบคุมมุมมอง (รวมถึงอาร์เรย์ที่มี VC ตัวเดียว) และตั้งค่าให้เป็นสแต็กมุมมองโดยใช้ setViewControllers สิ่งนี้ช่วยให้คุณมีอิสระอย่างเต็มที่ในการเปลี่ยน VC ในขณะที่ได้รับประโยชน์ทั้งหมดจากการทำงานในรูปแบบที่คาดหวังของ Apple และทำให้เหตุการณ์ทั้งหมด ฯลฯ เริ่มทำงานได้อย่างถูกต้อง

นี่คือสิ่งที่ฉันทำทุกครั้งเมื่อเปิดแอป:

  • เริ่มจากแอพที่ใช้หน้าต่าง
  • เพิ่ม UINavigationController เป็น rootViewController ของหน้าต่าง
  • เพิ่มสิ่งที่ฉันต้องการให้ UIViewController ตัวแรกของฉันเป็น rootViewController ของตัวควบคุม nav

(หมายเหตุการเริ่มต้นจากหน้าต่างเป็นเพียงความชอบส่วนตัว - ฉันชอบสร้างสิ่งต่างๆด้วยตัวเองดังนั้นฉันจึงรู้ว่ามันถูกสร้างขึ้นอย่างไรควรทำงานได้ดีกับเทมเพลตตามมุมมอง)

เหตุการณ์ทั้งหมดเกิดขึ้นอย่างถูกต้องและโดยพื้นฐานแล้วชีวิตก็ดี จากนั้นคุณสามารถใช้เวลาทั้งหมดในการเขียนส่วนสำคัญของแอปของคุณและไม่ยุ่งเกี่ยวกับการพยายามแฮ็คลำดับชั้นด้วยตนเองให้เป็นรูปร่าง


ไม่มีอะไรผิดปกติกับการเปิดใช้งานคอนโทรลเลอร์หลายมุมมอง UIViewController มีวิธีการอนุญาตให้สร้างลำดับชั้น (เช่น [addChildViewController:])
Richard

1
ใช่ตอนนี้ ในปี 2554 ไม่เป็นเช่นนั้น คำตอบนั้นถูกต้องในเวลานั้นเป็นที่ยอมรับว่าไม่ใช่ตอนนี้
Nigel Flack
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.