【问题标题】:Trouble coordinating view controllers无法协调视图控制器
【发布时间】:2013-01-19 10:13:05
【问题描述】:

我的应用程序中内置了以下视图控制器。呈现控制器是“PatientSelectViewController”(我们称之为控制器 A),它允许在文本字段中手动输入患者 ID 或按下“扫描条形码”按钮,该按钮将执行对另一个视图控制器的 segue - 即“BarcodeScanViewController "(我们称它为控制器 B)。

当 B 完成扫描条形码并返回结果(患者 ID)时,我将通知呈现视图控制器 (A),并且 A 负责在数据库中查找 ID。此时控制器 B 应该被解散。如果找到了 ID,那么我们过渡到第三个视图控制器 - “PatientConfirmViewController”(我们称之为 C)。但是,如果没有找到 ID,那么我想要一条弹出消息,说明并再次转到控制器 B 以再次扫描条形码。

同样,如果用户决定在文本字段中手动输入 ID 而不是扫描它,那么成功的 ID 会将我带到控制器 C,而不成功的 ID 会弹出消息并留在控制器 A 中再试一次。

我还希望将控制器嵌入到导航控制器中,这样我总是有标签栏按钮可以带我回到上一个视图控制器。例如,我将有一个标签栏按钮从 B 或 C 返回到 A。理想情况下,如果我在成功扫描条形码后到达 C,我希望标签栏按钮将我带回 B - 而不是 A! - 如果用户决定她不想确认此 ID,则其想法是用户可能想要重新扫描条形码。但这并不重要。

由于某种原因,我无法实现此功能。这是一个搞砸行为的例子:我打电话给 A 然后打电话给 B(扫描条形码)并扫描我知道在数据库中的条形码。这正确地将我带到 C 并显示患者信息。但后来我决定使用标签栏按钮“输入患者 ID”返回 A 然后我再次按下“扫描条形码”按钮,再次扫描与以前相同的条形码,但这次不是成功转换到 C,我得到了这个屏幕 - 注意搞砸的标签栏!它必须同时说“确认 ID”和“输入患者 ID”,然后按钮返回登录(这是首先调用 A 的控制器)和“扫描条形码” - 即控制器 B好像它以前从未弹出过一样! 这可能会在 2 次或 3 次或更多次成功扫描后随机发生。日志显示如下:

嵌套推送动画会导致导航栏损坏

开始/结束外观转换的不平衡调用 .

完成导航 过渡到意想不到的状态。导航栏子视图树可能 被损坏了。

这是我的实现方式:

在视图控制器 A 中:

-(void)prepareForSegue: (UIStoryboardSegue *)segue sender: (id)sender
{
    if ([[segue identifier] isEqualToString:@"BarcodeScanView"])
    {
        self.p_usingBarcodeScan=YES;
        [[segue destinationViewController]setViewDelegate:self]; //sets itself as a delegate for receiving the result of a barcode scan from controller B 
    }
    if ([[segue identifier] isEqualToString:@"ConfirmID"])
    {
        [[segue destinationViewController] setP_userInfo:p_userInfo]  ; //passes the data to the controller C
    }
}

接收条码扫描结果的委托方法(仍在控制器A中):

- (void) didScanBarcode:(NSString *)result
{

    self.p_userID = result;

    [self.navigationController popViewControllerAnimated:YES];//Pop B from the navigation stack to return to A - is this right????

    //Run the database query
    [self lookUpID];
}

在数据库中查找ID的方法(还在A中):

- (void) lookUpID{


    /*.....
    Does something here and gets a result of the lookup...
    */

    // Do something with the result
    if ([[result  p_userName] length] > 0 ){ //Found the user!
        p_userInfo = result;
        [self performSegueWithIdentifier: @"ConfirmID" sender: self];

    }
    else {
        UIAlertView * messageDlg = [[UIAlertView alloc] initWithTitle:nil message:@"User was not found. Please try again"
                                                             delegate:self cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
        [messageDlg show];

        //Here I'd like to perform this seque to B only if I got here after a barcode scan... 
        //Otherwise I am just staying in A...
        if (self.p_usingBarcodeScan == YES ){
            [self performSegueWithIdentifier: @"BarcodeScanView" sender: self];
        }  
    }
    return;
}

为了完整起见,在 B 中,一旦我设法扫描了条形码,我将其称为:

- (void)decodeResultNotification: (NSNotification *)notification {

    if ([notification.object isKindOfClass:[DecoderResult class]])
    {
        DecoderResult *obj = (DecoderResult*)notification.object;
        if (obj.succeeded)
        {
            decodeResult = [[NSString alloc] initWithString:obj.result];

            [[self viewDelegate] didScanBarcode:decodeResult];
        }
    }
}

我正在使用从 A 到 B 和从 A 到 C 的推送序列并使用情节提要。 这是情节提要的快照,从 A 到 B(“BarcodeScan”)和 A 到 C(“ConfirmID”)的转场可见。两者都是 push segues:

提前非常感谢!

【问题讨论】:

    标签: ios objective-c uiviewcontroller delegation


    【解决方案1】:

    你没有说你当前是在使用导航控制器并推送 segues,还是使用模态 segues 呈现。

    这里:

        [self.navigationController popViewControllerAnimated:YES];//Pop B from the navigation stack to return to A - is this right????
        [self dismissViewControllerAnimated:YES completion:nil];**//is this right???**
    

    第一个适用于从 push segue 返回,第二个适用于模态/呈现 segue。当您在导航控制器中使用后退按钮时,实际上会发生 push-return 方法。

    更新 我认为您需要稍微解开导航方法。我的建议

    • 在B中,有一个委托方法

      • 检查患者 ID
      • 如果好的话在A中设置self.p_userID
      • 将 BOOL 成功/失败返回给 B。
        _
    • 基于该结果,要么:

      • 弹出自己(你可以直接在B中使用[self.navigationController popViewController])或

      • 在 B 中显示您的警报。鉴于您在 B 中有一个后退按钮,并且(可能)有一个重新扫描按钮,您的警报可能不需要提供任何选择。

    A

    - (void) viewWillAppear:(BOOL)animated
    {
        NSLog (@"viewControllers %@",self.navigationController.viewControllers);
    
        [super viewWillAppear:animated];
        if (self.p_userID) {
            [self performSegueWithIdentifier: @"ConfirmID" sender: self];
            self.p_userID = nil;
        }
    }
    

    (只有当你还在 B 中设置 self.p_userID 时才会发生这种 performSegue)

    键入的用户 ID 逻辑更简单。再次检查患者 ID。如果它不存在,则在 A 中发出警报(同样,您不需要提供选择,因为所有导航选项都可以在没有警报的情况下使用)。如果存在,将 self.p_userID 设置为 ID 并启动 segue。

    prepareForSegue 中,您应该进行查找以从 self.p_userID 获取 userInfo 字典以传递给 C,然后将 self.p_userID 设置为 nil。或者(更好)只需将 self.p_userID 传递给 C 并在 C 中进行查找(假设您有一个单独的模型源对象)。无论您做什么,请务必在离开 A 时将 self.p_userID 设置为 nil,这样您就不会自动触发您不想要的 segue!也许在“viewWillDisappear”中也可以将其归零。

    【讨论】:

    • 谢谢!是的,我意识到当我使用 push segues 时,我应该只使用第一行!我更新了我原来的问题以反映这一点。然而,即使在这些更改之后,导航栏仍然搞砸了,第二次对 B 的转接没有完成等等。显然我仍然错过了一些东西....
    • @user1959008 - 我看不到您发布的代码有任何其他问题 - 也许您可以用更多代码或确切的未发生/出错的信息来更新您的问题。你是什​​么意思'导航栏仍然搞砸'和'segue to B没有完成'......也许还有你的故事板的图片及其连接。
    • 他是,谢谢,我更新了我原来的问题,用一个屏幕截图和我的故事板屏幕截图导致不良行为的场景。
    • 在我看来,问题在于我在 A 的委托方法中解除了 B(使用 [self.navigationController popViewControllerAnimated:YES];),而执行预计返回B 委托方法结束后。是这个问题吗?如果是这样,我还应该如何解雇 B?不建议呈现视图控制器关闭呈现的视图控制器吗?甚至 Apple 自己的视图控制器教程也有一个列表,其中委托方法正在关闭呈现的视图控制器!
    • @user1959008 是的......问题是,通过 B 中的一种方法,您要求自己从 A 中解散,然后立即推送另一个 VC。结果他们混在一起了。您需要解开并简化您的导航。我会尽快更新我的答案...
    【解决方案2】:

    好的,我正在尝试部分回答我自己的问题。 即使在执行了上面的 He Was 建议之后,我的麻烦仍然存在,甚至成倍增加(关于这些的一些细节在我在讨论线程https://chat.stackoverflow.com/rooms/23918/discussion-between-peterd-and-he-was 的评论中)

    但是,通过一些更改,我搜索了我收到的日志消息:“嵌套推送动画可能导致导航栏损坏”并最终阅读了这个答案:https://stackoverflow.com/a/5616935/1959008,这表明我的问题正在使用

       [self.navigationController popViewControllerAnimated:YES]; 
    

    即动画设置为 YES。一旦我将它设置为 NO,标签栏的问题就消失了(一些小怪癖仍然存在,我希望尽快解决它们)。这真的很奇怪——在我看来更像是一个错误而不是一个功能,但我当然可能是错的......

    【讨论】:

      猜你喜欢
      • 2019-02-09
      • 1970-01-01
      • 2021-04-19
      • 2011-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多