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