问题 包含适用于iOS8的WebKit框架无法验证


我正在使用WebKit框架的WKWebView,在尝试提交到应用商店时,我收到此错误:

Your app contains non-public API usage. Please review the errors, correct them, and resubmit your application.
The app links to non-public libraries in Payload...: /System/Library/PrivateFrameworks/WebKit.framework/WebKit

如果我将部署目标设置为8.0,那么错误就会消失,但我也想支持iOS 7。该错误似乎是iOS7也具有WebKit框架的结果,但它当时是私有的。

因此,我想动态链接到WebKit库。我怎么能在XCode中做到这一点?


12454
2017-09-17 17:48


起源

当您的用户使用iOS 7时,您将需要依靠UIWebView(目前尚不清楚您是否正在尝试这样做)。这应该工作: stackoverflow.com/q/25341238/1580288 - EthanB
我对ios7进行运行时检查并使用UIWebView。它在我的开发设备上运行良好。我遇到的问题是试图通过验证。谢谢! - weiyin
我有同样的问题。我只在iOS 8上使用WebKit,但我的应用程序部署到iOS 7 - Mike Vosseller


答案:


好吧,经过几个小时的挫折后,终于让这个工作了。

在Apple修复验证之前,关键是在运行时动态链接到WebKit框架。您的项目应该已经使用运行时检查来优雅地回退到iOS7及更早版本的UIWebView,即检查[WKWebView类]。

步骤1: 从项目设置中删除WebKit框架。转到目标 - >常规 - >链接的框架和库,然后删除WebKit。此时,您的代码将编译但无法链接,因为它无法解析WKWebView和关联的符号。

第2步: 编辑main.m文件以动态加载库:

#import <UIKit/UIKit.h>
#import <TargetConditionals.h>
#import <dlfcn.h>
#import "MyAppDelegate.h"

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

int main(int argc, char * argv[])
{
    @autoreleasepool {
        // Dynamically load WebKit if iOS version >= 8
        if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
#if TARGET_IPHONE_SIMULATOR
            NSString *frameworkPath = [[NSProcessInfo processInfo] environment][@"DYLD_FALLBACK_FRAMEWORK_PATH"];
            if (frameworkPath) {
                NSString webkitLibraryPath = [NSString pathWithComponents:@[frameworkPath, @"WebKit.framework", @"WebKit"]];
                dlopen([webkitLibraryPath cStringUsingEncoding:NSUTF8StringEncoding], RTLD_LAZY);
            }
#else
            dlopen("/System/Library/Frameworks/WebKit.framework/WebKit", RTLD_LAZY);
#endif
        }

        return UIApplicationMain(argc, argv, nil, NSStringFromClass([MyAppDelegate class]));
    }
}

我使用运行时操作系统版本检查,因为Apple只允许从iOS 8开始动态库加载。模拟器与实际设备的库位置不同,所以我使用条件编译来检查它。

第3步: 由于库是动态加载的,因此调用[WKWebView类]和[WKWebView alloc]将不起作用。浏览您的代码,更改每个实例

[WKWebView class]
// change to:
NSClassFromString(@"WKWebView")

每次分配WKWebView时都要更改:

[WKWebView alloc]
// change to:
[NSClassFromString(@"WKWebView") alloc]

您还必须为关联的类执行此操作,包括WKWebViewConfiguration, WKProcessPool,WKUserScript以及您正在使用的其他任何内容。检查链接器错误,查找可能遗漏的任何内容。

步骤4: 现在你的代码应该成功编译。打包,提交到应用商店,并庆祝。


16
2017-09-19 01:43



对于步骤#2,另一种方法是将库添加为可选,而不是在需要时添加以支持iOS7。 - jianhua
当我将WebKit.framework添加为可选时,验证错误会返回。但事实证明,如果您已将所有内容移至NSClassFromString,则告诉链接器根本不需要这些类!我正在更新以删除不必要的步骤。 - weiyin
我遇到同样的问题。这个方法的Thx。 @weiyin由于库是动态加载的,因此使用WKWebView和相关类并不方便。我编写了一个Invocation类来执行具有任何类型参数的选择器。希望能帮助别人。 [链接] [1] [1]: github.com/jnuhwb/WBInvocation - Wellbin Huang
@WellbinHuang您仍然可以导入W​​ebKit标头并正常使用它们的选择器。用WebKit编译是可以的,只是没有链接它。 - weiyin
救我的活!谢谢。 - Wellbin Huang