76
votes

I need to open Settings programmatically from within my app. I searched across SO but everywhere people say that it's impossible. But today I saw that it's implemented in Facebook app. There's a button on an UIAlertView and when you click it you open the Settings. So indeed this is possible to open Settings, I have witnessed this myself. But how to do that? Does anyone know how Facebook does that?

15
Note that Facebook Application is open source and completely available on github. - Sulthan
Facebook didn't show this alert, the OS did it. It happens in certain circumstances such as Airplane Mode being turned on or WiFi being turned off, and the OS offers for you to open Settings and change it. - Guy Kogus
@Sulthanthe note that the Facebook Application is not open source. Only the SDK is. - MatterGoal
Visit this answer for Swift 3: http://stackoverflow.com/a/34024467/5391914 - Hamed

15 Answers

140
votes

On iOS 8 you can open Settings programmatically!

Here is the code:

- (void)openSettings
{
    BOOL canOpenSettings = (&UIApplicationOpenSettingsURLString != NULL);
    if (canOpenSettings) {
        NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
        [[UIApplication sharedApplication] openURL:url];
    }
}

If your app has it’s own settings bundle, the settings will be opened showing your app’s settings. If your app does not have a setting bundle, the main settings page will be shown.

57
votes

You can't, there is no API call to do this.

Only system dialogs, dialogs from Apple Frameworks, can open the settings app. In iOS 5 there was a app url scheme to open the system dialog but Apple removed it later.


With the coming of iOS 8 you can open the settings dialog on your apps page.

if (&UIApplicationOpenSettingsURLString != NULL) {
   NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
    [[UIApplication sharedApplication] openURL:url];
}
else {
  // Present some dialog telling the user to open the settings app.
}
33
votes

On iOS 8 you can open Settings programmatically!

Here is the list of currently known URLs in the Settings app:

- (void) openSettings
{
if (&UIApplicationOpenSettingsURLString != nil)
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
else
    NSLog(@"UIApplicationOpenSettingsURLString is not available in current iOS version");
}    
  • 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=Brightness
  • prefs:root=General&path=Bluetooth
  • 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=Phone
  • prefs:root=Photos
  • 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=Sounds
  • prefs:root=General&path=SOFTWARE_UPDATE_LINK
  • prefs:root=STORE
  • prefs:root=TWITTER
  • prefs:root=General&path=USAGE
  • prefs:root=VIDEO
  • prefs:root=General&path=Network/VPN
  • prefs:root=Wallpaper
  • prefs:root=WIFI
  • prefs:root=INTERNET_TETHERING
20
votes

Vito Ziv's answer in Swift.

func openSettings() {
    UIApplication.shared.open(URL(string: UIApplicationOpenSettingsURLString)!, completionHandler: nil)

}
13
votes

The alert in the Facebook app that this question refers to is a standard alert which iOS displays itself when you set UIRequiresPersistentWiFi to YES in your Info.plist files and the user launches your app without a network connection.

To summarize the discussion here:

  • There is no URL you can use to get to the root level of the Settings app.
  • You can send the user to your app's section of the Settings app using UIApplicationOpenSettingsURLString in iOS 8.
  • Your app can display the same alert as Facebook, which does open the root level of the Settings app, by setting UIRequiresPersistentWiFi to YES.
11
votes

A memo about prefs:root= and Prefs:root.

Yes, our App was REJECTED by Apple due to prefs:root= and App-Prefs:root URL scheme today (2018-06-29). They are private API.

Rejected by Apple


For Swift 4,

Only UIApplication.openSettingsURLString is public API to open Settings.

7
votes
 if (&UIApplicationOpenSettingsURLString != NULL)

in iOS 8+ is always TRUE. So you can edit like this

NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];

if ([[UIApplication sharedApplication] canOpenURL:url]) {
    [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
}

(with new openURL for iOS 10)

5
votes

If you want open application settings you need write method with UIApplicationOpenSettingsURLString.

fileprivate func openSettings() {
  UIApplication.shared.open(URL(string: UIApplicationOpenSettingsURLString)!)      
}

If you need will open one of many settings, you need use this function

fileprivate func openSettings() {
  UIApplication.shared.open(URL(string:"App-Prefs:root=General")!)
}
3
votes

To open settings of our own application in iOS 8 and later, use following code.

- (void) openSettings
{
    if(&UIApplicationOpenSettingsURLString != nil)
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
    else
        NSLog(@"UIApplicationOpenSettingsURLString is not available in current iOS version");
}

For reference and detailed description please follow

Opening the Settings app programmatically in iOS 8

2
votes
 if (&UIApplicationOpenSettingsURLString != NULL) {
            UIAlertView_Blocks *alertView = [[UIAlertView_Blocks alloc] initWithTitle:NSLocalizedString(@"Camera Access Denied", nil)
                                                                              message:NSLocalizedString(@"You must allow camera access in Settings", nil)
                                                                             delegate:nil
                                                                    cancelButtonTitle:NSLocalizedString(@"Cancel", nil)
                                                                    otherButtonTitles:NSLocalizedString(@"Open Settings", nil), nil];
            [alertView showWithDissmissBlock:^(NSInteger buttonIndex) {
                if (alertView.cancelButtonIndex != buttonIndex) {
                    NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
                    [[UIApplication sharedApplication] openURL:url];
                }
            }];
        }
        else {
            UIAlertView_Blocks *alertView = [[UIAlertView_Blocks alloc] initWithTitle:NSLocalizedString(@"Camera Access Denied", nil)
                                                                              message:NSLocalizedString(@"You must allow camera access in Settings > Privacy > Camera", nil)
                                                                             delegate:nil
                                                                    cancelButtonTitle:NSLocalizedString(@"OK", nil)
                                                                    otherButtonTitles:nil, nil];
            [alertView showWithDissmissBlock:^(NSInteger buttonIndex) {
            }];
        }
1
votes

Here is a Swift 3 example with UIAlertController and UIAlertAction.

func showSettingsPopup() {
    let alertVC = UIAlertController(title: "Notifications disabled", message: "Please, turn on notifications if you want to receive a reminder messages.", preferredStyle: .alert)

    let close = UIAlertAction(title: "Close", style: .destructive, handler: { (action) in
        print("close action handler")                
    })

    let openSettings = UIAlertAction(title: "Open settings", style: .default, handler: { (action) in
        guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
            return
        }

        if UIApplication.shared.canOpenURL(settingsUrl) {
            UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
                print("Settings are opened: \(success)")
            })
        }
    })

    alertVC.addAction(openSettings)
    alertVC.addAction(close)
    present(alertVC, animated: true, completion: nil)
}
1
votes

In many of the answers given here I see the use of "App-Prefs:root" "prefs:root" we should not use these in our apps to open settings app. As per Apple this is a non-public url scheme and if we use it our app will get rejected.

0
votes
if #available(iOS 10.0, *) {
        if let url = URL(string: "App-Prefs:root=Privacy") {
            UIApplication.shared.open(url, completionHandler: .none)
        }
    } else {
        // Fallback on earlier versions
    }

Opening Privacy settings in App

0
votes

Instead of using prefs:, just use App-Prefs:

if ([[UIApplication sharedApplication] canOpenURL: [NSURL URLWithString: @"App-Prefs:root=WIFI"]]) {
    [[UIApplication sharedApplication] openURL: [NSURL URLWithString:@"App-Prefs:root=WIFI"]];
}

.

Everything is here: https://medium.com/@thanhvtrn/how-to-open-settings-wifi-in-swift-on-ios-10-1d94cf2c2e60

-1
votes

SWIFT 3

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