我在我的应用程序中构建了以下视图控制器。呈现控制器是“PatientSelectViewController”(让我们称之为控制器A),它允许在文本字段中手动输入患者ID或按下“扫描条形码”按钮,该按钮将执行到另一个视图控制器的segue - 即“BarcodeScanViewController” “(我们称之为控制器B)。
当B完成扫描条形码并返回结果(患者ID)时,我通知呈现视图控制器(A)有关它,A负责在数据库中查找ID。此时控制器B应该被解雇。如果找到了ID,那么我们转换到第三个视图控制器 - “PatientConfirmViewController”(让我们称之为C)。但是,如果找不到ID,那么我想要一条弹出消息,然后再次向控制器B再次扫描条形码。
同样,如果用户决定在文本字段中手动输入ID而不是扫描它,那么成功的ID会将我带到控制器C,而不成功的ID会给出弹出消息并保留在控制器A中再试一次。
我还希望将控制器嵌入到导航控制器中,这样我总是有tabbar按钮可以让我回到上一个视图控制器。例如,我将有一个标签栏按钮从B或C返回A.理想情况下,如果我在条形码扫描成功后到达C,我希望标签栏按钮将我带回B - 而不是A! - 如果用户决定她不想确认该ID,则该想法是用户可能想要重新扫描条形码。但这并不重要。
由于某种原因,我无法实现此功能。这是一个搞砸行为的例子:我正在调用A然后调用B(扫描条形码)并扫描我知道在数据库中的条形码。这正确地将我带到C并显示患者信息。但后来我决定使用标签栏按钮“输入患者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
}
}
接收条形码扫描结果的委托方法(仍在控制器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:
提前多多感谢!
答案 0 :(得分:0)
您没有说明您当前是使用导航控制器还是推送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???**
第一个对于从推送segue返回是正确的,第二个适用于模态/呈现segue。推送返回方法实际上是在导航控制器中使用后退按钮时发生的情况。
<强>更新强> 我想你需要稍微解开你的导航方法。我的建议
在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)
键入的userID逻辑更简单。再次检查患者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'中也可以为零。
答案 1 :(得分:0)
好的,我正试图部分回答我自己的问题。 即使在实施了上述建议之后,我的麻烦仍然存在甚至成倍增加(关于这些的一些细节在我在讨论主题http://chat.stackoverflow.com/rooms/23918/discussion-between-peterd-and-he-was的评论中)
然而,通过一些更改我搜索了我得到的日志消息:“嵌套推送动画可能导致导航栏损坏”并且最后阅读了这个答案:https://stackoverflow.com/a/5616935/1959008,这表明我的问题是使用
[self.navigationController popViewControllerAnimated:YES];
将动画设置为YES。一旦我将它设置为NO,tabbar的问题就消失了(一些小怪怪仍然存在,我希望很快就能解决它们)。这真的很奇怪 - 看起来更像是一个错误,而不是一个功能,但我当然可能是错的......