尝试在视图不在 window 层次结构中的 <OutgoingController: 0x104042600> 上显示 <OutgoingController: 0x1040e9600>
Attempt to present <OutgoingController: 0x1040e9600> on <OutgoingController: 0x104042600> whose view is not in the window hierarchy
我正在尝试使用 call Kit 实现一个 VoIP 应用程序。一个特定的场景是接受来电并结束已经在通话的呼叫。接听电话后,我会在 OutgoingCallController 中显示已连接的呼叫界面。
所以在特定情况下,我试图关闭已经连接的 OutgoingCallController,然后尝试使用新的来电详细信息再次呈现新的 OutgoingCallController。
我试图呈现 OutgoingCallController 的逻辑是这些代码行。 我在 CXProviderDelegate 中调用这个方法 class。
func displayOutgoingScreen() throws {
SwiftyBeaver.verbose("Starting displayOutgoingScreen!! ")
let storyBoard = UIStoryboard.init(name: DiallerProperties.storyBoard, bundle: nil)
let incomingcallController:OutgoingCallWithAllController = storyBoard.instantiateViewController(withIdentifier: "outgoingWithAll") as! OutgoingCallWithAllController
//incomingcallController.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
incomingcallController.number = AppDelegate().getIncomingCallNumber()
SwiftyBeaver.verbose("Incoming call number is: \(incomingcallController.number)")
DispatchQueue.main.async(execute: { () -> Void in
let keyWindow = UIApplication.shared.keyWindow
var controller:UIViewController = (keyWindow?.rootViewController)!
while controller.presentedViewController != nil {
controller=controller.presentedViewController!
}
let dateFormatter : DateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let date = Date()
let dateString = dateFormatter.string(from: date)
let interval = date.timeIntervalSince1970
print("presenting view here \(dateString) \(interval)!!")
controller.present(incomingcallController, animated: true, completion: nil)
});
}
特定日期代码用于记录目的,以查看执行这行代码的时间。
在 OutgoingCallWithAllController viewWillDisappear 方法中,我使用了相同的日期逻辑来查看该特定方法何时被执行。
这是我收到的输出。
viewWillDisappear test 2019-03-01 13:34:32 1551427472.314188!!
presenting view here 2019-03-01 13:34:32 1551427472.324421!!
这是我在调试器日志中收到的警告消息。
2019-03-01 13:34:32.344713+0530 [710:214818] Warning: Attempt to present <OutgoingCallWithAllController: 0x1040e9600> on <OutgoingCallWithAllController: 0x104042600> whose view is not in the window hierarchy!
这是我用来解除旧 OutgoingCallController 的代码片段。 outgoingvc 包含对我的 OutgoingCallController
的引用
AppDelegate.shared.outgoingvc?.dismiss(animated: false, completion: nil)
因为我试图关闭旧的 outgoingCallController 并再次显示它,所以我可以理解我正在尝试在已经关闭的旧控制器上显示新的 outgoingCallController。
所以我尝试使用下面的代码延迟呈现新控制器。
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
//providing delay so that outgoing call controller has been closed
action.fulfill()
SwiftyBeaver.verbose("Executing after delay!!")
}
但是,我仍然无法控制。我该如何解决这个特定问题?
如果万一已经调查过这个问题:
Warning: Attempt to present * on * whose view is not in the window hierarchy - swift
我知道我将旧的 OutgoingCallController 作为顶视图。
您可以使用以下扩展程序获取顶视图控制器:
extension UIApplication {
class func getTopMostViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return getTopMostViewController(base: nav.visibleViewController)
}
if let tab = base as? UITabBarController {
if let selected = tab.selectedViewController {
return getTopMostViewController(base: selected)
}
}
if let presented = base?.presentedViewController {
return getTopMostViewController(base: presented)
}
return base
}
}
使用此扩展程序使用以下代码获取导航堆栈中最顶层的视图控制器:
guard let topVC = UIApplication.getTopMostViewController() else {return}
使用顶视图控制器预设您的视图控制器:
DispatchQueue.main.async(execute: { () -> Void in
topVC.present(incomingcallController, animated: true, completion: nil)
}
我通过尝试在 0.5 秒间隔后获取最顶层的视图控制器来修复它。
即我在 0.5 秒间隔后调用我的 displayOutgoingScreen 函数。
在那段时间里,我的老朋友传出控制器恰好被完全关闭,我能够看到我的传出屏幕。
我认为您正试图在另一个实例被完全关闭之前呈现 Outgoing 视图控制器实例。
通过延迟发送,您只是掩盖了这个问题。
我建议你,如果你已经有一个模态呈现的视图控制器是堆栈,并且你关闭它,你可以在关闭函数的完成块中调用你的呈现函数。这样,当前一个视图控制器从视图层次结构中完全删除时,将显示下一个视图控制器。
但我仍然认为这不是一个好的用户体验。
我正在尝试使用 call Kit 实现一个 VoIP 应用程序。一个特定的场景是接受来电并结束已经在通话的呼叫。接听电话后,我会在 OutgoingCallController 中显示已连接的呼叫界面。
所以在特定情况下,我试图关闭已经连接的 OutgoingCallController,然后尝试使用新的来电详细信息再次呈现新的 OutgoingCallController。
我试图呈现 OutgoingCallController 的逻辑是这些代码行。 我在 CXProviderDelegate 中调用这个方法 class。
func displayOutgoingScreen() throws {
SwiftyBeaver.verbose("Starting displayOutgoingScreen!! ")
let storyBoard = UIStoryboard.init(name: DiallerProperties.storyBoard, bundle: nil)
let incomingcallController:OutgoingCallWithAllController = storyBoard.instantiateViewController(withIdentifier: "outgoingWithAll") as! OutgoingCallWithAllController
//incomingcallController.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
incomingcallController.number = AppDelegate().getIncomingCallNumber()
SwiftyBeaver.verbose("Incoming call number is: \(incomingcallController.number)")
DispatchQueue.main.async(execute: { () -> Void in
let keyWindow = UIApplication.shared.keyWindow
var controller:UIViewController = (keyWindow?.rootViewController)!
while controller.presentedViewController != nil {
controller=controller.presentedViewController!
}
let dateFormatter : DateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let date = Date()
let dateString = dateFormatter.string(from: date)
let interval = date.timeIntervalSince1970
print("presenting view here \(dateString) \(interval)!!")
controller.present(incomingcallController, animated: true, completion: nil)
});
}
特定日期代码用于记录目的,以查看执行这行代码的时间。
在 OutgoingCallWithAllController viewWillDisappear 方法中,我使用了相同的日期逻辑来查看该特定方法何时被执行。
这是我收到的输出。
viewWillDisappear test 2019-03-01 13:34:32 1551427472.314188!!
presenting view here 2019-03-01 13:34:32 1551427472.324421!!
这是我在调试器日志中收到的警告消息。
2019-03-01 13:34:32.344713+0530 [710:214818] Warning: Attempt to present <OutgoingCallWithAllController: 0x1040e9600> on <OutgoingCallWithAllController: 0x104042600> whose view is not in the window hierarchy!
这是我用来解除旧 OutgoingCallController 的代码片段。 outgoingvc 包含对我的 OutgoingCallController
的引用AppDelegate.shared.outgoingvc?.dismiss(animated: false, completion: nil)
因为我试图关闭旧的 outgoingCallController 并再次显示它,所以我可以理解我正在尝试在已经关闭的旧控制器上显示新的 outgoingCallController。
所以我尝试使用下面的代码延迟呈现新控制器。
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
//providing delay so that outgoing call controller has been closed
action.fulfill()
SwiftyBeaver.verbose("Executing after delay!!")
}
但是,我仍然无法控制。我该如何解决这个特定问题?
如果万一已经调查过这个问题:
Warning: Attempt to present * on * whose view is not in the window hierarchy - swift
我知道我将旧的 OutgoingCallController 作为顶视图。
您可以使用以下扩展程序获取顶视图控制器:
extension UIApplication {
class func getTopMostViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return getTopMostViewController(base: nav.visibleViewController)
}
if let tab = base as? UITabBarController {
if let selected = tab.selectedViewController {
return getTopMostViewController(base: selected)
}
}
if let presented = base?.presentedViewController {
return getTopMostViewController(base: presented)
}
return base
}
}
使用此扩展程序使用以下代码获取导航堆栈中最顶层的视图控制器:
guard let topVC = UIApplication.getTopMostViewController() else {return}
使用顶视图控制器预设您的视图控制器:
DispatchQueue.main.async(execute: { () -> Void in
topVC.present(incomingcallController, animated: true, completion: nil)
}
我通过尝试在 0.5 秒间隔后获取最顶层的视图控制器来修复它。
即我在 0.5 秒间隔后调用我的 displayOutgoingScreen 函数。
在那段时间里,我的老朋友传出控制器恰好被完全关闭,我能够看到我的传出屏幕。
我认为您正试图在另一个实例被完全关闭之前呈现 Outgoing 视图控制器实例。
通过延迟发送,您只是掩盖了这个问题。
我建议你,如果你已经有一个模态呈现的视图控制器是堆栈,并且你关闭它,你可以在关闭函数的完成块中调用你的呈现函数。这样,当前一个视图控制器从视图层次结构中完全删除时,将显示下一个视图控制器。
但我仍然认为这不是一个好的用户体验。