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.

  • 相关阅读:
    查询数据库对象依赖关系
    SQL Server数据库管理员必备:DBCC命令
    使用延迟的FileSystemWatcher来避免重复触发事件
    在Lambda表达式中使用递归
    如何观察SQL Server 生成和重用执行计划
    利用Lambda表达式、扩展方法以及泛型来实现一个另类的AOP
    将 SQL Server 2000 系统表映射到 SQL Server 2005 系统视图[MSDN]
    利用Lambda表达式、扩展方法以及泛型来为对象添加方法
    C# 中编译器是如何实现闭包的
    在ASP.NET中使用FileSystemWatcher来监控文件目录
  • 原文地址:https://www.cnblogs.com/shycie/p/6677004.html
Copyright © 2011-2022 走看看