【发布时间】:2019-04-11 08:02:51
【问题描述】:
使用 Xcode 10.1 和 Swift 4.2
我有一个复杂的应用程序,它使用在AppDelegate 中实现的UINavigationController。
navigationController的rootViewController是一个DashboardController()类(UIViewController的子类)
DashboardController 使用多个 ViewController(使用 self.addChild(viewController))实现了左侧菜单抽屉
一切正常,除非我需要推送 viewController 来呈现 BarCodeScannerView().
准系统 barCodeScannerView 可以按预期推送和弹出。
当我请求访问相机时出现问题(仅第一次)。
-
只要我将
Device.requestAccess(for:)呈现如下:viewController 被弹出 并且前一个视图(rootViewController)被呈现。 (还是用“App想要访问相机”AlertView)func requestCameraAccess() { AVCaptureDevice.requestAccess(for: AVMediaType.video) { 授予 如果授予{ self.launchScanner() } 别的 { self.goBack() } } }
如果我单击“确定”,系统将注册已授予访问权限,但
applicationDidBecomeActive(在AppDelegate中)在大约 1 秒后被调用。我在applicationDidBecomeActive中有一些初始化程序,它们都被再次执行。在短暂的延迟之后,一切正常。
顺便说一句:applicationWillResignActive、applicationDidEnterBackground 和 applicationWillEnterForeground 未被调用。所以很明显,这不是 App LifeCycle 的一部分。
知道我会在这里做什么吗?什么可以让app内的系统调用applicationDidBecomeActive?并且仍然保持一切正常运行?
提前谢谢...
更新阅读 cmets 后,我能够将问题 #2 隔离如下:
带有UINavigationController 的简单/准系统项目,dashboardViewController 为rootViewController。 dashboardViewController 在viewDidLoad() 中推送一个CameraViewController()。 cameraViewController 请求访问相机。单击确定时,将触发对applicationDidBecomeActive 的调用。
附上完整的项目。 (.plist 中的“隐私 - 相机使用说明”键除外。
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")
}
}
}
}
【问题讨论】:
-
"所以很明显这不是 App LifeCycle 的一部分" 这一点都不清楚。除非你(错误地)调用
didBecomeActive,否则只有运行时可以调用它,它调用它是因为我们变得活跃。 -
但是,我认为我们应该首先关注这一点:“一旦我呈现 Device.requestAccess(for:) 如下:viewController 被弹出并呈现前一个视图 (rootViewController)。 (仍然使用“应用程序想要访问相机”AlertView)“这是错误的,您应该考虑为什么要这样做。一旦调用了授权请求,在您收到异步结果之前什么都不会发生。因此,您需要专注于为什么会在授权对话框后面发生这种弹出。
-
谢谢@matt。在阅读了您的 cmets 之后,我怀疑这与我有几个由 DashboardController 管理的 ViewControllers (使用 addChild(viewController))...顺便说一句...对 didBecomeActive 的调用是由运行时触发的。我检查了我的代码以确保我没有调用它,并且还在 .didBecomeActiveNotification 通知中添加了一个观察者来验证它。
-
嗨@matt 我创建了一个新的准系统项目来复制这个问题,我发现了一些事情:1. ViewController 的弹出与相机的 .requestAccess 无关 2.- 它是也没有将 viewControllers 用作根 viewController 的子级。我能够使用一个简单的 NavController 复制问题 #2,该 NavController 推送一个简单的 UIViewController,并且在 viewDidLoad 中请求访问会触发对 applicationDidBecomeActive 的调用。我将代码添加到问题中.....
-
嗯,您可能根本不应该在视图中请求访问,因为您的视图控制器的视图还没有在界面中。因此,如果这是问题所在,请尽量不要这样做。无论如何,如果您将其发布在 github 或类似网站上,我将很高兴看到该项目。
标签: ios swift uinavigationcontroller avcapturedevice