Swift UIAlert不等待用户响应

f4t66c6m  于 2023-01-16  发布在  Swift
关注(0)|答案(1)|浏览(145)
func permissionInit() {
  Task{
        addListViewModel?.cameraPermission.accept(await chkCameraPermission())
            addListViewModel?.photoLibraryPermission.accept(await chkPhotoLibraryPermission())
            addListViewModel?.motionPermission.accept(await chkMotionPermission())
        }
    }

private func chkCameraPermission() async -> Bool{
        let mediaType = AVMediaType.video
        await AVCaptureDevice.requestAccess(for: mediaType)
        let mediaAuthoriztionStatus = AVCaptureDevice.authorizationStatus(for: mediaType)
        switch mediaAuthoriztionStatus{
        case .authorized:
            print("ShopUp Camera Permission True")
            return true
        case .denied, .restricted, .notDetermined:
            print("ShopUp Camera Permission False")
            warningAlert(title: "권한 오류", infoMativeMsg: "")
            return false
        default:
            return false
        }
    }
    
    private func chkPhotoLibraryPermission() async -> Bool {
        let status = await PHPhotoLibrary.requestAuthorization(for: .readWrite)
        switch status {
        case .authorized:
            print("ShopUp Photo Permission True")
            return true
        case .denied, .restricted, .notDetermined:
            print("ShopUp Photo Permission False")
            warningAlert(title: "권한 오류", infoMativeMsg: "")
            return false
        default:
            return false
        }
    }
    
    private func chkMotionPermission() async -> Bool{
        let coreMotionGranted = CMPedometer.authorizationStatus()
        switch coreMotionGranted {
        case .authorized:
            print("ShopUp CoreMotion Permission True")
            return true
        case .notDetermined, .restricted, .denied :
            print("ShopUp CoreMotion Permission False")
            warningAlert(title: "권한 오류", infoMativeMsg: "")
            return false
        default:
            return false
        }
    }
    
    func warningAlert(title: String, infoMativeMsg: String, completionHandler: Void? = nil) {
        let alert = UIAlertController(title: title, message: infoMativeMsg, preferredStyle: .alert)
        if completionHandler != nil {
            let okAction = UIAlertAction(title: "확인", style: .default, handler: {_ in completionHandler})
            alert.addAction(okAction)
        }else {
            let okAction = UIAlertAction(title: "확인", style: .default)
            alert.addAction(okAction)
        }
        self.present(alert, animated: true, completion: completionHandler != nil ? {completionHandler!} : nil)
    }

我在ViewController中添加了UIAlert,但它不等待用户响应并显示错误。
我也试过在self.present上等待,但也不起作用。permissionInit有一个等待,但似乎不起作用。

2023-01-09 14:45:37.015435+0900 ShopUp[544:94537] [Presentation] Attempt to present <UIAlertController: 0x12c03e000> on <UINavigationController: 0x12d019c00> (from <ShopUp.AddListViewController: 0x12ce08350>) while a presentation is in progress.
2023-01-09 14:45:37.015644+0900 ShopUp[544:94537] [Presentation] Attempt to present <UIAlertController: 0x12d07b800> on <UINavigationController: 0x12d019c00> (from <ShopUp.AddListViewController: 0x12ce08350>) while a presentation is in progress.

我想按顺序显示UIAlert。
如果你能告诉我哪一部分错了,我将不胜感激。

q0qdq0h2

q0qdq0h21#

你正在调用三个函数,它们都试图同时(或几乎同时)显示一个警报。只有第一个成功,因为一个视图控制器只能显示另一个视图控制器。另外两个失败,这就是为什么你会得到两个错误消息。
下面是连接这三个请求的一种方法,这样每个请求都将等待前一个请求完成:

extension UIViewController {
    func permissionInit() {
        let avCapture = Observable.createAsync { await AVCaptureDevice.requestAccess(for: .video) }
            .filter { !$0 }
            .observe(on: MainScheduler.instance)
            .flatMap { [weak self] _ in self?.warningAlert(title: "권한 오류", infoMativeMsg: "") ?? Observable.empty() }

        let phPhoto = Observable.createAsync { await PHPhotoLibrary.requestAuthorization(for: .readWrite) }
            .filter { $0 != .authorized }
            .observe(on: MainScheduler.instance)
            .flatMap { [weak self] _ in self?.warningAlert(title: "권한 오류", infoMativeMsg: "") ?? Observable.empty() }

        let cmPedo = Observable.just(CMPedometer.authorizationStatus())
            .filter { $0 != .authorized }
            .flatMap { [weak self] _ in self?.warningAlert(title: "권한 오류", infoMativeMsg: "") ?? Observable.empty() }

        _ = Observable.concat(avCapture, phPhoto, cmPedo)
            .subscribe(onNext: {
                print("all requests complete.")
            })
    }

    func warningAlert(title: String, infoMativeMsg: String) -> Observable<Void> {
        Observable.deferred {
            let result = PublishSubject<Void>()
            let alert = UIAlertController(title: title, message: infoMativeMsg, preferredStyle: .alert)
            let okAction = UIAlertAction(title: "확인", style: .default, handler: { _ in result.onSuccess(()) })
            alert.addAction(okAction)
            self.present(alert, animated: true, completion: nil)
            return result
        }
    }
}

extension Observable {
    static func createAsync(_ asyncFunc: @escaping () async throws -> Element) -> Observable<Element> {
        Observable.create { observer in
            let task = Task {
                do {
                    observer.onSuccess(try await asyncFunc())
                } catch {
                    observer.onError(error)
                }
            }
            return Disposables.create { task.cancel() }
        }
    }
}

public extension ObserverType {
    func onSuccess(_ element: Element) -> Void {
        onNext(element)
        onCompleted()
    }
}

关键在于使用concat操作符,它一次只订阅一个Observable,直到Observable停止订阅下一个Observable。
在本文中了解更多信息:Recipes for Combining Observables in RxSwift
最后,我也同意HangarRash的观点。

相关问题