Open settings directly from your app
Posted: | Author: Jörn | Filed under: iOS | Tags: iOS8, Settings | 5 Comments »Once upon a time it was possible to go to the settings right from your app using:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs://"]];
That was quite useful when some feature in your app could not be used, because the user disabled something in his settings. In that case you could inform the user that he had to change his settings if he wanted to use that feature and offer to open the settings directly from your app.
Unfortunately Apple decided to not longer allow this after the introduction of iOS 5.1
Good news: This feature is back with iOS8! Apple has added a NSString constant to UIKit that you are supposed to use. To avoid crashes on iOS versions below iOS8 it is a good idea to check if the constant exists on the system version the device is running. You could check if the user is running iOS8 or higher but I prefer to check directly if the constant exits rather than checking the iOS version. Who knows if Apple will decide to remove this constant again in the future…
So, to open the settings, you can use the following snippet:
BOOL canOpenSettings = (&UIApplicationOpenSettingsURLString != NULL);
if (canOpenSettings) {
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
[[UIApplication sharedApplication] openURL:url];
}
Swift:
if let settingsURL = NSURL(string: UIApplicationOpenSettingsURLString) {
UIApplication.sharedApplication().openURL(settingsURL)
}
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.
Unfortunately there does not seem to be a way to go directly to subpages of the settings (except your own settings bundle). If you’ve found a way to do that, please let me know in the comments!
Update: Linking to a subpage of the Setting seems to work again for system versions greater or equal than iOS8. It is not officially documented by Apple but it seems to work, although I not sure how reliable this is. It works on my iOS 9.1 iPhone but not in the Simulator. So I would not recommend to use this in production.
So, with caution, you can try this to open the Keyboard Settings:
if let settingsURL = NSURL(string: "prefs:root=General&path=Keyboard") {
UIApplication.sharedApplication().openURL(settingsURL)
}
Or go even one level deeper:
if let settingsURL = NSURL(string: "prefs:root=General&path=Keyboard/KEYBOARDS") {
UIApplication.sharedApplication().openURL(settingsURL)
}
To make these unofficial URLs work you might have to add prefs to the URL schemes of your project’s Info.plist file.
1
Garysaid atHi there,
I’ve been trying to use
BOOL canOpenSettings = (&UIApplicationOpenSettingsURLString != NULL);
if (canOpenSettings) {
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
[[UIApplication sharedApplication] openURL:url];
}
on my iPhone 6 with iOS 9.0 and calling this really doesn’t take me to settings page. It rather navigates to Safari.
Any idea, how I can solve this?
2
Jörnsaid atHi Gary,
sorry for the late reply. I just tested the code on my iPhone 6s (iOS9.1) and it opens the Settings. Have you logged the value of UIApplicationOpenSettingsURLString? It should be “app-settings:”. You could also try the direct “prefs:” links to see if they are working. See my update of the blog post above.
3
Jörnsaid atHi Gary,
I might have found a solution for you: Try adding `prefs` to the URL schemes of your project’s Info.plist file.
4
Wang Risaid atI added prefs scheme on my app, and did try following code.
BOOL canOpenSettings = (UIApplicationOpenSettingsURLString != NULL);
if (canOpenSettings) {
NSURL *url = [NSURL URLWithString:@”prefs:root=General&path=Keyboard/KEYBOARDS”];
[[UIApplication sharedApplication] openURL:url];
} else {
NSLog(@”impossible to open keyboard setting page!”);
}
It is working on iphone 5, but not on iphone6.
Have you any idea?
My current ios version is iOS 9.2
Thanks.
5
Jörnsaid atHi Wang,
I just tried your code and it works fine on my iPhone 6s (iOS 9.2). I am afraid the problem lies somewhere else.