0

我的应用程序中内置了以下视图控制器。呈现控制器是“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:

故事板快照

提前非常感谢!

4

2 回答 2

0

您没有说您当前是使用导航控制器和推送转场,还是使用模态转场呈现。

这里:

    [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。_
  • 基于该结果,要么:

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

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

一个

- (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”中也可以将其归零。

于 2013-02-04T17:25:55.983 回答
0

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

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

   [self.navigationController popViewControllerAnimated:YES]; 

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

于 2013-02-05T19:21:24.067 回答