iPhone: แสดง Modal UITableViewController พร้อมแถบนำทาง


87

ฉันกำลังแสดงมุมมองแบบโมดอลซึ่งเป็นUITableViewControllerคลาส ด้วยเหตุผลบางประการมันจะไม่แสดงแถบนำทางเมื่อฉันแสดง นี่คือรหัสของฉัน:

SettingsCreateAccount *detailViewController = [[SettingsCreateAccount alloc] initWithStyle:UITableViewStyleGrouped];
    detailViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    detailViewController.navigationController.navigationBarHidden = NO;
    [self.navigationController presentModalViewController:detailViewController animated:YES];
    detailViewController = nil;
    [detailViewController release];

ฉันคิดว่ามันแสดงโดยปริยาย? ถ้าช่วยได้ฉันกำลังเรียกสิ่งนี้จากคลาสอื่นที่UITableViewControllerจัดการโดยไฟล์UINavigationController. ไอเดีย?

คำตอบ:


146

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

หากคุณต้องการนำเสนอตัวควบคุมมุมมองแบบโมดอลที่มีฟังก์ชันการนำทางคุณต้องนำเสนอตัวควบคุมการนำทางแบบโมดอลที่มีตัวควบคุมมุมมองรายละเอียดของคุณแทนดังนี้:

SettingsCreateAccount *detailViewController = [[SettingsCreateAccount alloc] initWithStyle:UITableViewStyleGrouped];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
[detailViewController release];

navController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:navController animated:YES];
[navController release];

ตัวควบคุมโมดอลของคุณจะจัดการสแต็กการนำทางของตัวเอง


ขอบคุณฉันซาบซึ้งกับคำอธิบายดังนั้นฉันจึงรู้ว่าฉันทำอะไรผิด
Nic Hubbard

1
หากคุณใช้สตอรีบอร์ดจะไม่มีการเข้ารหัสใด ๆ ที่เกี่ยวข้องเลยในการทำสิ่งนี้ให้สำเร็จ ทางออกที่ดี!
Jelle

36

นี่คือวิธีหนึ่งที่จะแสดงแถบนำทางสำหรับผู้ที่ใช้สตอรี่บอร์ด, แนะนำโดยการสอนของ Apple ในสตอรี่บอร์ด

เนื่องจากตัวควบคุมมุมมองโมดอลไม่ได้รับการเพิ่มลงในสแต็กการนำทางจึงไม่ได้รับแถบการนำทางจากตัวควบคุมการนำทางของตัวควบคุมมุมมองตาราง ในการกำหนดแถบนำทางให้กับตัวควบคุมมุมมองเมื่อนำเสนอแบบโมดูลให้ฝังไว้ในตัวควบคุมการนำทางของตัวเอง

  1. ในมุมมองเค้าร่างให้เลือก View Controller
  2. เมื่อเลือกตัวควบคุมมุมมองให้เลือกตัวแก้ไข> ฝังใน> ตัวควบคุมการนำทาง

ตรวจสอบให้แน่ใจว่าคุณได้เพิ่ม modal segue ลงใน Navigation Controller ไม่ใช่ TableViewController
bickster

ในสถานการณ์ของหน้าแก้ไขโปรไฟล์ผู้ใช้ของ Twitter นี่คือ UITableViewController ที่นำเสนอแบบโมดูลาร์และมีปุ่ม DONE และ CANCEL ที่ด้านบน คำตอบนี้ไม่สมเหตุสมผลในสถานการณ์นั้นเนื่องจากไม่มีการนำทางเกิดขึ้น
William Entriken

17

บน iOS 7 และคุณต้องการเพียงแค่แถบนำทางบนตัวควบคุมมุมมองโมดอลเพื่อแสดงชื่อเรื่องและปุ่มบางปุ่ม ลองใช้เวทมนตร์นี้ใน UITableViewController ของคุณ:

// in the .h
@property (strong) UINavigationBar* navigationBar;

//in the .m
- (void)viewDidLoad {
    [super viewDidLoad];

    self.navigationItem.title = @"Awesome";
    self.navigationBar = [[UINavigationBar alloc] initWithFrame:CGRectZero];
    [self.view addSubview:_navigationBar];
    [self.navigationBar pushNavigationItem:self.navigationItem animated:NO];
}

-(void)layoutNavigationBar{
    self.navigationBar.frame = CGRectMake(0, self.tableView.contentOffset.y, self.tableView.frame.size.width, self.topLayoutGuide.length + 44);
    self.tableView.contentInset = UIEdgeInsetsMake(self.navigationBar.frame.size.height, 0, 0, 0);
}

-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
    //no need to call super
    [self layoutNavigationBar];
}

-(void)viewDidLayoutSubviews{
    [super viewDidLayoutSubviews];
    [self layoutNavigationBar];
}

ตะเข็บเป็นวิธีที่ยอดเยี่ยมในการทำสิ่งต่างๆ แต่เมื่อฉันลองใช้ Static UITableViewController ฉันไม่สามารถเลื่อนมุมมองตารางได้อีกต่อไป ทำไม?
Thomas Besnehard

2
ทุกวันนี้คุณควรฝังไว้ในตัวควบคุมการนำทางจะดีกว่า
malhal

นั่นเป็นทางออกที่ดี แต่ปัญหาเล็ก ๆ อย่างหนึ่งก็คือเมื่อคุณเลื่อนชื่อส่วนหัวของเซลล์ที่แสดงที่ด้านบนของแถบนำทาง
อาลี

ฉันแก้ไขได้โดยการเพิ่ม[self.view bringSubviewToFront:self.navigationBar];ที่ส่วนท้ายของ-(void)layoutNavigationBar.
อาลี

7

ฉันต้องการแบ่งปันวิธีการแก้ปัญหาที่ยอมรับในโครงการที่มีสตอรีบอร์ด:

วิธีง่ายๆคือใส่สตอรี่บอร์ดเปล่าตัวควบคุมการนำทางก่อน VC ซึ่งจะนำเสนอแบบโมฆะดังนั้นความสัมพันธ์จึงมีลักษณะดังนี้:

(Presenter VC) -> นำเสนอแบบโมดูล -> (ตัวควบคุมการนำทางที่มีตัวควบคุมที่จะนำเสนอเป็นรูท)

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

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

#import "ModalPresentationWithNavigationBarSegue.h"

@implementation ModalPresentationWithNavigationBarSegue

- (void)perform {
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:self.destinationViewController];

    [self.sourceViewController presentViewController:navigationController animated:YES completion:nil];
}
@end

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

Presenter VC -> Presentee VC

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


5

หากคุณต้องการเพียงแค่NavigationBarคุณสามารถเพิ่มอินสแตนซ์UINavigationBarและกำหนด BarItems ให้กับมันได้


ขึ้นอยู่กับ ViewController: ฉันคิดว่าคุณไม่สามารถเพิ่ม UINavigationBar ไปยัง UITableViewController ได้ไหม
Tobias

ใน IB ไปที่ Editor -> Embed in Navigation Controller และคุณจะมีแถบนำทาง ลากและเพิ่ม BarButtonItems ไปที่
AmitaiB

5

ฉันแค่อยากจะเพิ่มบางอย่างในสิ่งที่ @Scott พูด คำตอบของเขาเป็นวิธีที่ง่ายที่สุดและได้รับการยอมรับมากที่สุดในตอนนี้ด้วย Storyboards, iOS 7 และ 8 ... (และเร็ว ๆ นี้ 9)

การเพิ่มตัวควบคุมมุมมองลงในสตอรี่บอร์ดอย่างแน่นอนและการฝังตามที่อธิบายโดย @Scott เป็นวิธีที่ถูกต้อง

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

สิ่งหนึ่งที่ฉันต้องการที่ขาดหายไปคือกรณีของ @ Scott คือเมื่อคุณต้องการส่งต่อข้อมูลบางอย่างไปยังตัวควบคุมมุมมองที่นำเสนอแบบโมดูลาร์ซึ่งฝังอยู่ในตัวควบคุมการนำทาง

หากคุณคว้า segue.destinationViewController มันจะเป็น UINavigationController ไม่ใช่คอนโทรลเลอร์ที่คุณฝังไว้ใน UINavigationController

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

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"presentMyModalViewController"]) {
        // This could be collapsed, but it's a little easier to see
        // what's going on written out this way.

        // First get the destination view controller, which will be a UINavigationController
        UINavigationController *nvc = (UINavigationController *)segue.destinationViewController;

        // To get the view controller we're interested in, grab the navigation controller's "topViewController" property
        MyModalViewController *vc = (EmailReceiptViewController *)[nvc topViewController];

        // Now that we have the reference to our view controller, we can set its properties here:
        vc.myAwesomeProperty = @"awesome!";
    }
}

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

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