ตรวจจับเมื่อกดปุ่ม 'ย้อนกลับ' บนแถบนำทาง


135

ฉันจำเป็นต้องดำเนินการบางอย่างเมื่อกดปุ่มย้อนกลับ (กลับไปที่หน้าจอก่อนหน้ากลับไปที่มุมมองผู้ปกครอง) บน Navbar

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




คำตอบ:


317

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

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

ดู"การติดตั้งตัวควบคุมมุมมองคอนเทนเนอร์"สำหรับรายละเอียดเพิ่มเติม


ตั้งแต่ iOS 5 ฉันพบว่าวิธีที่ง่ายที่สุดในการจัดการกับสถานการณ์นี้คือการใช้วิธีการใหม่- (BOOL)isMovingFromParentViewController:

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

  if (self.isMovingFromParentViewController) {
    // Do your stuff here
  }
}

- (BOOL)isMovingFromParentViewController เหมาะสมเมื่อคุณกำลังผลักและเปิดตัวควบคุมในสแตกการนำทาง

อย่างไรก็ตามหากคุณกำลังนำเสนอตัวควบคุมมุมมองโมดอลคุณควรใช้- (BOOL)isBeingDismissedแทน:

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

  if (self.isBeingDismissed) {
    // Do your stuff here
  }
}

ดังที่ระบุไว้ในคำถามนี้คุณสามารถรวมคุณสมบัติทั้งสอง:

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

  if (self.isMovingFromParentViewController || self.isBeingDismissed) {
    // Do your stuff here
  }
}

โซลูชันอื่น ๆ ขึ้นอยู่กับการมีอยู่ของไฟล์UINavigationBar. แทนที่จะชอบแนวทางของฉันมากกว่าเพราะมันแยกงานที่จำเป็นในการดำเนินการออกจากการกระทำที่เรียกเหตุการณ์นั่นคือการกดปุ่มย้อนกลับ


ฉันชอบที่คุณตอบ แต่ทำไมคุณถึงใช้ 'self.isBeingDismissed'? ในกรณีของฉันข้อความใน 'self.isBeingDismissed' จะไม่ถูกนำไปใช้
รุจวิจิตรโกเตชะ

3
self.isMovingFromParentViewControllerมีค่า TRUE เมื่อฉันเปิดสแต็กการนำทางโดยใช้โปรแกรมpopToRootViewControllerAnimated- โดยไม่ต้องแตะปุ่มย้อนกลับ ฉันควรลงคะแนนคำตอบของคุณหรือไม่? (เรื่องบอกว่ากดปุ่ม "ย้อนกลับ" บนแถบนำทาง ")
kas-kad

2
คำตอบที่ยอดเยี่ยมขอบคุณมาก ใน Swift ฉันใช้:override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) if isMovingFromParentViewController(){ println("back button pressed") } }
Camillo

2
คุณควรทำสิ่งนี้ภายในเท่านั้น-viewDidDisappear:เนื่องจากเป็นไปได้ที่คุณจะได้รับ-viewWillDisappear:โดยไม่ต้อง-viewDidDisappear:(เช่นเมื่อคุณเริ่มปัดเพื่อปิดรายการตัวควบคุมการนำทางแล้วยกเลิกการปัดนั้น
Heath Borders

3
ดูเหมือนจะไม่ใช่วิธีแก้ปัญหาที่น่าเชื่อถืออีกต่อไป ทำงานในเวลาที่ฉันใช้สิ่งนี้ครั้งแรก (มันคือ iOS 10) แต่ตอนนี้ฉันบังเอิญพบว่ามันหยุดทำงานอย่างสงบ (iOS 11) ต้องเปลี่ยนไปใช้โซลูชัน "willMove (toParentViewController)"
Vitalii

101

ในขณะที่viewWillAppear()และviewDidDisappear() ถูกเรียกเมื่อแตะปุ่มย้อนกลับปุ่มเหล่านี้จะถูกเรียกในเวลาอื่นด้วย ดูท้ายคำตอบสำหรับข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนั้น

ใช้ UIViewController.parent

การตรวจจับปุ่มย้อนกลับทำได้ดีกว่าเมื่อ VC ถูกลบออกจากพาเรนต์ (NavigationController) ด้วยความช่วยเหลือของwillMoveToParentViewController(_:)ORdidMoveToParentViewController()

หากพาเรนต์เป็นศูนย์ตัวควบคุมมุมมองจะถูกดึงออกจากสแต็กการนำทางและปิด หากพาเรนต์ไม่ใช่ศูนย์ระบบจะเพิ่มลงในสแต็กและนำเสนอ

// Objective-C
-(void)willMoveToParentViewController:(UIViewController *)parent {
     [super willMoveToParentViewController:parent];
    if (!parent){
       // The back button was pressed or interactive gesture used
    }
}


// Swift
override func willMove(toParent parent: UIViewController?) {
    super.willMove(toParent: parent)
    if parent == nil {
        // The back button was pressed or interactive gesture used
    }
}

สลับออกwillMoveสำหรับdidMoveและตรวจสอบ self.parent จะทำผลงานหลังจากควบคุมดูจะถูกไล่ออก

กำลังหยุดการปิด

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

var backButton : UIBarButtonItem!

override func viewDidLoad() {
    super.viewDidLoad()

     // Disable the swipe to make sure you get your chance to save
     self.navigationController?.interactivePopGestureRecognizer.enabled = false

     // Replace the default back button
    self.navigationItem.setHidesBackButton(true, animated: false)
    self.backButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.Plain, target: self, action: "goBack")
    self.navigationItem.leftBarButtonItem = backButton
}

// Then handle the button selection
func goBack() {
    // Here we just remove the back button, you could also disabled it or better yet show an activityIndicator
    self.navigationItem.leftBarButtonItem = nil
    someData.saveInBackground { (success, error) -> Void in
        if success {
            self.navigationController?.popViewControllerAnimated(true)
            // Don't forget to re-enable the interactive gesture
            self.navigationController?.interactivePopGestureRecognizer.enabled = true
        }
        else {
            self.navigationItem.leftBarButtonItem = self.backButton
            // Handle the error
        }
    }
}


ข้อมูลเพิ่มเติมเกี่ยวกับการดูจะ / ไม่ปรากฏ

หากคุณไม่ได้รับviewWillAppear viewDidDisappearปัญหามาดูตัวอย่างกัน สมมติว่าคุณมีตัวควบคุมมุมมองสามตัว:

  1. ListVC: มุมมองตารางของสิ่งต่างๆ
  2. DetailVC: รายละเอียดเกี่ยวกับสิ่งของ
  3. SettingsVC: ตัวเลือกบางอย่างสำหรับสิ่งของ

ให้ติดตามการโทรในdetailVCขณะที่คุณไปจากlistVCไปsettingsVCและกลับไปlistVC

List> Detail (push detailVC) Detail.viewDidAppear<- ปรากฏ
รายละเอียด> การตั้งค่า (push settingsVC) Detail.viewDidDisappear<- หายไป

และเมื่อเราย้อนกลับไป ...
การตั้งค่า> รายละเอียด (pop settingsVC) Detail.viewDidAppear<- ปรากฏ
รายละเอียด> รายการ (pop detailVC) Detail.viewDidDisappear<- หายไป

สังเกตว่าviewDidDisappearมีการเรียกหลายครั้งไม่เพียง แต่เมื่อย้อนกลับเท่านั้น แต่ยังรวมถึงเมื่อไปข้างหน้าด้วย สำหรับการดำเนินการที่รวดเร็วซึ่งอาจเป็นที่ต้องการ แต่สำหรับการดำเนินการที่ซับซ้อนมากขึ้นเช่นการเรียกเครือข่ายเพื่อบันทึกอาจไม่ได้


โปรดทราบว่าผู้ใช้didMoveToParantViewController:จะทำงานเมื่อมองไม่เห็นมุมมองอีกต่อไป มีประโยชน์สำหรับ iOS7 ด้วย InteractiveGesutre
WCByrne

didMoveToParentViewController * มีการพิมพ์ผิด
thewormsterror

อย่าลืมโทรหา [super willMoveToParentViewController: parent]!
ScottyB

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

1
สิ่งนี้จะถูกเรียกเมื่อใช้งานโดยใช้โปรแกรม_ = self.navigationController?.popViewController(animated: true)ดังนั้นจึงไม่ได้เรียกแค่การกดปุ่มย้อนกลับ ฉันกำลังมองหาสำหรับการโทรที่ทำงานเฉพาะเมื่อกลับถูกกด
Ethan Allen

16

วิธีแรก

- (void)didMoveToParentViewController:(UIViewController *)parent
{
    if (![parent isEqual:self.parentViewController]) {
         NSLog(@"Back pressed");
    }
}

วิธีที่สอง

-(void) viewWillDisappear:(BOOL)animated {
    if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) {
       // back button was pressed.  We know this is true because self is no longer
       // in the navigation stack.  
    }
    [super viewWillDisappear:animated];
}

1
วิธีที่สองเป็นวิธีเดียวที่ใช้ได้ผลสำหรับฉัน วิธีแรกถูกเรียกตามมุมมองของฉันที่นำเสนอซึ่งไม่เป็นที่ยอมรับสำหรับกรณีการใช้งานของฉัน
marcshilling

11

ผู้ที่อ้างว่าไม่ได้ผลถือว่าเข้าใจผิด:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    if self.isMovingFromParent {
        print("we are being popped")
    }
}

ใช้งานได้ดี แล้วอะไรคือสาเหตุที่ทำให้เกิดตำนานที่แพร่หลายอย่างนั้น?

ปัญหาน่าจะเกิดจากการดำเนินการที่ไม่ถูกต้องของที่แตกต่างกันวิธีการคือว่าการดำเนินการลืมที่จะโทรwillMove(toParent:)super

หากคุณใช้งานwillMove(toParent:)โดยไม่ต้องโทรsuperก็self.isMovingFromParentจะเป็นfalseและการใช้งานviewWillDisappearจะล้มเหลว มันไม่ได้ล้มเหลว คุณทำลายมัน

หมายเหตุ:ปัญหาที่แท้จริงคือตัวควบคุมมุมมองที่สองตรวจพบว่าตัวควบคุมมุมมองแรกถูกงัด โปรดดูการอภิปรายทั่วไปเพิ่มเติมที่นี่: Unified UIViewController "กลายเป็นส่วนหน้า" การตรวจจับ?

แก้ไขความคิดเห็นที่แสดงให้เห็นว่านี้ควรจะเป็นมากกว่าviewDidDisappearviewWillDisappear


รหัสนี้จะถูกเรียกใช้งานเมื่อแตะปุ่มย้อนกลับ แต่จะถูกเรียกใช้งานเช่นกันหากมีการเปิด VC โดยใช้โปรแกรม
biomiker

1
@biomiker แน่นอน แต่นั่นก็เป็นความจริงในแนวทางอื่น ๆ Popping กำลังโผล่ คำถามคือจะตรวจจับป๊อปได้อย่างไรเมื่อคุณไม่ได้ป๊อปแบบเป็นโปรแกรม หากคุณป๊อปโดยใช้โปรแกรมคุณรู้อยู่แล้วว่าคุณกำลัง popping ดังนั้นจึงไม่มีอะไรให้ตรวจพบ
แมตต์

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

1
น่าเสียดายที่สิ่งนี้ส่งกลับมาtrueสำหรับท่าทางป๊อปแบบโต้ตอบ - จากขอบด้านซ้ายของตัวควบคุมมุมมอง - แม้ว่าการปัดจะไม่ได้เปิดเต็มที่ก็ตาม ดังนั้นแทนที่จะเช็คอินwillDisappearให้ทำในdidDisappearผลงาน
badhanganesh

1
@badhanganesh ขอบคุณคำตอบที่แก้ไขเพื่อรวมข้อมูลนั้น
แมตต์

9

ฉันเล่น (หรือต่อสู้) กับปัญหานี้มาสองวันแล้ว IMO แนวทางที่ดีที่สุดคือการสร้างคลาสส่วนขยายและโปรโตคอลเช่นนี้:

@protocol UINavigationControllerBackButtonDelegate <NSObject>
/**
 * Indicates that the back button was pressed.
 * If this message is implemented the pop logic must be manually handled.
 */
- (void)backButtonPressed;
@end

@interface UINavigationController(BackButtonHandler)
@end

@implementation UINavigationController(BackButtonHandler)
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item
{
    UIViewController *topViewController = self.topViewController;
    BOOL wasBackButtonClicked = topViewController.navigationItem == item;
    SEL backButtonPressedSel = @selector(backButtonPressed);
    if (wasBackButtonClicked && [topViewController respondsToSelector:backButtonPressedSel]) {
        [topViewController performSelector:backButtonPressedSel];
        return NO;
    }
    else {
        [self popViewControllerAnimated:YES];
        return YES;
    }
}
@end

วิธีนี้ใช้ได้ผลเพราะUINavigationControllerจะได้รับสายเรียกเข้าnavigationBar:shouldPopItem:ทุกครั้งที่มีการเปิดตัวควบคุมมุมมอง เราตรวจพบว่ามีการกดย้อนกลับหรือไม่ (ปุ่มอื่น ๆ ) สิ่งเดียวที่คุณต้องทำคือใช้โปรโตคอลในตัวควบคุมมุมมองที่กดย้อนกลับ

อย่าลืมเปิดตัวควบคุมมุมมองด้านในด้วยตนเองbackButtonPressedSelหากทุกอย่างเรียบร้อย

หากคุณมีคลาสย่อยUINavigationViewControllerและนำไปใช้navigationBar:shouldPopItem:แล้วไม่ต้องกังวลสิ่งนี้จะไม่รบกวน

คุณอาจสนใจที่จะปิดการใช้งานท่าทางย้อนกลับ

if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
    self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}

1
คำตอบนี้เกือบจะสมบูรณ์สำหรับฉันยกเว้นว่าฉันพบว่าตัวควบคุมวิว 2 ตัวมักจะโผล่ขึ้นมา การส่งคืน YES ทำให้วิธีการโทรเรียกป๊อปดังนั้นการเรียกป๊อปด้วยหมายความว่าตัวควบคุมวิว 2 ตัวจะถูกเปิดขึ้น ดูคำตอบนี้สำหรับคำถามอื่นสำหรับ deets เพิ่มเติม (คำตอบที่ดีมากที่สมควรได้รับคะแนนโหวตมากขึ้น): stackoverflow.com/a/26084150/978083
Jason Ridge

จุดดีคำอธิบายของฉันไม่ชัดเจนเกี่ยวกับข้อเท็จจริงนั้น "อย่าลืมเปิดตัวควบคุมมุมมองด้วยตนเองหากทุกอย่างเรียบร้อย" จะใช้เฉพาะในกรณีที่ส่งคืน "NO" มิฉะนั้นโฟลว์จะเป็นป๊อปปกติ
7ynk3r

1
สำหรับสาขา "else" จะดีกว่าที่จะเรียกการใช้งานขั้นสูงหากคุณไม่ต้องการจัดการกับป๊อปด้วยตัวเองและปล่อยให้มันส่งคืนสิ่งที่คิดว่าถูกต้องซึ่งส่วนใหญ่จะเป็นใช่ แต่ก็ดูแลป๊อปด้วยตัวมันเองและทำให้บั้งเคลื่อนไหวอย่างเหมาะสม .
pronebird

9

สิ่งนี้ใช้ได้กับฉันใน iOS 9.3.x พร้อม Swift:

override func didMoveToParentViewController(parent: UIViewController?) {
    super.didMoveToParentViewController(parent)

    if parent == self.navigationController?.parentViewController {
        print("Back tapped")
    }
}

ไม่เหมือนกับโซลูชันอื่น ๆ ที่นี่ดูเหมือนว่าจะไม่เกิดขึ้นโดยไม่คาดคิด


จะดีกว่าที่จะใช้ willMove แทน
Eugene Gordin

4

สำหรับบันทึกฉันคิดว่านี่เป็นสิ่งที่เขากำลังมองหามากกว่า ...

    UIBarButtonItem *l_backButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRewind target:self action:@selector(backToRootView:)];

    self.navigationItem.leftBarButtonItem = l_backButton;


    - (void) backToRootView:(id)sender {

        // Perform some custom code

        [self.navigationController popToRootViewControllerAnimated:YES];
    }

1
ขอบคุณ Paul วิธีนี้ค่อนข้างง่าย น่าเสียดายที่ไอคอนแตกต่างกัน นี่คือไอคอน "ย้อนกลับ" ไม่ใช่ไอคอนย้อนกลับ อาจมีวิธีใช้ไอคอนด้านหลัง ...
Ferran Maylinch

3

คุณสามารถใช้การโทรกลับของปุ่มย้อนกลับได้ดังนี้:

- (BOOL) navigationShouldPopOnBackButton
{
    [self backAction];
    return NO;
}

- (void) backAction {
    // your code goes here
    // show confirmation alert, for example
    // ...
}

สำหรับเวอร์ชันที่รวดเร็วคุณสามารถทำสิ่งต่างๆเช่นในขอบเขตทั่วโลก

extension UIViewController {
     @objc func navigationShouldPopOnBackButton() -> Bool {
     return true
    }
}

extension UINavigationController: UINavigationBarDelegate {
     public func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
          return self.topViewController?.navigationShouldPopOnBackButton() ?? true
    }
}

ด้านล่างคุณวางไว้ในตัวควบคุมมุมมองที่คุณต้องการควบคุมการทำงานของปุ่มย้อนกลับ:

override func navigationShouldPopOnBackButton() -> Bool {
    self.backAction()//Your action you want to perform.

    return true
}

1
ไม่รู้ทำไมคนโหวตลง ดูเหมือนจะเป็นคำตอบที่ดีที่สุด
Avinash

@Avinash navigationShouldPopOnBackButtonมาจากไหน? ไม่ใช่ส่วนหนึ่งของ API สาธารณะ
elitalon

@elitalon ขออภัยนี่เป็นคำตอบครึ่งหนึ่ง ฉันคิดว่าบริบทที่เหลืออยู่มีปัญหา อย่างไรก็ตามได้อัปเดตคำตอบตอนนี้
Avinash

2

ดังที่purrrminatorกล่าวไว้ว่าคำตอบของelitalonไม่ถูกต้องอย่างสมบูรณ์เนื่องจากyour stuffจะถูกดำเนินการแม้ว่าจะเปิดตัวควบคุมโดยใช้โปรแกรม

วิธีแก้ปัญหาที่ฉันพบจนถึงตอนนี้ไม่ค่อยดีนัก แต่ก็ใช้ได้ผลสำหรับฉัน นอกจากสิ่งที่elitalonกล่าวไปแล้วฉันยังตรวจสอบด้วยว่าฉันกำลังใช้โปรแกรมหรือไม่:

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

  if ((self.isMovingFromParentViewController || self.isBeingDismissed)
      && !self.isPoppingProgrammatically) {
    // Do your stuff here
  }
}

คุณต้องเพิ่มคุณสมบัตินั้นลงในคอนโทรลเลอร์ของคุณและตั้งค่าเป็นใช่ก่อนที่จะเปิดโดยใช้โปรแกรม:

self.isPoppingProgrammatically = YES;
[self.navigationController popViewControllerAnimated:YES];

ขอบคุณสำหรับความช่วยเหลือของคุณ!


2

วิธีที่ดีที่สุดคือใช้เมธอดผู้แทน UINavigationController

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated

เมื่อใช้สิ่งนี้คุณจะสามารถทราบได้ว่าคอนโทรลเลอร์ใดแสดง UINavigationController

if ([viewController isKindOfClass:[HomeController class]]) {
    NSLog(@"Show home controller");
}

ควรทำเครื่องหมายว่าเป็นคำตอบที่ถูกต้อง! อาจต้องการเพิ่มอีกหนึ่งบรรทัดเพื่อเตือนคน -> self.navigationController.delegate = self;
Mike Critchley

2

ฉันได้แก้ปัญหานี้โดยการเพิ่ม UIControl ไปที่ navigationBar ทางด้านซ้าย

UIControl *leftBarItemControl = [[UIControl alloc] initWithFrame:CGRectMake(0, 0, 90, 44)];
[leftBarItemControl addTarget:self action:@selector(onLeftItemClick:) forControlEvents:UIControlEventTouchUpInside];
self.leftItemControl = leftBarItemControl;
[self.navigationController.navigationBar addSubview:leftBarItemControl];
[self.navigationController.navigationBar bringSubviewToFront:leftBarItemControl];

และคุณต้องอย่าลืมลบเมื่อมุมมองหายไป:

- (void) viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    if (self.leftItemControl) {
        [self.leftItemControl removeFromSuperview];
    }    
}

นั่นคือทั้งหมด!



1

ดังที่ Coli88 กล่าวไว้คุณควรตรวจสอบโปรโตคอล UINavigationBarDelegate

โดยทั่วไปแล้วคุณยังสามารถใช้- (void)viewWillDisapear:(BOOL)animatedเพื่อทำงานแบบกำหนดเองเมื่อมุมมองที่เก็บรักษาไว้โดยตัวควบคุมมุมมองที่มองเห็นได้ในปัจจุบันกำลังจะหายไป น่าเสียดายที่สิ่งนี้จะครอบคลุมถึงการผลักดันและกรณีป๊อป



1

คำตอบของ7ynk3rนั้นใกล้เคียงกับสิ่งที่ฉันใช้ในตอนท้าย แต่มันต้องมีการปรับแต่ง:

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item {

    UIViewController *topViewController = self.topViewController;
    BOOL wasBackButtonClicked = topViewController.navigationItem == item;

    if (wasBackButtonClicked) {
        if ([topViewController respondsToSelector:@selector(navBackButtonPressed)]) {
            // if user did press back on the view controller where you handle the navBackButtonPressed
            [topViewController performSelector:@selector(navBackButtonPressed)];
            return NO;
        } else {
            // if user did press back but you are not on the view controller that can handle the navBackButtonPressed
            [self popViewControllerAnimated:YES];
            return YES;
        }
    } else {
        // when you call popViewController programmatically you do not want to pop it twice
        return YES;
    }
}

0

self.navigationController.isMovingFromParentViewController ไม่ทำงานอีกต่อไปบน iOS8 และ 9 ฉันใช้:

-(void) viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    if (self.navigationController.topViewController != self)
    {
        // Is Popping
    }
}

-1

(SWIFT)

ทางออกสุดท้ายที่พบ .. วิธีที่เรากำลังมองหาคือ "willShowViewController" ซึ่งเป็นวิธีการมอบหมายของ UINavigationController

//IMPORT UINavigationControllerDelegate !!
class PushedController: UIViewController, UINavigationControllerDelegate {

    override func viewDidLoad() {
        //set delegate to current class (self)
        navigationController?.delegate = self
    }

    func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
        //MyViewController shoud be the name of your parent Class
        if var myViewController = viewController as? MyViewController {
            //YOUR STUFF
        }
    }
}

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