Swift 是在 WWDC 2014 上发布的。Apple 的大部分示例代码项目现在都是用 Swift 编写的。但是 Apple 在 iOS 10.1 和 macOS 10.12.1 中使用 Swift 吗?
如何检测二进制文件是否正在使用 Swift?
一种天真的方法是检查应用程序的 Frameworks 文件夹中是否包含 Swift 库:libswiftCore.dylib
, libswiftFoundation.dylib
, ...
以下是 macOS 10.12.1 /System/Library/CoreServices/MRT.app/Contents/Frameworks/ 上 MRT.app 的 Frameworks 文件夹的内容:
但是,这不是一个好方法,因为 iOS 和 macOS 在 /System/Library/PrivateFrameworks/Swift/ 中包含 Swift 库的私有副本。iOS 和 macOS 中的多个应用程序直接链接到这些系统库。
以下是 macOS 10.12.1 /System/Library/CoreServices/PIPAgent.app/Contents/Frameworks/ 上 PIPAgent.app 的 Frameworks 文件夹的内容:
更好的方法是检查二进制文件是否链接到 Swift 库。这可以通过otool
使用 -L 选项的命令行工具轻松完成:
-L 显示目标文件使用的共享库的名称和版本号,如果文件是共享库,则显示共享库 ID。
在 PIPAgent 应用程序上运行此命令时:
代码语言:javascript复制otool -L /System/Library/CoreServices/PIPAgent.app/Contents/MacOS/PIPAgent | grep swift
你会得到以下输出:
代码语言:javascript复制/System/Library/PrivateFrameworks/Swift/libswiftAppKit.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftCore.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftCoreData.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftCoreGraphics.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftCoreImage.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftDarwin.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftDispatch.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftFoundation.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftIOKit.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftObjectiveC.dylib (compatibility version 1.0.0, current version 800.8.18)
构建脚本
使用 otool 命令行工具,很容易编写一个 bash 函数来判断文件是否是链接到 Swift 库的二进制文件:
代码语言:javascript复制#------------------------------------------------------------------------
# Function to check if a file (passed as argument $1) is using Swift
# It returns the number of occurrences of the string 'swift'
# from the output of otool
#------------------------------------------------------------------------
isFileUsingSwift ()
{
otool -L $1 2>/dev/null | grep -o swift | wc -l
}
在processFile
bash函数需要一个文件作为参数,如果它连接到 Swift 库二进制,将打印路径:
#------------------------------------------------------------------------
# Function to process a file (passed as argument $1).
# It calls the function isFileUsingSwift() to determine
# if this is a binary using Swift and in this case
# print the path of this file.
#------------------------------------------------------------------------
processFile ()
{
isFileUsingSwift=$( isFileUsingSwift $1 )
if [ ${isFileUsingSwift} != 0 ]
then
# We found a binary using Swift
echo " $1"
fi
}
循环遍历文件夹的所有文件现在是一行:
代码语言:javascript复制find ${PATH_TO_CHECK} -type f -exec bash -c 'processFile "$0"' {} ;
最终脚本
下面是完整的 bash 脚本,它循环遍历文件夹的所有文件并打印找到的所有使用 Swift 的二进制文件的路径。
注意:您可以在此处下载完整的脚本。
代码语言:javascript复制#!/bin/bash
#---------------------------------------------------------------------
# Bash script that loops through all the files of a folder and
# print the paths of all the binaries found that use Swift
# Created by Alexandre Colucci on 01.11.2016
# https://blog.timac.org/2016/1101-apples-use-of-swift-in-ios-10-1-and-macos-10-12
#---------------------------------------------------------------------
#---------------------------------------------------------------------
# Force expand a wildcard pattern into the list of matching pathnames
#---------------------------------------------------------------------
shopt -s nullglob
#---------------------------------------------------------------------
# Function to print the usage
#---------------------------------------------------------------------
printUsage ()
{
echo "Usage: detectSwift.sh PATH"
echo "PATH: Folder to search for binaries using Swift"
echo ""
echo "Examples:"
echo " detectSwift.sh /System/Library"
echo " detectSwift.sh /System"
echo " detectSwift.sh /"
echo ""
echo "Note: run as root in order to avoid permission issues."
echo ""
}
#---------------------------------------------------------------------
# Function to check if a file (passed as argument $1) is using Swift
# It returns the number of occurrences of the string 'swift'
# from the output of otool
#---------------------------------------------------------------------
isFileUsingSwift ()
{
otool -L $1 2>/dev/null | grep -o swift | wc -l
}
#---------------------------------------------------------------------
# Function to process a file (passed as argument $1).
# It calls the function isFileUsingSwift() to determine
# if this is a binary using Swift and in this case
# print the path of this file.
#---------------------------------------------------------------------
processFile ()
{
isFileUsingSwift=$( isFileUsingSwift $1 )
if [ ${isFileUsingSwift} != 0 ]
then
# We found a binary using Swift
echo " $1"
fi
}
#---------------------------------------------------------------------
# Check if the script was called with the expected usage
#---------------------------------------------------------------------
PARAMETER_NUMBER=$#
PARAMETER_REQUIRED=1
if [ $PARAMETER_NUMBER != $PARAMETER_REQUIRED ];
then
printUsage
exit 1
fi
#---------------------------------------------------------------------
# Get the folder path
#---------------------------------------------------------------------
PATH_TO_CHECK=$1
echo ""
echo "Start time:"
date
echo ""
echo "Apps using Swift in ${PATH_TO_CHECK}"
#---------------------------------------------------------------------
# Export the functions so that the subshell inherits them
#---------------------------------------------------------------------
export -f isFileUsingSwift
export -f processFile
#---------------------------------------------------------------------
# Find all the regular files in all subdirectories
# and call for each the function processFile()
#---------------------------------------------------------------------
find ${PATH_TO_CHECK} -type f -exec bash -c 'processFile "$0"' {} ;
#---------------------------------------------------------------------
# Finalizing
#---------------------------------------------------------------------
echo ""
echo "Completed at:"
date
echo ""
运行脚本
脚本真的很慢:对于每个常规文件,它都会创建一个子shell,调用 otool、grep 和 wc。
在 iOS 10.1 文件系统上运行此脚本大约需要 30 分钟。
对于 macOS 10.12.1,在 / 上运行脚本需要几十个小时。我建议只在 /System、/Applications 和 /usr 上运行这个脚本。并行处理这 3 个文件夹大约需要 2 小时。
Apple 在 iOS 10.1 中使用 Swift
在 iPhone 7 Plus 的 iOS 10.1 (14B72c) 上运行脚本将为您提供以下二进制文件列表:
代码语言:javascript复制/Applications/Calculator.app/Calculator
/Applications/Music.app/Music
/Applications/Music.app/PlugIns/MusicMessagesApp.appex/MusicMessagesApp
/Applications/Music.app/PlugIns/RecentlyPlayedTodayExtension.appex/RecentlyPlayedTodayExtension
/System/Library/PrivateFrameworks/UpNextWidget.framework/PlugIns/UpNext.appex/UpNext
您将从 dyld 共享缓存中获得这些额外的二进制文件:
代码语言:javascript复制/System/Library/PrivateFrameworks/CoreKnowledge.framework/CoreKnowledge
/System/Library/PrivateFrameworks/Swift/libswiftAssetsLibrary.dylib
/System/Library/PrivateFrameworks/Swift/libswiftAVFoundation.dylib
/System/Library/PrivateFrameworks/Swift/libswiftCloudKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftContacts.dylib
/System/Library/PrivateFrameworks/Swift/libswiftCore.dylib
/System/Library/PrivateFrameworks/Swift/libswiftCoreAudio.dylib
/System/Library/PrivateFrameworks/Swift/libswiftCoreBluetooth.dylib
/System/Library/PrivateFrameworks/Swift/libswiftCoreData.dylib
/System/Library/PrivateFrameworks/Swift/libswiftCoreGraphics.dylib
/System/Library/PrivateFrameworks/Swift/libswiftCoreImage.dylib
/System/Library/PrivateFrameworks/Swift/libswiftCoreLocation.dylib
/System/Library/PrivateFrameworks/Swift/libswiftCoreMedia.dylib
/System/Library/PrivateFrameworks/Swift/libswiftDarwin.dylib
/System/Library/PrivateFrameworks/Swift/libswiftDispatch.dylib
/System/Library/PrivateFrameworks/Swift/libswiftEventKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftFoundation.dylib
/System/Library/PrivateFrameworks/Swift/libswiftGameKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftGameplayKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftGLKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftHomeKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftLocalAuthentication.dylib
/System/Library/PrivateFrameworks/Swift/libswiftMultipeerConnectivity.dylib
/System/Library/PrivateFrameworks/Swift/libswiftObjectiveC.dylib
/System/Library/PrivateFrameworks/Swift/libswiftPassKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftRemoteMirror.dylib
/System/Library/PrivateFrameworks/Swift/libswiftSceneKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftsimd.dylib
/System/Library/PrivateFrameworks/Swift/libswiftSpriteKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftSwiftOnoneSupport.dylib
/System/Library/PrivateFrameworks/Swift/libswiftUIKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftWatchConnectivity.dylib
/System/Library/PrivateFrameworks/Swift/libswiftWatchKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftWebKit.dylib
/System/Library/PrivateFrameworks/UpNextWidget.framework/UpNextWidget
请注意,除了 Calculator.app 不可用之外,您将为 iPad 获得类似的输出。
Apple 在 macOS 10.12.1 中使用 Swift
在 macOS 10.12.1 上运行脚本将为您提供以下二进制文件列表:
代码语言:javascript复制/Applications/Utilities/Console.app/Contents/MacOS/Console
/usr/bin/swift
/usr/bin/swiftc
/usr/sbin/usernoted
/System/Library/CoreServices/Dock.app/Contents/MacOS/Dock
/System/Library/CoreServices/MRT.app/Contents/Frameworks/libswiftAppKit.dylib
/System/Library/CoreServices/MRT.app/Contents/Frameworks/libswiftCore.dylib
/System/Library/CoreServices/MRT.app/Contents/Frameworks/libswiftCoreData.dylib
/System/Library/CoreServices/MRT.app/Contents/Frameworks/libswiftCoreGraphics.dylib
/System/Library/CoreServices/MRT.app/Contents/Frameworks/libswiftCoreImage.dylib
/System/Library/CoreServices/MRT.app/Contents/Frameworks/libswiftDarwin.dylib
/System/Library/CoreServices/MRT.app/Contents/Frameworks/libswiftDispatch.dylib
/System/Library/CoreServices/MRT.app/Contents/Frameworks/libswiftFoundation.dylib
/System/Library/CoreServices/MRT.app/Contents/Frameworks/libswiftObjectiveC.dylib
/System/Library/CoreServices/MRT.app/Contents/MacOS/MRT
/System/Library/CoreServices/NotificationCenter.app/Contents/MacOS/NotificationCenter
/System/Library/CoreServices/OSDUIHelper.app/Contents/MacOS/OSDUIHelper
/System/Library/CoreServices/PIPAgent.app/Contents/MacOS/PIPAgent
/System/Library/PrivateFrameworks/Swift/libswiftAppKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftAVFoundation.dylib
/System/Library/PrivateFrameworks/Swift/libswiftCloudKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftContacts.dylib
/System/Library/PrivateFrameworks/Swift/libswiftCore.dylib
/System/Library/PrivateFrameworks/Swift/libswiftCoreAudio.dylib
/System/Library/PrivateFrameworks/Swift/libswiftCoreBluetooth.dylib
/System/Library/PrivateFrameworks/Swift/libswiftCoreData.dylib
/System/Library/PrivateFrameworks/Swift/libswiftCoreGraphics.dylib
/System/Library/PrivateFrameworks/Swift/libswiftCoreImage.dylib
/System/Library/PrivateFrameworks/Swift/libswiftCoreLocation.dylib
/System/Library/PrivateFrameworks/Swift/libswiftCoreMedia.dylib
/System/Library/PrivateFrameworks/Swift/libswiftDarwin.dylib
/System/Library/PrivateFrameworks/Swift/libswiftDispatch.dylib
/System/Library/PrivateFrameworks/Swift/libswiftEventKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftFoundation.dylib
/System/Library/PrivateFrameworks/Swift/libswiftGameKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftGameplayKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftGLKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftIOKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftLocalAuthentication.dylib
/System/Library/PrivateFrameworks/Swift/libswiftMultipeerConnectivity.dylib
/System/Library/PrivateFrameworks/Swift/libswiftObjectiveC.dylib
/System/Library/PrivateFrameworks/Swift/libswiftOpenCL.dylib
/System/Library/PrivateFrameworks/Swift/libswiftRemoteMirror.dylib
/System/Library/PrivateFrameworks/Swift/libswiftSceneKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftsimd.dylib
/System/Library/PrivateFrameworks/Swift/libswiftSpriteKit.dylib
/System/Library/PrivateFrameworks/Swift/libswiftSwiftOnoneSupport.dylib
/System/Library/PrivateFrameworks/Swift/libswiftWebKit.dylib
请注意,您将在 Xcode 8.1 中获得很多匹配项。如果排除各种工具链和平台 SDK,您将获得:
代码语言:javascript复制/Applications/Xcode.app/Contents/Frameworks/IDEDocumentation.framework/Versions/A/IDEDocumentation
/Applications/Xcode.app/Contents/Frameworks/libswiftAppKit.dylib
/Applications/Xcode.app/Contents/Frameworks/libswiftAVFoundation.dylib
/Applications/Xcode.app/Contents/Frameworks/libswiftCore.dylib
/Applications/Xcode.app/Contents/Frameworks/libswiftCoreAudio.dylib
/Applications/Xcode.app/Contents/Frameworks/libswiftCoreData.dylib
/Applications/Xcode.app/Contents/Frameworks/libswiftCoreGraphics.dylib
/Applications/Xcode.app/Contents/Frameworks/libswiftCoreImage.dylib
/Applications/Xcode.app/Contents/Frameworks/libswiftCoreMedia.dylib
/Applications/Xcode.app/Contents/Frameworks/libswiftDarwin.dylib
/Applications/Xcode.app/Contents/Frameworks/libswiftDispatch.dylib
/Applications/Xcode.app/Contents/Frameworks/libswiftFoundation.dylib
/Applications/Xcode.app/Contents/Frameworks/libswiftIOKit.dylib
/Applications/Xcode.app/Contents/Frameworks/libswiftObjectiveC.dylib
/Applications/Xcode.app/Contents/Frameworks/libswiftQuartzCore.dylib
/Applications/Xcode.app/Contents/Frameworks/libswiftXPC.dylib
/Applications/Xcode.app/Contents/PlugIns/IDEDocViewer.ideplugin/Contents/MacOS/IDEDocViewer
/Applications/Xcode.app/Contents/PlugIns/IDELanguageSupportUI.ideplugin/Contents/MacOS/IDELanguageSupportUI
/Applications/Xcode.app/Contents/PlugIns/IDEQuickHelp.ideplugin/Contents/MacOS/IDEQuickHelp
/Applications/Xcode.app/Contents/PlugIns/XcodeBuiltInExtensions.appex/Contents/MacOS/XcodeBuiltInExtensions
/Applications/Xcode.app/Contents/SharedFrameworks/DNTDocumentationModel.framework/Versions/A/DNTDocumentationModel
/Applications/Xcode.app/Contents/SharedFrameworks/DNTDocumentationSupport.framework/Versions/A/DNTDocumentationSupport
/Applications/Xcode.app/Contents/SharedFrameworks/DNTSourceKitSupport.framework/Versions/A/DNTSourceKitSupport
/Applications/Xcode.app/Contents/SharedFrameworks/DNTTransformer.framework/Versions/A/DNTTransformer
/Applications/Xcode.app/Contents/SharedFrameworks/DVTDocumentation.framework/Versions/A/DVTDocumentation
/Applications/Xcode.app/Contents/SharedFrameworks/DVTMarkup.framework/Versions/A/DVTMarkup
/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/Resources/repl_swift
/Applications/Xcode.app/Contents/SharedFrameworks/SourceKit.framework/Versions/A/Frameworks/libswiftCore.dylib
/Applications/Xcode.app/Contents/SharedFrameworks/SourceKit.framework/Versions/A/Frameworks/libswiftCoreGraphics.dylib
/Applications/Xcode.app/Contents/SharedFrameworks/SourceKit.framework/Versions/A/Frameworks/libswiftDarwin.dylib
/Applications/Xcode.app/Contents/SharedFrameworks/SourceKit.framework/Versions/A/Frameworks/libswiftDispatch.dylib
/Applications/Xcode.app/Contents/SharedFrameworks/SourceKit.framework/Versions/A/Frameworks/libswiftFoundation.dylib
/Applications/Xcode.app/Contents/SharedFrameworks/SourceKit.framework/Versions/A/Frameworks/libswiftIOKit.dylib
/Applications/Xcode.app/Contents/SharedFrameworks/SourceKit.framework/Versions/A/Frameworks/libswiftObjectiveC.dylib
/Applications/Xcode.app/Contents/SharedFrameworks/SourceKit.framework/Versions/A/SourceKit
结论
Apple 在 iOS 10.1 和 macOS 10.12.1 中对 Swift 的使用极其有限。
在 iOS 10.1 上,只有 2 个应用程序和 2 个使用 Swift 的私有框架:
- 计算器(仅限 iPhone)
- 音乐
- UpNextWidget.framework
- CoreKnowledge.framework
在 macOS 10.12.1 上,使用 Swift 的应用程序列表仅限于:
- 控制台
- swift
- swiftc
- 用户提示
- 程序坞(Dock)
- 捷径
- 通知中心
- OSDUIHelper
- PIPAgent
- Xcode
译自 Apple’s use of Swift in iOS 10.1 and macOS 10.12