ユーザーの現在位置を利用する明示的なユーザーインタラクションを備えたアプリケーションがあります。ユーザーが位置情報サービスへのアクセスを拒否した場合でも、以降の使用でユーザーに設定にアクセスしてアプリの位置情報サービスを再度有効にするように要求するようにします。
私が望む動作は、組み込みのマップアプリの動作です。
私自身のアプリでは、同じ基本フローの結果、CLLocationManagerDelegate -locationManager:didFailWithError:メソッドが最後のステップでkCLErrorDeniedエラーで呼び出され、ユーザーは設定アプリを開いて修正するオプションが与えられません。
エラーに応答して独自のアラートを表示できましたが、組み込みのマップアプリで使用されるようにOSが提供できるアラートのように、設定アプリを起動することはできません。
CLLocationManagerクラスにこの動作を与えることができるものがありませんか?
IOS8では、最終的にopenURLを介してユーザーを設定アプリにリンクできます。たとえば、ユーザーを設定アプリに移動するボタンが1つあるUIAlertViewを作成できます。
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:ICLocalizedString(@"LocationServicesPermissionTitle")
message:ICLocalizedString(@"LocationPermissionGeoFenceMessage")
delegate:self
cancelButtonTitle:@"Settings"
otherButtonTitles:nil];
[alert show];
UIAlertViewデリゲートで:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
[alertView dismissWithClickedButtonIndex:buttonIndex animated:YES];
[[UIApplication sharedApplication] openURL: [NSURL URLWithString: UIApplicationOpenSettingsURLString]];
}
更新:
IOS 8現在、定数UIApplicationOpenSettingsURLString
があります。これは、開くと設定アプリを開いてアプリケーションの設定を開くURLを表します(ユーザーはそこで位置情報サービスを再度有効にできます)。
オリジナル:
これを行う方法はありません。唯一の本当のオプションは、アプリケーションに位置情報サービスが必要であることをユーザーに知らせるアラートを表示し、手動で設定アプリに移動してオンにするよう指示することです。
AlertViewsは、iOS 8では非推奨です。新しいAlertControllerを使用してアラートを処理するより良い方法があります。
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString( @"Enter your title here", @"" ) message:NSLocalizedString( @"Enter your message here.", @"" ) preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString( @"Cancel", @"" ) style:UIAlertActionStyleCancel handler:nil];
UIAlertAction *settingsAction = [UIAlertAction actionWithTitle:NSLocalizedString( @"Settings", @"" ) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:
UIApplicationOpenSettingsURLString]];
}];
[alertController addAction:cancelAction];
[alertController addAction:settingsAction];
[self presentViewController:alertController animated:YES completion:nil];
Markusとbjcが提供するコードのSwift 3実装です。
let alertController = UIAlertController(title: NSLocalizedString("Enter your title here", comment: ""), message: NSLocalizedString("Enter your message here.", comment: ""), preferredStyle: .alert)
let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil)
let settingsAction = UIAlertAction(title: NSLocalizedString("Settings", comment: ""), style: .default) { (UIAlertAction) in
UIApplication.shared.openURL(NSURL(string: UIApplicationOpenSettingsURLString)! as URL)
}
alertController.addAction(cancelAction)
alertController.addAction(settingsAction)
self.present(alertController, animated: true, completion: nil)
locationServicesEnabledメソッドの Appleのドキュメント によると。
ユーザーは、全般で位置情報サービススイッチを切り替えることで、設定アプリケーションから位置情報サービスを有効または無効にできます。
ロケーションの更新を開始する前にこのメソッドの戻り値を確認して、ユーザーが現在のデバイスでロケーションサービスを有効にしているかどうかを判断する必要があります。 このメソッドがNOを返し、とにかくロケーションの更新を開始すると、コアロケーションフレームワークは、ロケーションサービスを再度有効にするかどうかを確認するようユーザーにプロンプトを表示します。
位置情報サービスの更新を開始するだけでは、アラートが表示されるようにすることはできませんか?
Swift 4では、構文に更新があります。
Swift 4
extension UIAlertController {
func createSettingsAlertController(title: String, message: String) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil)
let settingsAction = UIAlertAction(title: NSLocalizedString("Settings", comment: ""), style: .default) { (UIAlertAction) in
UIApplication.shared.open(URL(string: UIApplicationOpenSettingsURLString)! as URL, options: [:], completionHandler: nil)
}
alertController.addAction(cancelAction)
alertController.addAction(settingsAction)
self.present(alertController, animated: true, completion: nil)
}
}
Appleが新しいSDKについて考えるとき、あなたはあなたの質問に答えを持っていると思います。現時点では、私が知る限り、それは不可能です:
利用可能なURLハンドラがありません
使用できるメソッドがありません
しかし... Mapsが行うように、これは行うことができますが、おそらくプライベートAPIを使用します。この種のコーディングを恐れないのであれば、私の意見でそこを検索する必要があります。
Swift、
アプリのロケーションサービスを無効にすると、ロケーションマネージャーのデリゲートメソッドはエラーを表示し始めます。したがって、エラーを受信すると、位置情報サービスが有効か無効かを確認できます。その結果に応じて、ユーザーに設定に移動して位置情報サービスを有効にするように依頼できます。
エラーのロケーションマネージャーデリゲートメソッドで、ロケーション許可チェックを追加します
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
//check location permissions
self.checkLocationPermission()
}
}
ロケーション許可チェックのコード
//check location services enabled or not
func checkLocationPermission() {
if CLLocationManager.locationServicesEnabled() {
switch(CLLocationManager.authorizationStatus()) {
case .notDetermined, .restricted, .denied:
//open setting app when location services are disabled
openSettingApp(message:NSLocalizedString("please.enable.location.services.to.continue.using.the.app", comment: ""))
case .authorizedAlways, .authorizedWhenInUse:
print("Access")
}
} else {
print("Location services are not enabled")
openSettingApp(message:NSLocalizedString("please.enable.location.services.to.continue.using.the.app", comment: ""))
}
}
設定アプリを開くためのコード、
//open location settings for app
func openSettingApp(message: String) {
let alertController = UIAlertController (title: APP_NAME_TITLE, message:message , preferredStyle: .alert)
let settingsAction = UIAlertAction(title: NSLocalizedString("settings", comment: ""), style: .default) { (_) -> Void in
guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
return
}
if UIApplication.shared.canOpenURL(settingsUrl) {
UIApplication.shared.open(settingsUrl, options: [:], completionHandler: nil)
}
}
alertController.addAction(settingsAction)
let cancelAction = UIAlertAction(title: NSLocalizedString("cancel", comment: ""), style: .default, handler: nil)
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)
}
Swift Markusによる回答のコードのバージョンです。このコードは、設定を開くオプションをユーザーに提供するアラートを作成します。
let alertController = UIAlertController(title: NSLocalizedString("Enter your title here", comment: ""), message: NSLocalizedString("Enter your message here.", comment: ""), preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel, handler: nil)
let settingsAction = UIAlertAction(title: NSLocalizedString("Settings", comment: ""), style: .Default) { (UIAlertAction) in
UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString)!)
}
alertController.addAction(cancelAction)
alertController.addAction(settingsAction)
self.presentViewController(alertController, animated: true, completion: nil)
latest Swift上記の回答に基づいたバージョン。
func showSettingsAlert(_ from:UIViewController, title:String?, message:String?) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil)
let settingsAction = UIAlertAction(title: NSLocalizedString("Settings", comment: ""), style: .default) { (UIAlertAction) in
guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
return
}
if UIApplication.shared.canOpenURL(settingsUrl) {
UIApplication.shared.open(settingsUrl, options: [:], completionHandler: nil)
}
}
alertController.addAction(cancelAction)
alertController.addAction(settingsAction)
from.present(alertController, animated: true, completion: nil)
}
設定アラートコントローラーを作成するためのSwift 3拡張:
輸入財団
extension UIAlertController {
func createSettingsAlertController(title: String, message: String) -> UIAlertController {
let controller = UIAlertController(title: title, message: message, preferredStyle: .alert)
let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment:"" ), style: .cancel, handler: nil)
let settingsAction = UIAlertAction(title: NSLocalizedString("Settings", comment:"" ), style: .default, handler: { action in
UIApplication.shared.openURL(URL(string: UIApplicationOpenSettingsURLString)!)
})
controller.addAction(cancelAction)
controller.addAction(settingsAction)
return controller
}
}