一、布景
在 iOS
运用开发的世界里,每次 Xcode
更新都带来了新的特性和应战。最近的 Xcode 15
更新不例外,这次晋级引入了对 SwiftUI
的主动强依靠。SwiftUI
最低是从 iOS 13
开端支撑。
这一改变也带来了潜在的兼容性问题。如果您的项目在晋级到 Xcode 15
后仍需支撑 iOS 13
以下版别,那么在这些旧设备上运转运用时,将不可避免地遇到崩溃问题。
二、问题
Xcode15
晋级后 iOS13
以下崩溃问题
问题描述及原因
崩溃信息如下:
ExceptionType:EXC_CRASH(SIGABRT)
ExceptionCodes:0x0000000000000000,0x0000000000000000
ExceptionNote:EXC_CORPSE_NOTIFY
TerminationDescription:DYLD,Librarynotloaded:/System/Library/Frameworks/SwiftUI.framework/SwiftUI|Referencedfrom:/var/containers/Bundle/Application/E96C2AC1-F3D8-4A70-8FDE-FA34A0C73AD3/JDMobileLite.app/JDMobileLite|Reason:imagenotfound
TriggeredbyThread:0
Xcode15 默认会在 Build Setting
增加 ASSETCATALOG_COMPILER_GENERATE_ASSET_SYMBOL_FRAMEWORKS
选项,默认值为:
SwitUIUIKitAppKit
因为 SwiftUI 是从 iOS13 开端支撑,这样导致在以下的设备上运转会崩溃。
官方文档如下:
developer.apple.com/documentati…
问题解决
检查一下Asset Catalog Compiler这一项 Generate Swift Asset Symbol Framework Support,把SwiftUI去掉
问题解决复查
1、重新出包,运用 iOS13以下 的设备安装运转验证;
2、运用 otool 检测 ipa 中的二进制验证:
问题解决前数据如下:
$otool-LJDMobileLite
JDMobileLite:
...
...
/System/Library/Frameworks/QuickLook.framework/QuickLook(compatibilityversion1.0.0,currentversion946.3.2)
/System/Library/Frameworks/SwiftUI.framework/SwiftUI(compatibilityversion1.0.0,currentversion5.2.12)
/System/Library/Frameworks/UserNotifications.framework/UserNotifications(compatibilityversion1.0.0,currentversion1.0.0)
...
...
问题解决后数据如下:
$otool-LJDMobileLite
JDMobileLite:
...
...
/System/Library/Frameworks/QuickLook.framework/QuickLook(compatibilityversion1.0.0,currentversion946.3.2)
/System/Library/Frameworks/UserNotifications.framework/UserNotifications(compatibilityversion1.0.0,currentversion1.0.0)
...
...
解决方案参考:
forums.developer.apple.com/forums/thre…
stackoverflow.com/questions/5…
三、规避东西
跟着 Xcode
和 iOS SDK
的不断更新,我们作为开发者,面临着一个继续的应战:保证我们的运用在旧版别的iOS上仍然能够稳定运转。这一应战的核心在于保持 App支撑的最低体系版别号 与 项目依靠的体系库支撑最低版别号 的一致性。这不仅仅是一个单次的修正问题,而是需求一个体系化的解决方案来继续监控和解决这一问题。以下是实现这一方针的三个关键思路:
1、怎么获取到 App 支撑的最低体系版别号?
每一个 App
中都会有一个 info.plist
文件,这儿经过 plistlib
读取该 App
支撑的最低体系版别号及当前 App
的版别信息,脚本如下:
defread_minimum_os_version(app_path):
info_plist_path=app_path+"/"+"info.plist"
try:
withopen(info_plist_path,'rb')asf:
data=plistlib.load(f)
returndata.get('MinimumOSVersion'),data.get('CFBundleShortVersionString'),data.get('CFBundleVersion')
except(KeyError,FileNotFoundError):
returnNone
2、怎么获取 App 依靠的体系库列表?
这儿需求运用到 otool
东西的能力,依靠 bash
环境,脚本代码如下:
#!/bin/bash
#otool.sh
file_path=$1
otool-L$file_path
Python
经过 subprocess
履行 otool.sh
并获取依靠体系库列表:
defsystem_frameworks_list(app_path):
filename=os.path.basename(app_path)
filename,extension=os.path.splitext(filename)
macho_path=app_path+"/"+filename
result=subprocess.run(["sh","otool.sh",macho_path],stdout=subprocess.PIPE)
#检查指令是否成功履行
ifresult.returncode==0:
#将输出解码为字符串
output_str=result.stdout.decode('utf-8')
#打印输出
print("t履行sh脚本获取体系列表信息成功")
frameworks=extract_frameworks(output_str)
returnframeworks
else:
print(f"t履行脚本失败,退出状况码:{result.returncode}")
returnNone
3、怎么获取这些体系库最低支撑的体系版别号?
经过查询资料,Apple 是有敞开 API 进行查询,查询方法为:developer.apple.com/tutorials/d…
解析可获取对应库的最低支撑体系版别号。
需求留心的是,如下库需求过滤:
defignore_frameworks():
#OpenAL(OpenAudioLibrary)是一个跨渠道的敞开源代码音频库,它提供了一组接口,
#使得游戏开发者能够更方便地处理音频。
#OpenAL提供了诸如3D声响定位、回声作用、混响作用等功能,使得游戏开发者能够创建愈加逼真的音效体验。
#https://www.openal.org/platforms/查询得到iOS开发中是在CoreAudio中,而CoreAudio从iOS2就开端支撑
#MobileCoreServices结构运用一致类型标识符(UTI)信息来创建和操作能够在您的运用和其他运用和服务之间交流的数据。
#底层直接引证CoreServices,MobileCoreServices支撑
#支撑的最低体系版别,这个结构自iOS的前期版别就已经存在,并且跟着操作体系的每次更新而得到更新和维护
#WebKit和JavaScriptCore在iOS7就开端支撑,但是有一些特性API会有版别限制,不再体系库这一层级去考虑
return["OpenAL","MobileCoreServices","WebKit","JavaScriptCore"]
东西实现的流程:
四、东西运用
履行 main.py
, 并传入 app
包的途径即可
$python3main.py-f/Users/denglibing/Downloads/JDMOBILELITE-V6.0.0-100-1337-APPSTORE-d0e2839a/Payload/JDMobileLite.app
==Step1解析参数
app_path:/Users/denglibing/Downloads/JDMOBILELITE-V6.0.0-100-1337-APPSTORE-d0e2839a/Payload/JDMobileLite.app
output:/Users/denglibing/Downloads/JDMOBILELITE-V6.0.0-100-1337-APPSTORE-d0e2839a/Payload
==Step2经过sh脚本获取该app依靠的体系库列表(剔除weak依靠))
履行sh脚本获取体系列表信息成功
体系库列表:['AVFoundation','Accelerate','AdSupport','AddressBook','AddressBookUI','AssetsLibrary','AudioToolbox','CFNetwork','CoreFoundation','CoreGraphics','CoreLocation','CoreMedia','otion','CoreText','CoreVideo','EventKit','Foundation','GLKit','ImageIO','LocalAuthentication','MediaPlayer','OpenGLES','PassKit','QuartzCore','Security','StoreKit','SystemConfiguration','UIKit','VideoToolbox','WatchConnectivity','AVKit','CoreData','CoreImage','MapKit','MessageUI','Photos','QuickLook','iAd','SwiftUI']
==Step3读取info.plist文件获取该app版别信息
app_version:6.0.0app_build:1337min_ios_version:11.0
==Step4developer.apple.com查询获取体系库最低支撑版别号,得到反常依靠
反常依靠:SwiftUI
!!!请重点排查!!!,不然或许导致低版别体系启动崩溃
本次分析耗时:38.130秒
开源地址,欢迎运用并反应: github.com/erduoniba/a…