Unity引用UIWebView问题解决

问题

2020年5月以来,上传到iTunes Connect的ipa文件如包含UIWebView相关引用,会导致ipa包无法通过处理,构建版本不可用。

审核团队在邮件中给出的说明如下:

ITMS-90809: Deprecated API Usage – Apple will stop accepting submissions of apps that use UIWebView APIs . See https://developer.apple.com/documentation/uikit/uiwebview
for more information.

使用find查找工程中相关API:

find . | grep -v .svn  | grep "\.a" | grep -v "\.app" | xargs grep UIWebView

结果指向libiPhone-lib.a文件,该文件是Unity导出工程时生成的系统库文件,说明其中包含UIWebView引用。

解决方案

【方案一】

升级Unity版本

Unity在Unity2017.4.33版本中修复了此问题,条件允许可升级Unity版本来解决。

iOS:Fixed Deprecated API Usage warning for using UIWebView when submitting Builds to the App Store Connect.(1180664, 1182274)

【方案二】

去除libiPhone-lib.a中UIWebView的引用

  1. 首先,生成一个URLUtility.mm文件

    #include 
    #import 
    
    using namespace std;
    namespace core {
        template 
        class StringStorageDefault {};
        template 
        class basic_string {
        public:
            char * str;
            basic_string( char* arg){
                str = arg;
            }
        };
    }
    
    void OpenURLInGame(core::basic_string< char,core::StringStorageDefault > const&arg){}
    
    void OpenURL(core::basic_string >const &arg){
        const void *arg2 = arg.str;
        UIApplication *app = [UIApplication sharedApplication];
        NSString *urlStr = [NSString stringWithUTF8String:(char *)arg2];
        NSURL *url = [NSURL URLWithString:urlStr];
        if (@available(iOS 10.0, *)) {
            [app openURL:url options:@{UIApplicationOpenURLOptionsSourceApplicationKey : @YES} completionHandler:nil];
        } else {
            [app openURL:url];
        }
    }
    
    
    void OpenURL(std::string const&arg){
        UIApplication *app = [UIApplication sharedApplication];
        NSString *urlStr = [NSString stringWithUTF8String:arg.c_str()];
        NSURL *url = [NSURL URLWithString:urlStr];
        if (@available(iOS 10.0, *)) {
            [app openURL:url options:@{UIApplicationOpenURLOptionsSourceApplicationKey : @YES} completionHandler:nil];
        } else {
            [app openURL:url];
        }
    }
    
  1. 使用lipo查看libiPhone-lib.a文件中包含的架构

    lipo -info libiPhone-lib.a 
    Architectures in the fat file: libiPhone-lib.a are: armv7 arm64 armv7s 
    

    可知,以上libiPhone-lib.a中包含的架构有armv7、arm64和armv7s,以下以arm64为例。

  2. 使用URLUtility.mm生成对应架构下URLUtility.o文件

    clang -c URLUtility.mm -arch arm64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk
    
  3. 分离libiPhone-lib.a中各架构文件

    lipo libiPhone-lib.a -thin arm64 -output ./URLUtility64/libiPhone-lib64.a
    
  4. 移除对应架构中的原有URLUtility.o文件

    ar -d ./URLUtility64/libiPhone-lib64.a URLUtility.o
    
  5. 将新生成的URLUtility.o文件添加到对应架构的.a中

    ar -q ./URLUtility64/libiPhone-lib64.a ./URLUtility64/URLUtility.o
    
  6. 将各架构的.a文件合并生成新的libiPhone-lib.a

    lipo -create ./URLUtility64/libiPhone-lib64.a ./URLUtilityv7/libiPhone-libv7.a ./URLUtilityv7s/libiPhone-libv7s.a -output ./new/libiPhone-lib.a
    

以上,即可替换libiPhone-lib.a中的URLUtility.o文件,从而达到移除UIWebView相关引用的目的。

可以使用Python3将以上流程用脚本实现

#!/usr/bin/evn python
# coding=UTF-8

import os
import shutil

iPhone_OS_SDK_path = "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk"
lib_file = "libiPhone-lib.a"
arm_list = ["arm64", "armv7", "armv7s"]
origin_lib_path = "./origin_lib"
new_lib_path = "./new_lib"

def makeDir(path):
    if os.path.exists(path):
        print("移除原" + path + "文件")
        shutil.rmtree(path)
    os.makedirs(path)
    print("生成新" + path + "文件")

def generateO(arm):
    cmd_generate_o = "clang -c URLUtility.mm -arch " + arm + " -isysroot " + iPhone_OS_SDK_path
    cmd_move_o = "mv URLUtility.o ./" + arm + "/URLUtility.o"
    os.system(cmd_generate_o)
    os.system(cmd_move_o)

def armThin(arm, path):
    cmd_thin = "lipo libiPhone-lib.a -thin " + arm + " -output " + path + "/libiPhone-lib.a"
    os.system(cmd_thin)

def arDelete(path):
    cmd_ar_delete = "ar -d " + path + "/libiPhone-lib.a URLUtility.o"
    os.system(cmd_ar_delete)

def arAdd(path):
    cmd_ar_add = "ar -q "+ path + "/libiPhone-lib.a " + path + "/URLUtility.o"
    os.system(cmd_ar_add)

def create_lib():
    arm64 = arm_list[0]
    armv7 = arm_list[1]
    armv7s = arm_list[2]
    cmd_create_lib = "lipo -create ./" + arm64 + "/" + lib_file + " ./" + armv7 + "/" + lib_file + " ./" + armv7s + "/" + lib_file +  " -output " + new_lib_path + "/" + lib_file 
    os.system(cmd_create_lib)
    print(cmd_create_lib)
    print("生成新的libiPhone-lib.a,已移除UIWebView引用")

def find_API(path):
    cmd_cd = "cd " + path
    cmd_find = "find . | grep -v .svn  | grep \"\.a\" | grep -v \"\.app\" | xargs grep UIWebView"
    print(new_lib_path)
    print(cmd_find)

    os.system(cmd_cd)
    os.system(cmd_find)

def restructure():
    for arm in arm_list:
        arm_path = "./" + arm
        
        #创建文件夹
        makeDir(arm_path)

        #生成各架构对应的URLUtility.o文件
        generateO(arm)

        #分离出各架构的libiPhone-lib.a
        armThin(arm, arm_path)

        #移除各架构libiPhone-lib.a中原有的URLUtility.o文件
        arDelete(arm_path)

        #将新的URLUtility.o文件合并到libiPhone-lib.a中去
        arAdd(arm_path)

    #创建lib文件夹
    makeDir(new_lib_path)

    #合并成一个libiPhone-lib.a
    create_lib()

    #执行find名称,查找是否包含UIWebView相关调用
    find_API(new_lib_path)

if __name__ == "__main__":
    restructure()

初始文件目录为:

.
├── URLUtility.mm
└── libiPhone-lib.a 

脚本运行完成后文件目录为:

.
├── URLUtility.mm
├── URLUtility64
│   ├── URLUtility.o
│   └── libiPhone-lib64.a
├── URLUtilityv7
│   ├── URLUtility.o
│   └── libiPhone-libv7.a
├── URLUtilityv7s
│   ├── URLUtility.o
│   └── libiPhone-libv7s.a
├── libiPhone-lib.a
├── new
│   └── libiPhone-lib.a
└── restructure.

其中new文件目录下的libiPhone-lib.a已实现UIWebView引用的移除,使用find命令进行验证,发现新的libiPhone-lib.a中已不包含UIWebView相关任何代码。将该文件与工程中的对应文件进行替换,即可解决ipa包上传问题。

你可能感兴趣的:(Unity引用UIWebView问题解决)