要求 UISplitViewController 为详细视图控制器延迟加载多个视图控制器

发布于 2024-10-17 15:13:46 字数 3685 浏览 5 评论 0原文

呃,标题可能没说清楚。我已将其从 MultipleDetailView 中提取出来来自苹果的示例代码。每次用户从弹出窗口中的表中选择一行时,detailViewController 都会再次分配 FirstDetailViewController 和 SecondDetailViewController。我不想一遍又一遍地分配和初始化视图控制器,而是想将现有的、已经分配和初始化的视图控制器(如果存在)分配给选择行的detailViewController。我修改了分割视图模板而不是示例代码来实现我所需要的。程序中的代码:

这是 AppDelegate.h 文件:

@interface iPadHelloWorldAppDelegate : NSObject <UIApplicationDelegate> {

    UIWindow *window;

    UISplitViewController *splitViewController;

    MasterViewController *masterViewController;
    DetailViewController *detailViewController;
    SecondDetailViewController *secondDetailViewController;
}

这是 AppDelegate.m 文件:

 masterViewController = [[MasterViewController alloc] init];
 UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
 detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailView" bundle:nil];
 secondDetailViewController = [[SecondDetailViewController alloc] initWithNibName:@"SecondDetailView" bundle:nil];
 splitViewController = [[UISplitViewController alloc] init];
 splitViewController.viewControllers = [NSArray arrayWithObjects:navigationController, detailViewController, nil];
    splitViewController.delegate = detailViewController;
    // Add the split view controller's view to the window and display.
    [window addSubview:splitViewController.view];
    [window makeKeyAndVisible];

这是 MasterViewController.m:

- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSUInteger row = indexPath.row;
    [self.appDelegate.splitViewController viewWillDisappear:YES];
    self.tempArrays = [NSMutableArray arrayWithArray:self.appDelegate.splitViewController.viewControllers];
    [self.tempArrays removeLastObject];
    if (row == 0) {
        [self.tempArrays addObject:self.appDelegate.detailViewController];
        self.appDelegate.splitViewController.delegate = self.appDelegate.detailViewController;
    }
    if (row == 1) {
        [self.tempArrays addObject:self.appDelegate.secondDetailViewController];
        self.appDelegate.splitViewController.delegate = self.appDelegate.secondDetailViewController;
    }
    self.appDelegate.splitViewController.viewControllers = self.tempArrays;
    [self.appDelegate.splitViewController viewWillAppear:YES];
}

这是 DetailViewController.m:

#pragma mark -
#pragma mark Split view support

- (void)splitViewController: (UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController: (UIPopoverController*)pc {

    barButtonItem.title = @"Master List";
    [navigationBar.topItem setLeftBarButtonItem:barButtonItem animated:NO];
    self.popoverController = pc;
}

// Called when the view is shown again in the split view, invalidating the button and popover controller.
- (void)splitViewController: (UISplitViewController*)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {

    [navigationBar.topItem setLeftBarButtonItem:nil animated:NO];
    self.popoverController = nil;
}

我能够延迟加载视图控制器,但是当我点击弹出窗口的栏按钮并跳转到第二个视图控制器,第二个视图控制器不显示弹出窗口。当我跳回第一个详细视图控制器时,将显示弹出窗口。

基本上,这里是一个类似的问题。但那里的投递箱链接不起作用。

Well, might not be clear with the title. I have pulled this right out of the MultipleDetailView sample code from Apple. Every time the user selects a row from the table in the pop over, detailViewController is allocated the FirstDetailViewController and SecondDetailViewController again. Instead of allocating and initializing the view controller over and over, I want to assign the existing and already allocated and initialized view controller if existing to the detailViewController on the selection of the row. I have modified the Split View Template instead of the sample code to achieve what I need. Code from the program:

This is the AppDelegate.h file:

@interface iPadHelloWorldAppDelegate : NSObject <UIApplicationDelegate> {

    UIWindow *window;

    UISplitViewController *splitViewController;

    MasterViewController *masterViewController;
    DetailViewController *detailViewController;
    SecondDetailViewController *secondDetailViewController;
}

This is the AppDelegate.m file:

 masterViewController = [[MasterViewController alloc] init];
 UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
 detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailView" bundle:nil];
 secondDetailViewController = [[SecondDetailViewController alloc] initWithNibName:@"SecondDetailView" bundle:nil];
 splitViewController = [[UISplitViewController alloc] init];
 splitViewController.viewControllers = [NSArray arrayWithObjects:navigationController, detailViewController, nil];
    splitViewController.delegate = detailViewController;
    // Add the split view controller's view to the window and display.
    [window addSubview:splitViewController.view];
    [window makeKeyAndVisible];

This is the MasterViewController.m:

- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSUInteger row = indexPath.row;
    [self.appDelegate.splitViewController viewWillDisappear:YES];
    self.tempArrays = [NSMutableArray arrayWithArray:self.appDelegate.splitViewController.viewControllers];
    [self.tempArrays removeLastObject];
    if (row == 0) {
        [self.tempArrays addObject:self.appDelegate.detailViewController];
        self.appDelegate.splitViewController.delegate = self.appDelegate.detailViewController;
    }
    if (row == 1) {
        [self.tempArrays addObject:self.appDelegate.secondDetailViewController];
        self.appDelegate.splitViewController.delegate = self.appDelegate.secondDetailViewController;
    }
    self.appDelegate.splitViewController.viewControllers = self.tempArrays;
    [self.appDelegate.splitViewController viewWillAppear:YES];
}

This is the DetailViewController.m:

#pragma mark -
#pragma mark Split view support

- (void)splitViewController: (UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController: (UIPopoverController*)pc {

    barButtonItem.title = @"Master List";
    [navigationBar.topItem setLeftBarButtonItem:barButtonItem animated:NO];
    self.popoverController = pc;
}

// Called when the view is shown again in the split view, invalidating the button and popover controller.
- (void)splitViewController: (UISplitViewController*)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {

    [navigationBar.topItem setLeftBarButtonItem:nil animated:NO];
    self.popoverController = nil;
}

I am able to lazy load the view controllers, but when I tap the bar button for the popover and jump to the second view controller, the second view controller does not show the pop over. When I jump back to the first detail view controller, the popover is displayed.

Basically, here is a similar question. But the link to the drop box there doesn't work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

三寸金莲 2024-10-24 15:13:47

尝试在该对象的 viewDidLoad 中分配 viewController。给两个视图控制器一个标题并将它们放入一个数组中。如果需要,您可以将这些标题用于两个单元格文本标签。
在 didSelectRowAtIndexPath 中,您可以获得所选行

UIViewController <SubstitutableDetailViewController> *detailViewController = [theArray objectAtIndex:indexPath.row];

编辑的正确视图控制器:

@interface SomeClass : NSObject {
  NSArray *controllerArray;
}
@end
@implementation SomeClass

- (void) viewDidLoad {
  controllerArray = [[NSArray alloc] initWithObject://yourControllers//,nil];
  [super viewDidLoad]
}

- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section {

    // Two sections, one for each detail view controller.
    return 2;
}

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

  //Create Cell

  UIViewCOntroller *controller = [controllerArray objectAtIndex:indexPath.row];
  cell.textLabel.text = controller.title;

  return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  [detailViewController autorelease]; 
  detailViewController = [[controllerArray objectAtIndex:indexPath.row] retain];
}

@end

Try allocating the viewControllers in the viewDidLoad in this object. Give both viewcontrollers a title and put them in an array. These titles you can use for both cells textlabels if needed.
In the didSelectRowAtIndexPath you can get the correct viewcontroller for the selected row

UIViewController <SubstitutableDetailViewController> *detailViewController = [theArray objectAtIndex:indexPath.row];

Edit:

@interface SomeClass : NSObject {
  NSArray *controllerArray;
}
@end
@implementation SomeClass

- (void) viewDidLoad {
  controllerArray = [[NSArray alloc] initWithObject://yourControllers//,nil];
  [super viewDidLoad]
}

- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section {

    // Two sections, one for each detail view controller.
    return 2;
}

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

  //Create Cell

  UIViewCOntroller *controller = [controllerArray objectAtIndex:indexPath.row];
  cell.textLabel.text = controller.title;

  return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  [detailViewController autorelease]; 
  detailViewController = [[controllerArray objectAtIndex:indexPath.row] retain];
}

@end
忆伤 2024-10-24 15:13:47

无需创建详细视图控制器的新实例或更新分割视图控制器中的视图控制器。

试试这个。

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {

        UIApplication *application = [UIApplication sharedApplication];
        AppDelegate *appDelegate = (AppDelegate*) [application delegate];
        appDelegate.detailViewController.label.text = @"Detail view controller updated";

    }

PS:请拖动标签到详细信息进行测试。

It isn't necessary to create a new instance of the detail view controller or update the viewControllers in the split view controller.

Try this.

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {

        UIApplication *application = [UIApplication sharedApplication];
        AppDelegate *appDelegate = (AppDelegate*) [application delegate];
        appDelegate.detailViewController.label.text = @"Detail view controller updated";

    }

PS: Please, drag a label to the detail for testing.

偏闹i 2024-10-24 15:13:46

既然你让我开枪了——就这样吧。从我们的观点来看,SplitViewController 是相当有缺陷的。如果您不完全遵循 Apple 在示例代码中的做法,我们就会遇到很多问题。

首先,我建议您再次获取示例代码并从头开始,因为看起来您已经修改了很多。

至于你的问题:在你的委托和 MainWindow.xib 中,你设置了 SplitViewController 。最重要的是不要按照您的方式设置 viewControllers 数组。

我遇到了这样的问题:如果我覆盖 RootViewController,它会弄乱 SplitViewController 并产生像您遇到的那样的错误。

尝试仅设置一次 RootViewController(TableViewController),并且永远不要在 viewControllers 属性中覆盖它。不过,这对于 DetailViewController 来说似乎没问题。

其次,您的代码应该放在其他地方,而不是放在 RootViewController 中。这应该仅适用于 tableView 数据源和内容。

尝试一下并在这里反馈,我会尽快关注。

祝你好运。

编辑:添加代码 - 在 RootViewController 中执行此操作:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here. Create and push another view controller.

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {


DetailViewController *dvC = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];

// take the original view controller from the splitviewcontroller as root
// appDelegateiPad defined like this in my appdelegate:
// #define appDelegateiPad ((AppDelegate_iPad *)[[UIApplication sharedApplication] delegate]) 
NSArray *viewControllers = [[NSArray alloc] initWithObjects:[[appDelegateiPad.splitViewController viewControllers]objectAtIndex:0], dvC, nil];
        appDelegateiPad.splitViewController.viewControllers = viewControllers;
//careful with this, set it to whatever your delegate is in your case           
appDelegateiPad.splitViewController.delegate = dvC;
        [viewControllers release];  


//this is my version
//i have the popoverController property in my detailviewcontroller. this is where my splitviewcontroller delegate methods are. you need to set the popovercontroller property in the class where your splitviewcontroller delegate methos are
    dvC.popoverController = [[[appDelegateiPad.splitViewController viewControllers]objectAtIndex:1] popoverController];     

    } 
}

Since you have asked me to have shot - here it goes. The SplitViewController is rather buggy, from our opinion here. We have encountered many problems if you don't stick to exactly the way Apple does it in their sample code.

First of all, I would suggest you take the sample code again and start from scratch, since it seems you have modified a lot.

As for your problem: In your delegate and the MainWindow.xib you set up your SplitViewController. The most important thing is to not set up the viewControllers array the way you do it.

I encountered the problem that if I overwrite the RootViewController, it messes up the SplitViewController and produces bugs like the one you encounter.

Try setting up your RootViewController (the TableViewController) only once and never overwrite it in the viewControllers property. This seems to be OK for the DetailViewController, though.

Secondly, you code should be placed elsewhere, not in the RootViewController. This should be for the tableView datasource and content only.

Try this and feedback here, I'll follow asap.

Best of luck.

EDIT: code addition - do this in your RootViewController:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here. Create and push another view controller.

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {


DetailViewController *dvC = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];

// take the original view controller from the splitviewcontroller as root
// appDelegateiPad defined like this in my appdelegate:
// #define appDelegateiPad ((AppDelegate_iPad *)[[UIApplication sharedApplication] delegate]) 
NSArray *viewControllers = [[NSArray alloc] initWithObjects:[[appDelegateiPad.splitViewController viewControllers]objectAtIndex:0], dvC, nil];
        appDelegateiPad.splitViewController.viewControllers = viewControllers;
//careful with this, set it to whatever your delegate is in your case           
appDelegateiPad.splitViewController.delegate = dvC;
        [viewControllers release];  


//this is my version
//i have the popoverController property in my detailviewcontroller. this is where my splitviewcontroller delegate methods are. you need to set the popovercontroller property in the class where your splitviewcontroller delegate methos are
    dvC.popoverController = [[[appDelegateiPad.splitViewController viewControllers]objectAtIndex:1] popoverController];     

    } 
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文