zoukankan      html  css  js  c++  java
  • iOS10 openURL方法跳转到设置界面

    问题

    在iOS10之前,跳转到系统设置界面的某个指定界面的方式如下:

    //打开定位服务界面
    NSURL*url=[NSURL URLWithString:@"prefs:root=Privacy&path=LOCATION"];
    if ([[UIApplication sharedApplication] canOpenURL:url]) {
        [[UIApplication sharedApplication] openURL:url];
    };

    但是在iOS10上,调用canOpenURL:打开系统设置界面时控制台会报如下错误,并且无法跳转:

    -canOpenURL: failed for URL: "Prefs:root=Privacy&path=LOCATION" - error: "The operation couldn’t be completed. (OSStatus error -10814.)"

    原因是iOS10只允许如下方式跳转到设置里自己app的界面,对跳转到其他界面做了限制:

    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];

    解决方法

    可以使用 MobileCoreServices.framework 里的私有API:

    - (BOOL)openSensitiveURL:(id)arg1 withOptions:(id)arg2;

    头文件参考: LSApplicationWorkspace.h

    使用方法:

    //注意首字母改成了大写,prefs->Prefs
    NSURL*url=[NSURL URLWithString:@"Prefs:root=Privacy&path=LOCATION"];
    Class LSApplicationWorkspace = NSClassFromString(@"LSApplicationWorkspace");
    [[LSApplicationWorkspace performSelector:@selector(defaultWorkspace)] performSelector:@selector(openSensitiveURL:withOptions:) withObject:url withObject:nil];

    MobileCoreServices.framework 不是私有库,所以直接使用 performSelector: 即可调用私有API。

    注意

    • iOS10的系统URLScheme改成了首字母大写,使用小写的方式会无法打开。
    • 使用私有API的app无法通过App Store审核。你也可以尝试把私有类名和selector字符串混淆一下,绕过审核。例如 这位仁兄 用ASCII混淆的方法:
    - (UIView *)statusBarView { 
        UIView *statusBar = nil; 
        NSData *data = [NSData dataWithBytes:(unsigned char []){0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x61, 0x72} length:9]; 
        NSString *key = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; 
        id object = [UIApplication sharedApplication]; 
        if ([object respondsToSelector:NSSelectorFromString(key)]) {
            statusBar = [object valueForKey:key]; 
        }
        return statusBar; 
    }

    不过,还是不建议使用私有API,因为它是不可靠的。也许某天苹果就把它移除了。

    以下是摘抄自GitHub上的一段可以通过Google私有文件


    2down vote
    +100

    Point 1: LSApplicationWorkspace is private api, so if you use this and will upload your app to app store, it will get rejected.

    Point 2: If you are having any in-house app and still want to use this in your app, then below is the way to use it.

    1. Add MobileCoreServices Framework in your bundle
    2. Create LSApplicationWorkspace.h file with the code exactly same as the code provided at here "https://github.com/nst/iOS-Runtime-Headers/blob/master/Frameworks/MobileCoreServices.framework/LSApplicationWorkspace.h".
    3. Now add this LSApplicationWorkspace.h file into your bundle
    4. Create bridging header for your swift app
    5. Add #import "LSApplicationWorkspace.h" in your bridging header
    6. Now add import MobileCoreServices in your current file and add your code let test = LSApplicationWorkspace.defaultWorkSpace(), it will work fine.

    NOTE: For using any private header, you must have to include its .h file into your code. You can find any private headers by searching "runtime headers" in google. You will get all runtime headers. And to include that header in your swift code, you need to go via bridging-header.

  • 相关阅读:
    Linux常用命令记录
    Python写入数据至Excel文件中--学习笔记
    python操作mysql数据库封装类
    @property和@score.setter的用法--学习记录
    python3操作mysql数据库时,新增含有中文的数据时不成功但没报错,解决记录
    关于springmvc+maven项目引入css文件
    安全测试:xss注入方法
    报错记录:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
    uiautomatorviewer.bat报错:Error while obtaining UI hierarchy XML file: com.android.ddmlib.SyncExceptio
    面向对象15.2String类-构造函数
  • 原文地址:https://www.cnblogs.com/shycie/p/6677004.html
Copyright © 2011-2022 走看看