AVCaptureDevice.requestAccess 使用 UINavigationController 出现意外行为
AVCaptureDevice.requestAccess presents unexpected behavior with a UINavigationController
使用 Xcode 10.1 和 Swift 4.2
我有一个复杂的应用程序,它使用在 AppDelegate
中实现的 UINavigationController
。
navigationController 的 rootViewController 是 DashboardController()
class(UIViewController
的子class)
DashboardController
使用多个 ViewController(使用 self.addChild(viewController)
)实现左侧菜单抽屉
一切正常,除非我需要按 viewController 来呈现 BarCodeScannerView().
准系统 barCodeScannerView 可以按预期 pushed 和 popped。
当我请求访问相机时出现问题(只是第一次)。
只要我按如下方式显示 Device.requestAccess(for:)
:viewController 是 popped 并且前一个视图 (rootViewController) 是呈现。 (仍然使用 "App would like to access the camera" AlertView)
func requestCameraAccess() {
AVCaptureDevice.requestAccess(for: AVMediaType.video) { 授予
如果授予{
self.launchScanner()
} 别的 {
self.goBack()
}
}
}
如果我点击"OK" 系统会注册访问已被授予,但是
applicationDidBecomeActive
(在 AppDelegate
中)在大约 1 秒后被调用。我在 applicationDidBecomeActive
中有一些初始化器,它们都被再次执行。在短暂延迟后,一切正常。
顺便说一句:未调用 applicationWillResignActive
、applicationDidEnterBackground
和 applicationWillEnterForeground
。所以很明显这不是 App LifeCycle 的一部分。
知道我在这里会发生什么吗?什么可以使应用程序内的系统调用applicationDidBecomeActive
?并仍然保留所有内容 运行?
提前致谢...
更新 阅读评论后,我能够将问题 #2 隔离如下:
一个 simple/barebones 项目,其中 UINavigationController
的 dashboardViewController 为 rootViewController
。 dashboardViewController 在 viewDidLoad()
中推送 CameraViewController()
。 cameraViewController 请求访问相机。单击“确定”时,将触发对 applicationDidBecomeActive
的调用。
附上完整项目。 (.plist 中的 "Privacy - Camera Usage Description" 键除外。
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow? = UIWindow()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let dashboardViewController = DashboardViewController()
window?.rootViewController = UINavigationController(rootViewController: dashboardViewController)
window?.makeKeyAndVisible()
return true
}
func applicationDidBecomeActive(_ application: UIApplication) {
print("applicationDidBecomeActive")
}
func applicationWillResignActive(_ application: UIApplication) {}
func applicationDidEnterBackground(_ application: UIApplication) {}
func applicationWillEnterForeground(_ application: UIApplication) {}
func applicationWillTerminate(_ application: UIApplication) {}
}
class DashboardViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
let cameraVC = CameraViewController()
self.navigationController?.pushViewController(cameraVC, animated: true)
}
}
import AVFoundation
class CameraViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
AVCaptureDevice.requestAccess(for: AVMediaType.video) { granted in
if granted {
print("Access granted")
}
}
}
}
我会说问题出在你的测试程序上。当我 运行 你的代码在 applicationWillResignActive
中带有 print
语句时,这就是我看到的:
applicationDidBecomeActive
applicationWillResignActive
Access granted
applicationDidBecomeActive
这看起来完全正常。得到一个虚假的 didBecomeActive
会很奇怪,但事实并非如此;我们退出活跃状态,然后再次活跃起来,这很好。您应该期望您的应用程序可以随时退出活动状态并再次变为活动状态。正常生命周期中的许多事情都可能导致这种情况,像授权对话框这样的进程外对话框的呈现可以合理地成为其中之一。您应该以应对这种可能性的方式编写代码。
使用 Xcode 10.1 和 Swift 4.2
我有一个复杂的应用程序,它使用在 AppDelegate
中实现的 UINavigationController
。
navigationController 的 rootViewController 是 DashboardController()
class(UIViewController
的子class)
DashboardController
使用多个 ViewController(使用 self.addChild(viewController)
)实现左侧菜单抽屉
一切正常,除非我需要按 viewController 来呈现 BarCodeScannerView().
准系统 barCodeScannerView 可以按预期 pushed 和 popped。
当我请求访问相机时出现问题(只是第一次)。
只要我按如下方式显示
Device.requestAccess(for:)
:viewController 是 popped 并且前一个视图 (rootViewController) 是呈现。 (仍然使用 "App would like to access the camera" AlertView)func requestCameraAccess() { AVCaptureDevice.requestAccess(for: AVMediaType.video) { 授予 如果授予{ self.launchScanner() } 别的 { self.goBack() } } }
如果我点击"OK" 系统会注册访问已被授予,但是
applicationDidBecomeActive
(在AppDelegate
中)在大约 1 秒后被调用。我在applicationDidBecomeActive
中有一些初始化器,它们都被再次执行。在短暂延迟后,一切正常。
顺便说一句:未调用 applicationWillResignActive
、applicationDidEnterBackground
和 applicationWillEnterForeground
。所以很明显这不是 App LifeCycle 的一部分。
知道我在这里会发生什么吗?什么可以使应用程序内的系统调用applicationDidBecomeActive
?并仍然保留所有内容 运行?
提前致谢...
更新 阅读评论后,我能够将问题 #2 隔离如下:
一个 simple/barebones 项目,其中 UINavigationController
的 dashboardViewController 为 rootViewController
。 dashboardViewController 在 viewDidLoad()
中推送 CameraViewController()
。 cameraViewController 请求访问相机。单击“确定”时,将触发对 applicationDidBecomeActive
的调用。
附上完整项目。 (.plist 中的 "Privacy - Camera Usage Description" 键除外。
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow? = UIWindow()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let dashboardViewController = DashboardViewController()
window?.rootViewController = UINavigationController(rootViewController: dashboardViewController)
window?.makeKeyAndVisible()
return true
}
func applicationDidBecomeActive(_ application: UIApplication) {
print("applicationDidBecomeActive")
}
func applicationWillResignActive(_ application: UIApplication) {}
func applicationDidEnterBackground(_ application: UIApplication) {}
func applicationWillEnterForeground(_ application: UIApplication) {}
func applicationWillTerminate(_ application: UIApplication) {}
}
class DashboardViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
let cameraVC = CameraViewController()
self.navigationController?.pushViewController(cameraVC, animated: true)
}
}
import AVFoundation
class CameraViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
AVCaptureDevice.requestAccess(for: AVMediaType.video) { granted in
if granted {
print("Access granted")
}
}
}
}
我会说问题出在你的测试程序上。当我 运行 你的代码在 applicationWillResignActive
中带有 print
语句时,这就是我看到的:
applicationDidBecomeActive
applicationWillResignActive
Access granted
applicationDidBecomeActive
这看起来完全正常。得到一个虚假的 didBecomeActive
会很奇怪,但事实并非如此;我们退出活跃状态,然后再次活跃起来,这很好。您应该期望您的应用程序可以随时退出活动状态并再次变为活动状态。正常生命周期中的许多事情都可能导致这种情况,像授权对话框这样的进程外对话框的呈现可以合理地成为其中之一。您应该以应对这种可能性的方式编写代码。