【问题标题】:iPhone SDK: Switching to one view then back to previous view errorsiPhone SDK:切换到一个视图然后返回到前一个视图错误
【发布时间】:2010-05-06 03:36:20
【问题描述】:

我有一个 UITabBarConroller,用于在 3 个不同的视图之间切换。这一切都完美无缺。在我的一个选项卡上,我添加了一个名为“添加”的按钮,为此添加了一个出口,以及一个如下所示的 IBAction 方法:

// Method used to load up view where we can add a new ride
- (IBAction)showAddNewRideView {    

    MyRidesViewController *controller = [[MyRidesViewController alloc] initWithNibName:@"AddNewRide" bundle:nil];
    controller.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    [self presentModalViewController:controller animated:YES];
    [controller release];

}//end showAddNewRideView

这目前工作正常,并加载了我的 AddNewRide nib 文件。但是,一旦该视图加载,我有一个取消按钮,单击该按钮时,我想返回到前一个视图。所以,我想我会做与上述相反的事情,使用以下方法来加载我以前的笔尖:

- (IBAction)cancelAddingNewRide {
    MyRidesViewController *controller = [[MyRidesViewController alloc] initWithNibName:@"MainWindow" bundle:nil];
    controller.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    [self presentModalViewController:controller animated:YES];
    [controller release];

}//end cancelAddingNewRide

但是,尝试加载 MainWindow nib,程序崩溃,我收到以下错误:

2010-05-05 20:24:37.211 Ride[6032:207] *** -[MyRidesViewController cancelAddingNewRide]: unrecognized selector sent to instance 0x501e450
2010-05-05 20:24:37.213 Ride[6032:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[MyRidesViewController cancelAddingNewRide]: unrecognized selector sent to instance 0x501e450'

所以,我有点不明白为什么它会以一种方式起作用,而另一种则不起作用。

【问题讨论】:

    标签: iphone objective-c views


    【解决方案1】:

    首先,我想解决部分错误:将您的视图视为堆栈。当您“推送”一个模态控制器时,您就是将该视图添加到堆栈中。旧的景色还在下面。因此,您需要“弹出”模式视图以返回旧视图。如果你推送一个新视图,现在堆栈上有 3 个视图都占用了内存,而你实际上只需要一个。

    所以,在 cancelAddingNewRide 里面试试:

    [super dismissModalViewControllerAnimated:true];
    

    您可能还有其他导致崩溃的问题,但这通常应该可以正常工作。

    【讨论】:

    • 这是真的,但不是推荐的方式。当前的 viewController 不应该关闭自己,调用它的类应该关闭它
    • Apple 的文档说:“父视图控制器负责关闭它使用 presentModalViewController:animated: 方法呈现的模态视图控制器。但是,如果您在模态视图控制器本身上调用此方法,则模态视图控制器自动将消息转发到其父视图控制器。”虽然模态控制器不负责,但它并没有说它不应该自行解散。 Apple 会在其他地方记录这一点吗?
    • 耶!这绝对有效,并解决了我的问题。但是,你看这不是一个好方法吗?
    • 我确实相信 Apple 的演示示例中 viewController 会调用其父级以将其关闭,而您的报价基本上证实了这一点。我想我能想到的唯一问题是,如果父母想知道 viewController 已经以这种方式被解雇了,这样做会有问题,也许是在 viewWillAppear 方法中。取消不是问题,但是如果您想重新加载表格以更新您刚刚在 modalViewController 上输入的内容,这将是一个问题,因为父级不会知道它已被取消或添加了什么,只是它已被解雇.
    • 对——发生这种情况时,我使用 NSNotificationCenter 中心将更新消息发布回控制视图。这真的很容易,但我愿意接受其他更好的方法。
    【解决方案2】:

    通常当我使用 presentModalViewController 时,呈现的 viewController 会告诉调用 viewController 使用dismissModalViewControllerAnimated:YES;

    换句话说,在 cacncelAddingNewRide 中,您只需调用其中包含 showAddnewRideView 的类并将其传递给方法。

    这很难解释,但我给你举个例子:

    cancelAddingNewRide 类:

    - (IBACtion)home:(id)sender {
        if (self.delegate respondsToSelctor:@selector(dismiss:)]) {
            [self.delegate dismiss:self];
        }
    }
    

    然后在 showAddNewRideView 类中

    -(void) dismiss:(cancelAddingNewRide_class *) controller {
         [self dismissModalViewControllerAnimated:Yes];
    }
    

    希望这是有道理的,请注意拼写错误

    编辑:哦,让控制器的委托自己

    controller.delegate = self;
    

    实际上,更多地考虑它还有更多的东西。您必须将被调用的 viewController 定义为委托。看看斯坦福大学的 iPhone 讲座,第 11 讲涉及这个问题,可从iTunesU 获得。

    【讨论】:

    • 我已链接到完整课程,因为我无法判断之前断开的链接是针对第 11 课的视频还是幻灯片。请随时更新指向第 11 课的链接.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多