Apple maps route request URL from current location - ios

I'm now thinking about an app for iOS, which could send an SMS to other people (without Internet connection) with a URL link to give them offline direction to my location in native maps app when they tap the link.
I know it can be done with this kind of URL:
http://maps.apple.com/maps?saddr=<their location>&daddr=<my location, filled by my app>
Of course I could leave saddr blank and let them pick their current location from the autocomplete list for start point, but it's gonna take them 1 more step to get the direction. I just want to make sure to give them the most convenient way.
How to guide the native maps app to automatically get SMS receiver user's current location by this URL? I need some thing like this:
http://maps.apple.com/maps?saddr=current_location&daddr=<my location, filled by my app>
I also want to send this link to other platform user, like with Android user I could use:
http://maps.google.com/maps?saddr=current_location&daddr=<my location, filled by my app>
Windows Phone (I haven't known yet):
http://maps.???.com/maps?saddr=current_location&daddr=<my location, filled by my app>
Any keyword or answer will be very appreciated!

You were pretty close!
Apple Maps:
http://maps.apple.com/maps?saddr=Current%20Location&daddr=<Your Location>
Google Maps:
comgooglemaps-x-callback://?saddr=&daddr=<Your Location>

If you are using objective-c:
NSString *urlString = [NSString stringWithFormat:#"maps.apple.com/maps?saddr=&daddr=%#,%#",destinationLatitude,destinationLongitude];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
If you are using swift 2.2:
var string = "http://maps.apple.com/?saddr=&daddr=\(destinationLatitude),\(destinationLongitude)"
UIApplication.sharedApplication().openURL(NSURL(string: string)!)
If you are using swift 3.0:
var string = "http://maps.apple.com/?saddr=&daddr=\(destinationLatitude),\(destinationLongitude)"
UIApplication.shared.openURL(URL(string: string)!)

in My Case Best Way To Connect inside Chat :
let OptionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let GoogleMap = UIAlertAction(title: "Open Google Map".localized, style: .default) { (alert) in
if let url = URL(string: "comgooglemaps://?saddr=&daddr=\(Lat),\(Lng)&directionsmode=driving"),
UIApplication.shared.canOpenURL(url) {
print("comgoogle maps worked")
if #available(iOS 10, *) {
UIApplication.shared.open(url, options: [:], completionHandler:nil)
} else {
UIApplication.shared.openURL(url)
}
}
}
let OpenMaps = UIAlertAction(title: "Open Maps".localized, style: .default) { (alert) in
if let url = URL(string: "http://maps.apple.com/?saddr=&daddr=\(Lat),\(Lng)"),
UIApplication.shared.canOpenURL(url) {
print("Maps maps worked")
if #available(iOS 10, *) {
UIApplication.shared.open(url, options: [:], completionHandler:nil)
} else {
UIApplication.shared.openURL(url)
}
}
}
OptionMenu.addAction(UIAlertAction(title: "Cancel".localized, style: .cancel, handler: nil))
OptionMenu.addAction(GoogleMap)
OptionMenu.addAction(OpenMaps)
self.present(OptionMenu, animated: true, completion: nil)

Related

Add variable to URL in swift

I am currently developing an app in Xcode with Swift. The general premise of the app is that when the app first loads, the user will be asked to enter a 'mobile linking code' this will essentially be added onto the end of the url as a variable which will serve as their login to the site, the rest of the authentication is done server side. Then when the user logs into the app each time after that, this variable will be auto applied to the URL so that essentially they are always auto logged in.
I have my code setup for the app and the UIAlertController loads with a text field, I am struggling on how to find out how to append the 'mobile linking code' (which the user will type into the text field) to the end of the URL on first load and then also how to append this to the URL that loads each time after that.
The code I have is as follows
At the top of my WebViewController.swift
var webviewurl = "https://mywebsite.co.uk/loginarea.php?link=" (I need to append the mobile link code to the end of that url)
Further down in my code I have my first run dialog, in which I have added a UIAlertController. This will be ran on the very first time opening the app only in which the user will input their 'mobile link code', upon clicking Submit, the webview should be redirected to the url with the data in the text field appended to the end.
if activatefirstrundialog == "true" {
if !user.bool(forKey: "firstrun")
{
user.set("1", forKey: "firstrun")
user.synchronize()
webView.stopLoading()
let ac = UIAlertController(title: "Enter Mobile Link Code", message: "Enter the mobile link code found in your Client Area", preferredStyle: .alert)
ac.addTextField()
let submitAction = UIAlertAction(title: "Submit", style: .default) { [unowned ac] _ in
let answer = ac.textFields![0]
// do something interesting with "answer" here
let url = URL(string: "https://mywebsite.co.uk/loginarea.php?link=")!
self.webView.load(URLRequest(url: url + answer))
}
ac.addAction(submitAction)
present(ac, animated: true)
}
}
}
I would be eternally grateful if someone could help me with this.
TIA
To use the mobileLink between multiple app sessions, you need to save it somewhere after it is entered for the first time by the user.
Let's say we save it in UserDefaults. You can then fetch its value accordingly like so,
if !user.bool(forKey: "firstrun") {
//your code...
let submitAction = UIAlertAction(title: "Submit", style: .default) { [unowned ac] _ in
if let answer = ac.textFields.first?.text {
UserDefaults.standard.set(answer, forKey: "mobileLink")
let url = URL(string: "https://mywebsite.co.uk/loginarea.php?link=\(answer)")!
self.webView.load(URLRequest(url: url))
}
}
//your code...
} else if let mobileLink = UserDefaults.standard.string(forKey: "mobileLink") {
let url = URL(string: "https://mywebsite.co.uk/loginarea.php?link=\(mobileLink)")!
self.webView.load(URLRequest(url: url))
}
Did you mean something like this?
let submitAction = UIAlertAction(title: "Submit", style: .default) { [unowned ac] _ in
let answer = ac.textFields![0]
// do something interesting with "answer" here
if let answerText = answer.text, answerText.count > 0 {
if let percentageEncodedString = "https://mywebsite.co.uk/loginarea.php?link=\(answerText)".addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) {
if let url = URL(string:percentageEncodedString) {
self.webView.load(URLRequest(url: url))
} else {
//Handle error here, url is not valid
}
} else {
//Handle error here, url cannot be encoded
}
} else {
//Handle error here, text field's text is nil or text is empty
}
}
You should store this mobile linking code somewhere safe. you can use keychain to store it.
To answer your question, you can concatenate the string and form a URL Like this:
let url = URL(string: "https://mywebsite.co.uk/loginarea.php?link=\(answer)")!
Here answer is a variable.

Opening app's notification settings in the settings app

In the case that a user may accidentally declines to receive notifications and wants to turn notifications later, how can I use an NSURL to open the IOS Settings App to my app's notification page where they can select Allow Notifications?
Updated 8 Dec, 2021:
This method will open Settings > Your App. It will show all available privacy toggles like camera, photos, notifications, cellular data, etc.
After a comment from #Mischa below, tested and updated the answer to this (more succinct):
if let appSettings = URL(string: UIApplication.openSettingsURLString), UIApplication.shared.canOpenURL(appSettings) {
UIApplication.shared.open(appSettings)
}
Previous answer:
I found the answer to this question (albeit helpful) has a bit too much assumed logic. Here is a plain and simple Swift 5 implementation if anyone else stumbles upon this question:
if let bundleIdentifier = Bundle.main.bundleIdentifier, let appSettings = URL(string: UIApplication.openSettingsURLString + bundleIdentifier) {
if UIApplication.shared.canOpenURL(appSettings) {
UIApplication.shared.open(appSettings)
}
}
For Swift 3, use UIApplicationOpenSettingsURLString to go to settings for your app where it shows the Notifications status and "Cellular Data"
let settingsButton = NSLocalizedString("Settings", comment: "")
let cancelButton = NSLocalizedString("Cancel", comment: "")
let message = NSLocalizedString("Your need to give a permission from notification settings.", comment: "")
let goToSettingsAlert = UIAlertController(title: "", message: message, preferredStyle: UIAlertControllerStyle.alert)
goToSettingsAlert.addAction(UIAlertAction(title: settingsButton, style: .destructive, handler: { (action: UIAlertAction) in
DispatchQueue.main.async {
guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
return
}
if UIApplication.shared.canOpenURL(settingsUrl) {
if #available(iOS 10.0, *) {
UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
print("Settings opened: \(success)") // Prints true
})
} else {
UIApplication.shared.openURL(settingsUrl as URL)
}
}
}
}))
logoutUserAlert.addAction(UIAlertAction(title: cancelButton, style: .cancel, handler: nil))
Swift 5:
if let url = URL(string: UIApplication.openSettingsURLString) {
UIApplication.shared.open(url)
}
This should keep you covered for all iOS versions, including iOS 15 and iOS 16.
extension UIApplication {
private static let notificationSettingsURLString: String? = {
if #available(iOS 16, *) {
return UIApplication.openNotificationSettingsURLString
}
if #available(iOS 15.4, *) {
return UIApplicationOpenNotificationSettingsURLString
}
if #available(iOS 8.0, *) {
// just opens settings
return UIApplication.openSettingsURLString
}
// lol bruh
return nil
}()
private static let appNotificationSettingsURL = URL(
string: notificationSettingsURLString ?? ""
)
func openAppNotificationSettings() -> Bool {
guard
let url = UIApplication.appNotificationSettingsURL,
self.canOpen(url) else { return false }
return self.open(url)
}
}
Usage:
Button {
let opened = UIApplication.shared.openAppNotificationSettings()
if !opened {
print("lol fail")
}
} label: {
Text("Notifications")
}
UPDATE: This will be rejected by Apple.
To open notifications part of settings use this
UIApplication.shared.open(URL(string:"App-Prefs:root=NOTIFICATIONS_ID")!, options: [:], completionHandler: nil)
Since iOS 15.4 we can deeplink to the notif settings screen directly using UIApplicationOpenNotificationSettingsURLString:
https://developer.apple.com/documentation/uikit/uiapplicationopennotificationsettingsurlstring?language=objc

OpenURL in iOS10

So apparently OpenURL has been deprecated in iOS 10. Does anyone have any documentation on why or can explain what to do next? I looked on the Apple site already and found a few things pertaining to OpenURL and this is what they say to use now:
UIApplication.shared().open(url: URL, options: [String: AnyObject], completionHandler: ((Bool) -> Void)?)
Does anyone have any evidence that this is the new way to use OpenURL in Swift 3.0? In addition what values are to be used in the options: and completionHandler: parameters respectively?
Swift 3+:
func open(scheme: String) {
if let url = URL(string: scheme) {
if #available(iOS 10, *) {
UIApplication.shared.open(url, options: [:],
completionHandler: {
(success) in
print("Open \(scheme): \(success)")
})
} else {
let success = UIApplication.shared.openURL(url)
print("Open \(scheme): \(success)")
}
}
}
Usage:
open(scheme: "tweetbot://timeline")
Source
A quick fix:
// Objective-C
UIApplication *application = [UIApplication sharedApplication];
[application openURL:URL options:#{} completionHandler:nil];
// Swift
UIApplication.shared.open(url, options: [:], completionHandler: nil)
A complete answer:
http://useyourloaf.com/blog/openurl-deprecated-in-ios10/
Credits: Keith Harrison (useyourloaf.com)
An empty options dictionary will result in the same behaviour as openUrl.
Otherwise:
+-------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+
| UIApplicationOpenURLOptionsSourceApplicationKey | NSString containing the bundle ID of the originating application |
+-------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+
| UIApplicationOpenURLOptionsAnnotationKey | property-list typed object corresponding to what the originating application passed in UIDocumentInteractionController's annotation property |
+-------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+
| UIApplicationOpenURLOptionsOpenInPlaceKey | bool NSNumber, set to YES if the file needs to be copied before use |
+-------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+
From UIApplication.h
// Options are specified in the section below for openURL options. An empty options dictionary will result in the same
// behavior as the older openURL call, aside from the fact that this is asynchronous and calls the completion handler rather
// than returning a result.
// The completion handler is called on the main queue.
- (void)openURL:(NSURL*)url options:(NSDictionary<NSString *, id> *)options completionHandler:(void (^ __nullable)(BOOL success))completion NS_AVAILABLE_IOS(10_0) NS_EXTENSION_UNAVAILABLE_IOS("");
UIKIT_EXTERN UIApplicationOpenURLOptionsKey const UIApplicationOpenURLOptionsSourceApplicationKey NS_SWIFT_NAME(sourceApplication) NS_AVAILABLE_IOS(9_0); // value is an NSString containing the bundle ID of the originating application
UIKIT_EXTERN UIApplicationOpenURLOptionsKey const UIApplicationOpenURLOptionsAnnotationKey NS_SWIFT_NAME(annotation) NS_AVAILABLE_IOS(9_0); // value is a property-list typed object corresponding to what the originating application passed in UIDocumentInteractionController's annotation property
UIKIT_EXTERN UIApplicationOpenURLOptionsKey const UIApplicationOpenURLOptionsOpenInPlaceKey NS_SWIFT_NAME(openInPlace) NS_AVAILABLE_IOS(9_0); // value is a bool NSNumber, set to YES if the file needs to be copied before use
The new UIApplication method openURL:options:completionHandler:, which is executed asynchronously and calls the specified completion handler on the main queue (this method replaces openURL:).
This is under Additional Framework Changes > UIKit at: https://developer.apple.com/library/prerelease/content/releasenotes/General/WhatsNewIniOS/Articles/iOS10.html
You need to do some checking first before loading the url. Please check the codes below.
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:#"https://www.gmail.com"]]){
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"https://www.gmail.com"] options:#{} completionHandler:^(BOOL success) {
//completion codes here
}];
}
I hope this helps.
If your app still support iOS 9 or lower, just keep using the old openURL. You should only move to the new one if your Deployment Target is iOS 10.
let actual:
[String: AnyObject] = ["xxx key": "xxx value" as AnyObject, "yyy key": "yyy value" as AnyObject]
UIApplication.shared.open(URL(string: "http:google.com")!, options: actual, completionHandler: {(true) -> Swift.Void in
print("Refresh")
})
Where xxx and yyy are any string you want to print or leave them blank .
you can use function to open settings:
func showAlert(title:String, message:String){
let alert = UIAlertController(title: title,
message: message,
preferredStyle: UIAlertController.Style.alert)
let okAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alert.addAction(okAction)
let settingsAction = UIAlertAction(title: "Settings", style: .default, handler: { _ in
// Take the user to Settings app to possibly change permission.
guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else { return }
if UIApplication.shared.canOpenURL(settingsUrl) {
if #available(iOS 10.0, *) {
UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
// Finished opening URL
})
} else {
// Fallback on earlier versions
UIApplication.shared.openURL(settingsUrl)
}
}
})
alert.addAction(settingsAction)
present(alert, animated: true, completion: nil)
}
Call this function like this given below
showAlert(title: "Unable to access the Photos", message: "To enable access, go to Settings > Privacy > Photos and turn on Photos access for this app.")

How do I open phone settings when a button is clicked?

I am trying to implement a feature in an App that shows an alert when the internet connection is not available.
The alert has two actions (OK and Settings), whenever a user clicks on settings, I want to take them to the phone settings programmatically.
I am using Swift and Xcode.
Using UIApplication.openSettingsURLString
Update for 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)
}
Swift 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)
}
⚠️ Be careful!
This answer is based on undocumented APIs and recently (since iOS12) Apple is rejecting apps with this approach.
Original answer below
Swift 5
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil)
Swift 4
UIApplication.shared.open(URL(string: UIApplicationOpenSettingsURLString)!, options: [:], completionHandler: nil)
NOTE: The following method works for all the versions below iOS 11, for higher versions the app might get rejected since it's a private API
Sometimes we want to take a user to settings other than our app settings.
The following method will help you achieve that:
First, configure the URL Schemes in your project. You will find it in Target -> Info -> URL Scheme. click on + button and type prefs in URL Schemes
Swift 5
UIApplication.shared.open(URL(string: "App-prefs:Bluetooth")!)
Swift 3
UIApplication.shared.open(URL(string:"App-Prefs:root=General")!, options: [:], completionHandler: nil)
Swift
UIApplication.sharedApplication().openURL(NSURL(string:"prefs:root=General")!)
Objective-C
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"prefs:root=General"]];
and following are all the available URLs
**On IOS < 12 **
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=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=FACEBOOK
prefs:root=General&path=USAGE prefs:root=VIDEO
prefs:root=General&path=Network/VPN
prefs:root=Wallpaper
prefs:root=WIFI
prefs:root=INTERNET_TETHERING
prefs:root=Phone&path=Blocked
prefs:root=DO_NOT_DISTURB
On IOS 13
App-prefs:General&path=About
App-prefs:AIRPLANE_MODE
App-prefs:General&path=AUTOLOCK
App-prefs:Bluetooth
App-prefs:General&path=DATE_AND_TIME
App-prefs:FACETIME
App-prefs:General
App-prefs:General&path=Keyboard
App-prefs:CASTLE
App-prefs:CASTLE&path=STORAGE_AND_BACKUP
App-prefs:General&path=INTERNATIONAL
App-prefs:MUSIC
App-prefs:NOTES
App-prefs:NOTIFICATIONS_ID
App-prefs:Phone
App-prefs:Photos
App-prefs:General&path=ManagedConfigurationList
App-prefs:General&path=Reset
App-prefs:Sounds&path=Ringtone
App-prefs:Sounds
App-prefs:General&path=SOFTWARE_UPDATE_LINK
App-prefs:STORE
App-prefs:Wallpaper
App-prefs:WIFI
App-prefs:INTERNET_TETHERING
App-prefs:DO_NOT_DISTURB
Not tested
App-prefs:TWITTER (??)
App-prefs:FACEBOOK (??)
App-prefs:NIKE_PLUS_IPOD (??)
Note: Network setting will not be opened in a simulator, but the link will work on a real device.
SWIFT 5
if let settingsUrl = URL(string: UIApplication.openSettingsURLString) {
UIApplication.shared.open(settingsUrl)
}
In iOS 8+ you can do the following:
func buttonClicked(sender:UIButton)
{
UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString))
}
Swift 4
let settingsUrl = URL(string: UIApplicationOpenSettingsURLString)!
UIApplication.shared.open(settingsUrl)
Using #vivek's hint I develop an utils class based on Swift 3, hope you appreciate!
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)
}
}
}
This is very helpful since that API's will change for sure and you can refactor once and very fast!
The first response from App-Specific URL Schemes worked for me on iOS 10.3.
if let appSettings = URL(string: UIApplicationOpenSettingsURLString + Bundle.main.bundleIdentifier!) {
if UIApplication.shared.canOpenURL(appSettings) {
UIApplication.shared.open(appSettings)
}
}
App-Prefs:root=Privacy&path=LOCATION worked for me for getting to general location settings. Note: only works on a device.
iOS 12+
The open(url:options:completionHandler:) method has been updated to include a non-nil options dictionary, which as of this post only contains one possible option of type UIApplication.OpenExternalURLOptionsKey (in the example).
#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)
}
Explicitly constructing a URL, such as with "App-Prefs", has gotten some apps rejected from the store.
word of warning: the prefs:root or App-Prefs:root URL schemes are considered private API. Apple may reject you app if you use those, here is what you may get when submitting your app:
Your app uses the "prefs:root=" non-public URL scheme, which is a private entity. The use of non-public APIs is not permitted on the App Store because it can lead to a poor user experience should these APIs change. Continuing to use or conceal non-public APIs in future submissions of this app may result in the termination of your Apple Developer account, as well as removal of all associated apps from the App Store.
Next Steps
To resolve this issue, please revise your app to provide the associated functionality using public APIs or remove the functionality using the "prefs:root" or "App-Prefs:root" URL scheme.
If there are no alternatives for providing the functionality your app requires, you can file an enhancement request.
in ios10/ Xcode 8 in simulator:
UIApplication.shared.openURL(URL(string:UIApplicationOpenSettingsURLString)!)
works
UIApplication.shared.openURL(URL(string:"prefs:root=General")!)
does not.
I have seen this line of code
UIApplication.sharedApplication() .openURL(NSURL(string:"prefs:root=General")!)
is not working, it didn't work for me in ios10/ Xcode 8, just a small code difference, please replace this with
UIApplication.sharedApplication().openURL(NSURL(string:"App-Prefs:root=General")!)
Swift3
UIApplication.shared.openURL(URL(string:"prefs:root=General")!)
Replace with
UIApplication.shared.openURL(URL(string:"App-Prefs:root=General")!)
Hope it helps.
Cheers.
Adding to #Luca Davanzo
iOS 11, some permissions settings have moved to the app path:
iOS 11 Support
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)
}
}
SWIFT 4
This could take your app's specific settings, if that's what you're looking for.
UIApplication.shared.openURL(URL(string: UIApplicationOpenSettingsURLString)!)
As above #niravdesai said App-prefs.
I found that App-Prefs: works for both iOS 9, 10 and 11. devices tested.
where as prefs: only works on iOS 9.
UIApplication.open(_:options:completionHandler:) must be used from main thread only
Solution:
if let appSettings = URL(string: UIApplication.openSettingsURLString + Bundle.main.bundleIdentifier!) {
if UIApplication.shared.canOpenURL(appSettings) {
DispatchQueue.main.async {
UIApplication.shared.open(appSettings)
}
}
}

How can I add a link for a rate button with swift?

First I don't know how to get the link before I submit my app, and if the link is for each country app store or is it universal?
Also I don't know if the way to do it is just by putting the link there like:
#IBAction func rate(sender: AnyObject) {
UIApplication.sharedApplication().openURL(NSURL(string : "webLinkHere")!)
}
Or should I use another way to do this?
Thanks
Try This, change appId in your method by your App ID
Swift 5
import StoreKit
func rateApp() {
if #available(iOS 10.3, *) {
SKStoreReviewController.requestReview()
} else if let url = URL(string: "itms-apps://itunes.apple.com/app/" + "appId") {
if #available(iOS 10, *) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(url)
}
}
}
Swift 3 \ 4
func rateApp() {
guard let url = URL(string: "itms-apps://itunes.apple.com/app/" + "appId") else {
return
}
if #available(iOS 10, *) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(url)
}
}
id959379869 This is the id when you go on your Itune page of your app
Example :
https://itunes.apple.com/fr/app/hipster-moustache/id959379869?mt=8
How get the ID :
Itunesconnect account
My Apps
Click on "+" Button
New iOS App
Fill require details
After filling all details goto your App
Click on More Button
View on AppStore
It will redirect you to your App URL this will be universal
Look Http URL
This is working the best for me.
Directs the user straight to the 'Write A Review' composer of the application.
Swift 3.1 (Support for iOS10 and below)
Introduces new action=write-review
let appID = "959379869"
if let checkURL = URL(string: "http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=\(appID)&pageNumber=0&sortOrdering=2&type=Purple+Software&mt=8") {
open(url: checkURL)
} else {
print("invalid url")
}
...
func open(url: URL) {
if #available(iOS 10, *) {
UIApplication.shared.open(url, options: [:], completionHandler: { (success) in
print("Open \(url): \(success)")
})
} else if UIApplication.shared.openURL(url) {
print("Open \(url)")
}
}
Tested and works on Swift 2.2
let appID = "959379869" // Your AppID
if let checkURL = NSURL(string: "http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=\(appID)&pageNumber=0&sortOrdering=2&type=Purple+Software&mt=8") {
if UIApplication.sharedApplication().openURL(checkURL) {
print("url successfully opened")
}
} else {
print("invalid url")
}
Swift 4
let url = URL(string: "itms-apps:itunes.apple.com/us/app/apple-store/id\(YOURAPPID)?mt=8&action=write-review")!
UIApplication.shared.openURL(url)
Now after iOS 10.3+
The SKStoreReviewController allows users to rate an app directly from within the app through a dialog box. The only downsite is that you can only request StoreKit to display the dialog, but can't be sure if it will.
import StoreKit
func requestToRate() {
SKStoreReviewController.requestReview()
}
Swift 5.1: The following function sends your user directly to the review section of ANY store, not just on the American one:
func rateApp(id : String) {
guard let url = URL(string : "itms-apps://itunes.apple.com/app/id\(id)?mt=8&action=write-review") else { return }
if #available(iOS 10.0, *) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(url)
}
}
Usage:
rateApp(id: "1287000522")
Important Note: This doesn't work on simulator! Test it on a real device.
You can use the following function and replace the APP_ID with your one. Calling this function will open the app in app store link and user will see the Review page where he can click and write a review easily.
func rateApp(){
UIApplication.sharedApplication().openURL(NSURL(string : "itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=\(APP_ID)&onlyLatestVersion=true&pageNumber=0&sortOrdering=1)")!);
}
For iOS 10.3+ you can use SKStoreReviewController with simple dialog, and choose rating in alert-style window. To use it, you should import StoreKit library. So, universal way to rate your app inside itself is like this:
import StoreKit
func rateApp(){
if #available(iOS 10.3, *) {
SKStoreReviewController.requestReview()
} else {
guard let url = URL(string: "itms-apps://itunes.apple.com/ru/app/cosmeteria/id1270174484") else {
return
}
if #available(iOS 10.0, *) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(url)
}
}
}
And when you try to launch it in simulator, you won't see App Store window, so try it on device and it gonna work. This way covers all iOS versions, using all abilities. And the part of path in you application address "/us/app" means your App Store localisation, for example "us" means USA. You can easily find your app id in address string just by opening app in App Store in any browser.To get the link, just copy address in browser. Changing "https://" for "itms-apps://" lets you to open app in App Store application, while "https" opens web page in Safari
WARNING: If you are running your app on a simulator
UIApplication.sharedApplication().openURL(NSURL(string : "url")!)
will not work because there is no app store in the simulator. In order to test this functionality you must run your app on a device.
Swift 3
func rateApp(){
UIApplication.shared.open(URL(string : "itms-apps://itunes.apple.com/app/id959379869")!, options: [:]) { (done) in
// Handle results
}}
id959379869 This is the id when you go on your iTunes page of your app
Goto your itunesconnect account -> My Apps -> Click on "+" Button ->New iOS App -> Fill require details -> After filling all details goto your App -> Click on More Button -> View on AppStore -> it will redirect you to your App URL this will be universal & will be same after your app goes live .
All the above answers are not best practices they might be affecting your app store ratings. For best practice use the below code.
func ReviewAppController() {
let alert = UIAlertController(title: "Feedback", message: "Are you enjoying our App?", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Dismis", style: .cancel, handler: nil))
alert.addAction(UIAlertAction(title: "Yes, i Love it!", style: .default, handler: {_ in
SKStoreReviewController.requestReview()
}))
alert.addAction(UIAlertAction(title: "No, this sucks!", style: .default, handler: {_ in
//Collect feedback
}))
present(alert, animated: true)
}
This link opens your app page in the App Store and then presents the write review sheet.
itms-apps://itunes.apple.com/app/id[APP_ID]?action=write-review
You can find the APP_ID in the App Store Connect under the details of your app as Apple ID.
In case you want to directly write a review rather than just open an app page:
if let url = URL(string: "https://itunes.apple.com/in/app/\(yourappname)/id\(yourAppleAppId)?ls=1&mt=8&action=write-review") {
if #available(iOS 10.0, *) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
// Earlier versions
if UIApplication.shared.canOpenURL(url as URL) {
UIApplication.shared.openURL(url as URL)
}
}
}

Resources