【问题标题】:How do I open phone settings when a button is clicked?单击按钮时如何打开电话设置?
【发布时间】:2015-03-25 00:11:30
【问题描述】:

我正在尝试在应用程序中实现一项功能,该功能会在互联网连接不可用时显示警报。 警报有两个操作(确定和设置),每当用户单击设置时,我想以编程方式将它们带到手机设置。

我正在使用 Swift 和 Xcode。

【问题讨论】:

    标签: ios swift settings


    【解决方案1】:

    iOS 12+

    open(url:options:completionHandler:) 方法已更新为包含一个非零选项字典,截至本文为止,该字典仅包含 UIApplication.OpenExternalURLOptionsKey 类型的一个可能选项(在示例中)。

    @objc func openAppSpecificSettings() {
        guard let url = URL(string: UIApplication.openSettingsURLString),
            UIApplication.shared.canOpenURL(url) else {
                return
        }
        let optionsKeyDictionary = [UIApplication.OpenExternalURLOptionsKey(rawValue: "universalLinksOnly"): NSNumber(value: true)]
        
        UIApplication.shared.open(url, options: optionsKeyDictionary, completionHandler: nil)
    }
    

    显式构建 URL(例如使用“App-Prefs”)导致某些应用被商店拒绝。

    【讨论】:

    • 我确认这一点,应用程序之前使用“App-Prefs”很好,但在 Apple 的特别活动之后,我的更新被拒绝,回退到 UIApplicationOpenSettingsURLString。
    • 当我们使用 UIApplication.openSettingsURLString 时是否允许这个苹果,因为当我们打开设置应用程序时苹果拒绝了。
    【解决方案2】:

    SWIFT 5

    if let settingsUrl = URL(string: UIApplication.openSettingsURLString) {
    
       UIApplication.shared.open(settingsUrl)
    
     }
    

    在 iOS 8+ 中,您可以执行以下操作:

     func buttonClicked(sender:UIButton)
        {
            UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString))
        }
    

    斯威夫特 4

        let settingsUrl = URL(string: UIApplicationOpenSettingsURLString)!
        UIApplication.shared.open(settingsUrl)
    

    【讨论】:

    • 这会将您带到应用程序的特定设置,我如何将它们带到常规设置页面甚至更好地到健康部分?
    • 斯威夫特 3 - UIApplication.shared.openURL(URL(string: UIApplicationOpenSettingsURLString)!)
    • @AceGreen 你到健康部门了吗?
    • 如何只打开“设置”应用?它的“主页”
    • 没有“!”签到URL(string: UIApplication.openSettingsURLString).map { UIApplication.shared.open($0, options: [:], completionHandler: nil) }
    【解决方案3】:

    ⚠️小心!

    此答案基于未记录的 API,最近(自 iOS12 起)Apple 拒绝采用这种方法的应用程序。

    原答案如下

    斯威夫特 5

    UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil)
    

    斯威夫特 4

    UIApplication.shared.open(URL(string: UIApplicationOpenSettingsURLString)!, options: [:], completionHandler: nil)
    

    注意:以下方法适用于 iOS 11 以下的所有版本,更高版本的应用可能会被拒绝,因为它是私有 API

    有时我们希望将用户带到我们的应用设置以外的设置。 以下方法将帮助您实现这一目标:

    首先,在您的项目中配置 URL 方案。您将在 Target -> Info -> URL Scheme 中找到它。单击 + 按钮并在 URL Schemes 中键入首选项

    斯威夫特 5

    UIApplication.shared.open(URL(string: "App-prefs:Bluetooth")!)
    

    斯威夫特 3

    UIApplication.shared.open(URL(string:"App-Prefs:root=General")!, options: [:], completionHandler: nil)
    

    斯威夫特

    UIApplication.sharedApplication().openURL(NSURL(string:"prefs:root=General")!)
    

    Objective-C

    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=General"]];
    

    以下是所有可用的网址

    **在IOS

    • prefs:root=General&path=About
    • prefs:root=General&path=ACCESSIBILITY
    • prefs:root=AIRPLANE_MODE
    • prefs:root=General&path=AUTOLOCK
    • prefs:root=General&path=USAGE/CELLULAR_USAGE
    • prefs:root=亮度
    • prefs:root=蓝牙
    • prefs:root=General&path=DATE_AND_TIME
    • prefs:root=FACETIME
    • prefs:root=General
    • prefs:root=General&path=Keyboard
    • prefs:root=CASTLE
    • prefs:root=CASTLE&path=STORAGE_AND_BACKUP
    • prefs:root=General&path=INTERNATIONAL
    • prefs:root=LOCATION_SERVICES
    • prefs:root=ACCOUNT_SETTINGS
    • prefs:root=MUSIC
    • prefs:root=MUSIC&path=EQ
    • prefs:root=MUSIC&path=VolumeLimit
    • prefs:root=General&path=Network
    • prefs:root=NIKE_PLUS_IPOD
    • prefs:root=NOTES
    • prefs:root=NOTIFICATIONS_ID
    • prefs:root=电话
    • prefs:root=照片
    • prefs:root=General&path=ManagedConfigurationList
    • prefs:root=General&path=Reset
    • prefs:root=Sounds&path=Ringtone
    • prefs:root=Safari
    • prefs:root=General&path=Assistant
    • prefs:root=声音
    • prefs:root=General&path=SOFTWARE_UPDATE_LINK
    • prefs:root=STORE
    • prefs:root=TWITTER
    • prefs:root=FACEBOOK
    • prefs:root=General&path=USAGE prefs:root=VIDEO
    • prefs:root=General&path=Network/VPN
    • prefs:root=壁纸
    • prefs:root=WIFI
    • prefs:root=INTERNET_TETHERING
    • prefs:root=Phone&path=Blocked
    • prefs:root=DO_NOT_DISTURB

    在 IOS 13 上

    • App-prefs:General&path=About
    • 应用偏好:AIRPLANE_MODE
    • App-prefs:General&path=AUTOLOCK
    • 应用偏好:蓝牙
    • App-prefs:General&path=DATE_AND_TIME
    • 应用偏好:FACETIME
    • 应用偏好:常规
    • App-prefs:General&path=Keyboard
    • 应用偏好:CASTLE
    • 应用首选项:CASTLE&path=STORAGE_AND_BACKUP
    • App-prefs:General&path=INTERNATIONAL
    • 应用偏好:音乐
    • 应用偏好:注意事项
    • App-prefs:NOTIFICATIONS_ID
    • 应用偏好:电话
    • 应用偏好:照片
    • App-prefs:General&path=ManagedConfigurationList
    • App-prefs:General&path=Reset
    • App-prefs:Sounds&path=Ringtone
    • 应用偏好:声音
    • App-prefs:General&path=SOFTWARE_UPDATE_LINK
    • 应用偏好:STORE
    • 应用偏好:壁纸
    • 应用偏好:WIFI
    • 应用偏好:INTERNET_TETHERING
    • 应用偏好:DO_NOT_DISTURB

      未测试

    • App-prefs:TWITTER (??)

    • 应用偏好:FACEBOOK (??)
    • 应用偏好:NIKE_PLUS_IPOD (??)

    注意:网络设置不会在模拟器中打开,但链接可以在真机上使用。

    【讨论】:

    • 这不适用于 iOS 10。在 iOS 9.3 上运行相同的代码。它有效,在 iOS 10 上运行,但没有(无论使用哪个 url)
    • 对于 iOS 10,使用 App-Prefs 而不是 prefs 作为 URL 字符串的方案。例如App-Prefs:root=WIFI
    • 最近对一款应用进行审核以在 App Store 上发布它,Apple 拒绝了它,因为它使用了“prefs:root”或“App-Prefs:root”。当用户没有互联网连接时,我用它来打开 wifi 设置。
    • 由于 iOS 12 即将推出,Apple 拒绝包含此类首选项的应用程序。请注意它。甚至我的应用也被拒绝了
    • 请勿使用 App-Prefsprefs:root,因为它们是私有 API,除非您非常幸运,否则您的应用会被拒绝。
    【解决方案4】:

    使用UIApplication.openSettingsURLString

    Swift 5.1 更新

     override func viewDidAppear(_ animated: Bool) {
        let alertController = UIAlertController (title: "Title", message: "Go to Settings?", 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
                    print("Settings opened: \(success)") // Prints true
                })
            }
        }
        alertController.addAction(settingsAction)
        let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)
        alertController.addAction(cancelAction)
    
        present(alertController, animated: true, completion: nil)
    }
    

    斯威夫特 4.2

    override func viewDidAppear(_ animated: Bool) {
        let alertController = UIAlertController (title: "Title", message: "Go to Settings?", preferredStyle: .alert)
    
        let settingsAction = UIAlertAction(title: "Settings", style: .default) { (_) -> Void in
    
            guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
                return
            }
    
            if UIApplication.shared.canOpenURL(settingsUrl) {
                UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
                    print("Settings opened: \(success)") // Prints true
                })
            }
        }
        alertController.addAction(settingsAction)
        let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)
        alertController.addAction(cancelAction)
    
        present(alertController, animated: true, completion: nil)
    }
    

    【讨论】:

    • 我该如何实现? @Marius Fanu
    • 它使用 iOS8 @Marius Fanu
    • @AyoolaSolomon 我已经更新了我的答案,使用SettingsCancel 按钮在viewDidAppear 方法上添加警报
    • 不,我不这么认为。为了转到您的应用程序,您的应用程序应实现自定义 URL 方案,并从当前应用程序调用 UIApplication.sharedApplication().openURL(yourCustomURL),但您没有设置应用程序的访问权限
    • @PersianBlue 在 iOS 10.1.1 中是正确的,这无法启动设置应用程序。
    【解决方案5】:

    警告:prefs:rootApp-Prefs:root URL 方案被视为私有 API。如果您使用这些应用程序,Apple 可能会拒绝您的应用程序,这是您在提交应用程序时可能会得到的:

    您的应用使用“prefs:root=”非公共 URL 方案,这是一个私有实体。 App Store 不允许使用非公共 API,因为如果这些 API 发生变化,可能会导致糟糕的用户体验。在未来提交此应用时继续使用或隐藏非公开 API 可能会导致您的 Apple Developer 帐户被终止,以及从 App Store 中删除所有相关应用。

    接下来的步骤

    要解决此问题,请修改您的应用以使用公共 API 提供相关功能,或使用“prefs:root”或“App-Prefs:root”URL 方案删除该功能。

    如果没有其他方法可以提供您的应用所需的功能,您可以提出增强请求。

    【讨论】:

    【解决方案6】:

    SWIFT 4

    这可能需要您应用的特定设置,如果您正在寻找的话。

    UIApplication.shared.openURL(URL(string: UIApplicationOpenSettingsURLString)!)
    

    【讨论】:

    • 谢谢...我有这个工作...但我想更改其他开发人员的应用程序的设置。例如,按下一个按钮并更改 facebook 的推送通知设置,这样他们就不会在会议期间发送消息。我预测可能会有 MDM 解决方案......或没有。
    • @IrishGringo 更改 Facebook 应用程序设置的唯一方法是让用户自己打开 Facebook 应用程序的设置,方法是通过常规设置 >> 通知 >> Facebook
    【解决方案7】:

    如上所述,@niravdesai 说 App-prefs。 我发现App-Prefs: 适用于 iOS 9、10 和 11。经过测试的设备。 其中prefs: 仅适用于 iOS 9。

    【讨论】:

      【解决方案8】:

      添加到@Luca Davanzo

      iOS 11,部分权限设置已移至应用路径:

      iOS 11 支持

       static func open(_ preferenceType: PreferenceType) throws {
          var preferencePath: String
          if #available(iOS 11.0, *), preferenceType == .video || preferenceType == .locationServices || preferenceType == .photos {
              preferencePath = UIApplicationOpenSettingsURLString
          } else {
              preferencePath = "\(PreferencesExplorer.preferencePath)=\(preferenceType.rawValue)"
          }
      
          if let url = URL(string: preferencePath) {
              if #available(iOS 10.0, *) {
                  UIApplication.shared.open(url, options: [:], completionHandler: nil)
              } else {
                  UIApplication.shared.openURL(url)
              }
          } else {
              throw PreferenceExplorerError.notFound(preferencePath)
          }
      }
      

      【讨论】:

      • 这可以通过 Apple Review 吗?我的意思是,这会导致应用被拒绝吗?
      • 当我运行此代码时,我只是将我带到设置页面。不是其中的特定设置选项卡。
      【解决方案9】:

      根据@vivek 的提示,我开发了一个基于Swift 3 的utils 类,希望您能欣赏!

      import Foundation
      import UIKit
      
      public enum PreferenceType: String {
      
          case about = "General&path=About"
          case accessibility = "General&path=ACCESSIBILITY"
          case airplaneMode = "AIRPLANE_MODE"
          case autolock = "General&path=AUTOLOCK"
          case cellularUsage = "General&path=USAGE/CELLULAR_USAGE"
          case brightness = "Brightness"
          case bluetooth = "Bluetooth"
          case dateAndTime = "General&path=DATE_AND_TIME"
          case facetime = "FACETIME"
          case general = "General"
          case keyboard = "General&path=Keyboard"
          case castle = "CASTLE"
          case storageAndBackup = "CASTLE&path=STORAGE_AND_BACKUP"
          case international = "General&path=INTERNATIONAL"
          case locationServices = "LOCATION_SERVICES"
          case accountSettings = "ACCOUNT_SETTINGS"
          case music = "MUSIC"
          case equalizer = "MUSIC&path=EQ"
          case volumeLimit = "MUSIC&path=VolumeLimit"
          case network = "General&path=Network"
          case nikePlusIPod = "NIKE_PLUS_IPOD"
          case notes = "NOTES"
          case notificationsId = "NOTIFICATIONS_ID"
          case phone = "Phone"
          case photos = "Photos"
          case managedConfigurationList = "General&path=ManagedConfigurationList"
          case reset = "General&path=Reset"
          case ringtone = "Sounds&path=Ringtone"
          case safari = "Safari"
          case assistant = "General&path=Assistant"
          case sounds = "Sounds"
          case softwareUpdateLink = "General&path=SOFTWARE_UPDATE_LINK"
          case store = "STORE"
          case twitter = "TWITTER"
          case facebook = "FACEBOOK"
          case usage = "General&path=USAGE"
          case video = "VIDEO"
          case vpn = "General&path=Network/VPN"
          case wallpaper = "Wallpaper"
          case wifi = "WIFI"
          case tethering = "INTERNET_TETHERING"
          case blocked = "Phone&path=Blocked"
          case doNotDisturb = "DO_NOT_DISTURB"
      
      }
      

      enum PreferenceExplorerError: Error {
          case notFound(String)
      }
      
      open class PreferencesExplorer {
      
          // MARK: - Class properties -
      
          static private let preferencePath = "App-Prefs:root"
      
          // MARK: - Class methods -
      
          static func open(_ preferenceType: PreferenceType) throws {
              let appPath = "\(PreferencesExplorer.preferencePath)=\(preferenceType.rawValue)"
              if let url = URL(string: appPath) {
                  if #available(iOS 10.0, *) {
                      UIApplication.shared.open(url, options: [:], completionHandler: nil)
                  } else {
                     UIApplication.shared.openURL(url)
                  }
              } else {
                  throw PreferenceExplorerError.notFound(appPath)
              }
          }
      
      }
      

      这非常有用,因为 API 肯定会发生变化,而且您可以非常快速地重构一次!

      【讨论】:

      • 这会通过苹果审查吗?
      • 我要再添加一件事让它稍微好一点。在枚举中,您可以使用名称 urlString 创建一个 String 类型的变量。然后返回 "App-Prefs:root=" = self.rawValue。这将基本上消除对 appPath 和静态私有 let 的需要。干杯。
      • 通知设置未在 iOS 11 上打开。
      • 这将不起作用,因为我们从应用程序收到此消息:“您的应用程序使用“prefs:root=”非公共 URL 方案,这是一个私有实体。使用非公共 API不允许在 App Store 上使用,因为如果这些 API 发生更改,可能会导致糟糕的用户体验。在未来提交此应用程序时继续使用或隐藏非公共 API 可能会导致您的 Apple Developer 帐户被终止,以及从 App Store 中删除所有关联的应用程序。”
      • @L_Sonic 不,它不会通过审核,如果通过了,它可能会在您推送的任何未来更新中被随机标记
      【解决方案10】:

      App-Prefs:root=Privacy&path=LOCATION 为我提供了一般位置设置。注意:仅适用于设备。

      【讨论】:

      • 这被拒绝了
      【解决方案11】:

      App-Specific URL Schemes 的第一个回复在 iOS 10.3 上为我工作。

      if let appSettings = URL(string: UIApplicationOpenSettingsURLString + Bundle.main.bundleIdentifier!) {
          if UIApplication.shared.canOpenURL(appSettings) {
            UIApplication.shared.open(appSettings)
          }
        }
      

      【讨论】:

      • 这应该打开什么?
      【解决方案12】:

      我看过这行代码

      UIApplication.sharedApplication() .openURL(NSURL(string:"prefs:root=General")!)
      

      不起作用,在 ios10/Xcode 8 中对我不起作用,只是代码略有不同,请替换为

      UIApplication.sharedApplication().openURL(NSURL(string:"App-Prefs:root=General")!)
      

      Swift3

      UIApplication.shared.openURL(URL(string:"prefs:root=General")!)
      

      替换为

      UIApplication.shared.openURL(URL(string:"App-Prefs:root=General")!)
      

      希望对您有所帮助。 干杯。

      【讨论】:

      • 原因:应用被拒绝
      【解决方案13】:

      在 ios10/Xcode 8 模拟器中:

      UIApplication.shared.openURL(URL(string:UIApplicationOpenSettingsURLString)!)
      

      作品

      UIApplication.shared.openURL(URL(string:"prefs:root=General")!)
      

      没有。

      【讨论】:

      • iOS 10 中的 NS 前缀是否已被移除?
      • 这只有在你的应用有 .bundle 文件(你的应用偏好)时才有效
      • @Sophy Swicz 如何添加 .bundle 文件?
      • @Developer github.com/phynet/SettingBundleiOSProject 同样,您的应用设置是您的应用允许使用的所有服务,并显示在应用的常规 -> 设置中
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多