Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 协调视图控制器时出现问题_Ios_Objective C_Uiviewcontroller_Delegation - Fatal编程技术网

Ios 协调视图控制器时出现问题

Ios 协调视图控制器时出现问题,ios,objective-c,uiviewcontroller,delegation,Ios,Objective C,Uiviewcontroller,Delegation,我的应用程序中内置了以下视图控制器。演示控制器是“PatientSelectViewController”(我们称之为控制器A),它允许在文本字段中手动输入患者ID或按下“扫描条形码”按钮,该按钮将执行到另一个视图控制器的切换,即“BarcodeScanViewController”(我们称之为控制器B) 当B扫描完条形码并返回一个结果(患者ID)时,我通知演示视图控制器(a),a负责在数据库中查找ID。此时应解除控制器B。如果找到ID,那么我们将转换到第三个视图控制器-“PatientConf

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

当B扫描完条形码并返回一个结果(患者ID)时,我通知演示视图控制器(a),a负责在数据库中查找ID。此时应解除控制器B。如果找到ID,那么我们将转换到第三个视图控制器-“PatientConfigrmViewController”(我们称之为C)。但是,如果找不到ID,我希望弹出一条消息,上面写着“是”,然后再次转到控制器B再次扫描条形码

类似地,如果用户决定在文本字段中手动输入ID而不是扫描它,那么成功的ID会将我带到控制器C,而不成功的ID会弹出一条消息,并留在控制器a中进行另一次尝试

我还希望控制器嵌入到导航控制器中,以便始终具有选项卡栏按钮,将我带回上一个视图控制器。例如,我将有一个tabbar按钮从B或C返回a。理想情况下,如果我在成功的条形码扫描后到达C,我希望tabbar按钮将我带回到B,而不是a如果用户决定不想确认此ID,则可能需要重新扫描条形码。但这并不重要

由于某种原因,我在实现这一点上遇到了困难。下面是一个错误行为的例子:我先打电话给a,然后打电话给B(扫描条形码),然后扫描数据库中的条形码。这会正确地将我带到C,并显示患者信息。但后来我决定使用tabbar按钮“输入患者ID”返回到A,然后我再次按下“扫描条形码”按钮,再次像以前一样扫描相同的条形码,但这次没有成功过渡到C,我得到了这个屏幕-注意这个错误的tabbar!它必须同时显示“确认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
    }
}
- (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];
}
接收条形码扫描结果的委托方法(仍在控制器a中):

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

为了完整起见,在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(“条形码扫描”)和a到C(“确认”)的顺序可见。两者都是推送序列:


提前多谢

您不会说您当前是否正在使用导航控制器和推送序列,或者使用模式序列

在这里:

第一个适用于从推送序列返回,第二个适用于模式/呈现序列。当您在导航控制器中使用“后退”按钮时,推送返回方法实际上就是这样

更新 我认为你需要稍微理清你的导航方法。我的建议

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

    • 检查患者ID
    • 如果很好,请在
    • 将布尔成功/失败返回到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时,才会发生此性能检查)

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


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

好的,我想部分回答我自己的问题。 即使在执行了上面的建议后,我的麻烦依然存在,甚至成倍增加(关于这些问题的一些细节,请参阅我在讨论帖中的评论)

然而,通过一些更改,我在谷歌上搜索了我得到的日志消息:“嵌套推送动画可能导致导航栏损坏”,最后阅读了以下答案:,这表明我的问题是使用了

   [self.navigationController popViewControllerAnimated:YES]; 
这是设置为“是”的动画。一旦我将其设置为NO,tabbar的问题就消失了(一些小问题仍然存在,我希望很快解决它们)。这真的很奇怪——对m来说,这更像是一个bug,而不是一个特性
- (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;
    }
}
   [self.navigationController popViewControllerAnimated:YES];