如果 authorizationStatus 被拒绝,SwiftUI 将用户定向到他们的设置页面

标签 swift uikit swiftui

我调用了一个函数来访问用户的联系信息。但是,我需要此功能来提示用户警告,如果 authorizationStatus 被拒绝,可以将他们重定向到他们的设置页面。

到目前为止,我的代码可以成功提示用户输入他们的联系信息。但是,如果案例最终被拒绝,我想运行 show_settings_alert 函数,如下所示:

func requestContactPermissions(completion: @escaping (Bool) -> ()) {
    let store = CNContactStore()
    var authStatus = CNContactStore.authorizationStatus(for: .contacts)
    switch authStatus {
    case .denied:
        show_settings_alert()
}

这是我在一些关于此问题的教程中找到的 show_settings_alert 函数:

func show_settings_alert() {
    let alertController = UIAlertController(title: "TITLE", message: "Please go to Settings and turn on the permissions", preferredStyle: .alert)
    let settingsAction = UIAlertAction(title: "Settings", style: .default) { (_) -> Void in
        guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else {
            return
        }
        if UIApplication.shared.canOpenURL(settingsUrl) {
            UIApplication.shared.open(settingsUrl, completionHandler: { (success) in })
         }
    }
    let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)
    alertController.addAction(cancelAction)
    alertController.addAction(settingsAction)
    
    self.present(alertController, animated: true, completion: nil)
}

问题是,我试图在一个函数中运行 self.present,因此,我无法访问 self。我也认识到这是 UIKit 代码,但我不完全确定如何在使用 SwiftUI 时获得相同的功能。

我知道 SwiftUI 附带了一个 Alert 类,但我不希望在我的模板 View 中包含此逻辑。

最佳答案

我之前在使用camera usage的时候也做过类似的实现。
我认为您可以使用 Combine 和 SwiftUI 来实现它。 当您选择拒绝或限制时,以下实现将显示警报。

import Combine
import Contacts

class Contact: ObservableObject {
  var dispose = Set<AnyCancellable>()
  let contactStore = CNContactStore()
  @Published var invalidPermission: Bool = false
  
  var authorizationStatus: AnyPublisher<CNAuthorizationStatus, Never> {
    Future<CNAuthorizationStatus, Never> { promise in
      self.contactStore.requestAccess(for: .contacts) { (_, _) in
        let status = CNContactStore.authorizationStatus(for: .contacts)
        promise(.success(status))
      }
    }
    .eraseToAnyPublisher()
  }
  
  func requestAccess() {
    self.authorizationStatus
      .receive(on: RunLoop.main)
      .map { $0 == .denied || $0 == .restricted }
      .assign(to: \.invalidPermission, on: self)
      .store(in: &dispose)
  }
}

ContactView 通过 Contact 类的 invalidPermission 状态显示警报。

在这段代码中,您按下一个按钮来向联系人请求使用它的权限。如果被拒绝,则显示转到设置的警报。如果已授权,则不会显示警报。

struct ContactView: View {
  @ObservedObject var contact = Contact()
  
  var body: some View {
    VStack {
      Button(action: {
        // if pressed button, request contact permissions
        self.contact.requestAccess()
      }) {
        Text("Request access to Contacts")
      }
    }
    .alert(isPresented: self.$contact.invalidPermission) {
      Alert(
        title: Text("TITLE"),
        message: Text("Please go to Settings and turn on the permissions"),
        primaryButton: .cancel(Text("Cancel")),
        secondaryButton: .default(Text("Settings"), action: {
          if let url = URL(string: UIApplication.openSettingsURLString), UIApplication.shared.canOpenURL(url) {
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
          }
        }))
    }
  }
}

关于如果 authorizationStatus 被拒绝,SwiftUI 将用户定向到他们的设置页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62561308/

相关文章:

ios - SwiftUI - 更新父 View 状态时如何保留 subview 的状态?

cocoa-touch - 检查当前日期字符串是否在其他两个日期范围内或之外

ios - 如何在不指定估计行高的情况下使用 iOS 自动调整单元格大小?

iphone - 防止编辑时 UITableViewCell (contentView) 缩进

ios - 多个ZStack控制zIndex

ios - 更改NavigationView标题SwiftUI的颜色

ios - UITableView单元格选择动画和NSFetchedResultsController

ios - Swift 4 - SwiftyJson 比较数组并合并找到的值

swift - 有没有办法在 RealityKit 中将 View 渲染为实体?

ios - 将 "Clear"按钮添加到 iPhone UITextField