ios技巧 -- 靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)

常用庫(kù)文件格式

  • .a:靜態(tài)庫(kù)
  • .dylib:動(dòng)態(tài)庫(kù)
  • .framework:動(dòng)靜結(jié)合的庫(kù)
  • .xcframework:特定架構(gòu)下庫(kù)

庫(kù)(Library)說?了就是?段編譯好的?進(jìn)制代碼,加上頭?件就可以供別
?使?。

什么時(shí)候會(huì)?到庫(kù)(Library)?

  1. 某些代碼需要給別?使?,但是我們不希望別?看到源碼,就需要以
    庫(kù)的形式進(jìn)?封裝,只暴露出頭?件。
  2. 對(duì)于某些不會(huì)進(jìn)??的改動(dòng)的代碼,我們想減少編譯的時(shí)間,就可以
    把它打包成庫(kù),因?yàn)閹?kù)是已經(jīng)編譯好的?進(jìn)制了,編譯的時(shí)候只需
    要 Link ?下,不會(huì)浪費(fèi)編譯時(shí)間。

什么是靜態(tài)庫(kù)?

靜態(tài)庫(kù)即靜態(tài)鏈接庫(kù):可以簡(jiǎn)單的看成?組?標(biāo)?件的集合。即很多?
標(biāo)?件經(jīng)過壓縮打包后形成的?件。Windows 下的 .lib,Linux 和 Mac
下的 .a。Mac獨(dú)有的.framework。
缺點(diǎn):
浪費(fèi)內(nèi)存和磁盤空間,模塊更新困難

什么是動(dòng)態(tài)庫(kù)?

與靜態(tài)庫(kù)相反,動(dòng)態(tài)庫(kù)在編譯時(shí)并不會(huì)被拷?到?標(biāo)程序中,?標(biāo)程序
中只會(huì)存儲(chǔ)指向動(dòng)態(tài)庫(kù)的引?。等到程序運(yùn)?時(shí),動(dòng)態(tài)庫(kù)才會(huì)被真正加
載進(jìn)來。格式有:.framework、.dylib、.tdb。
缺點(diǎn):
會(huì)導(dǎo)致?些性能損失。但是可以優(yōu)化,?如延遲綁定(Lazy Binding)技術(shù)

什么是tdb格式?

tbd全稱是text-based stub libraries,本質(zhì)上就是?個(gè)YAML描述的?本?
件。
他的作?是?于記錄動(dòng)態(tài)庫(kù)的?些信息,包括導(dǎo)出的符號(hào)、動(dòng)態(tài)庫(kù)的架構(gòu)信息、動(dòng)
態(tài)庫(kù)的依賴信息
?于避免在真機(jī)開發(fā)過程中直接使?傳統(tǒng)的dylib。
對(duì)于真機(jī)來說,由于動(dòng)態(tài)庫(kù)都是在設(shè)備上,在Xcode上使?基于tbd格式的偽
framework可以??減少Xcode的??。

Framework

Mac OS/iOS 平臺(tái)還可以使? Framework。Framework 實(shí)際上是?種打包
?式,將庫(kù)的?進(jìn)制?件,頭?件和有關(guān)的資源?件打包到?起,?便管
理和分發(fā)。
Framework 和系統(tǒng)的 UIKit.Framework 還是有很?區(qū)別。系統(tǒng)的
Framework 不需要拷?到?標(biāo)程序中,我們??做出來的 Framework 哪怕
是動(dòng)態(tài)的,最后也還是要拷?到 App 中(App 和 Extension 的 Bundle 是
共享的),因此蘋果?把這種 Framework 稱為 Embedded Framework。

Embedded Framework

開發(fā)中使?的動(dòng)態(tài)庫(kù)會(huì)被放?到ipa下的framework?錄下,基于沙盒運(yùn)?。
不同的App使?相同的動(dòng)態(tài)庫(kù),并不會(huì)只在系統(tǒng)中存在?份。?是會(huì)在多
個(gè)App中各?打包、簽名、加載?份。

Mach-o File Format

?個(gè)Mach-o?件有兩部分組成:header 和data。
header:代表了?件的映射,描述了?件的內(nèi)容以及?件所有內(nèi)容所在的位置。
data:緊跟header之后,由多個(gè)?進(jìn)制組成,one by one。

Load Commands

進(jìn)制?件加載進(jìn)內(nèi)存要執(zhí)?的?些指令。
這?的指令主要在負(fù)責(zé)我們 APP 對(duì)應(yīng)進(jìn)程的創(chuàng)建和基本設(shè)置(分配虛擬內(nèi)
存,創(chuàng)建主線程,處理代碼簽名/加密的?作),然后對(duì)動(dòng)態(tài)鏈接庫(kù)(.dylib
系統(tǒng)庫(kù)和我們??創(chuàng)建的動(dòng)態(tài)庫(kù))進(jìn)?庫(kù)加載和符號(hào)解析的?作。

Mach-o File Format

?個(gè)Mach-o?件有兩部分組成:header 和data。
header:包含三種類型。Mach header,segment,sections
header內(nèi)的section描述了對(duì)應(yīng)的?進(jìn)制信息。
注意?:Mach header屬于header的?部分,它包含了整個(gè)?件的信息和segment信息。

Embedded Framework

開發(fā)中使?的Embedded Framework會(huì)被放?到ipa下的Frameworks?錄下,基
于沙盒運(yùn)?。
不同的App使?相同的動(dòng)態(tài)庫(kù),并不會(huì)只在系統(tǒng)中存在?份。?是會(huì)在多
個(gè)App中各?打包、簽名、加載?份。

這里我們通過file查看AFN的.a文件,打開終端
file libAFNetworking.a:查看文件的格式

libAFNetworking.a: current ar archive

ar -t libAFNetworking.a查看.a文件的合集

__.SYMDEF
AFAutoPurgingImageCache.o
AFHTTPSessionManager.o
AFImageDownloader.o
AFNetworkActivityIndicatorManager.o
AFNetworking-dummy.o
AFNetworkReachabilityManager.o
AFSecurityPolicy.o
AFURLRequestSerialization.o
AFURLResponseSerialization.o
AFURLSessionManager.o
UIActivityIndicatorView+AFNetworking.o
UIButton+AFNetworking.o
UIImageView+AFNetworking.o
UIProgressView+AFNetworking.o
UIRefreshControl+AFNetworking.o
WKWebView+AFNetworking.o

clang

NAME
       clang - the Clang C, C++, and Objective-C compiler

SYNOPSIS
       clang [options] filename ...

DESCRIPTION
       clang  is  a C, C++, and Objective-C compiler which encompasses prepro-
       cessing, parsing, optimization, code generation, assembly, and linking.
       Depending  on  which high-level mode setting is passed, Clang will stop
       before doing a full link.  While Clang  is  highly  integrated,  it  is
       important to understand the stages of compilation, to understand how to
       invoke it.  These stages are:

clang命令參數(shù):
-x: 指定編譯文件語(yǔ)言類型
-g: 生成調(diào)試信息
-c: 生成目標(biāo)文件,只運(yùn)行preprocess,compile,assemble,不鏈接
-o: 輸出文件
-isysroot: 使用的SDK路徑
1. -I<directory> 在指定目錄尋找頭文件 header search path
2. -L<dir> 指定庫(kù)文件路徑(.a.dylib庫(kù)文件) library search path
3. -l<library_name> 指定鏈接的庫(kù)文件名稱(.a.dylib庫(kù)文件)other link flags -lAFNetworking
-F<directory> 在指定目錄尋找framework framework search path
-framework <framework_name> 指定鏈接的framework名稱 other link flags -framework AFNetworking

將.m編譯成.o文件

//-x 指定編譯語(yǔ)言
clang -x objective-c \
//-target 指定編譯平臺(tái)
-target x86_64-apple-macos10.15 \
//編譯成arc環(huán)境,10.6一下用-fno-objc-arc
-fobjc-arc \
//指定需要的sdk路徑 并找到自己xcode目錄下的sdk路徑,在這使用的是MacOSX,也可以換成對(duì)應(yīng)的手機(jī)或者模擬器
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk \
//鏈接庫(kù)
-I./AFNetworking \
//將.m編譯成.o
-c test.m -o test.o

目標(biāo)文件就可以通過重定位符號(hào)表,鏈接重定位。所以我們只需要導(dǎo)入頭文件即可
將.o編譯成可執(zhí)行文件

clang -target x86_64-apple-macos10.5 \
//編譯成arc環(huán)境,10.6一下用-fno-objc-arc
-fobjc-arc \
//指定需要的sdk路徑 并找到自己xcode目錄下的sdk路徑,在這使用的是MacOSX,也可以換成對(duì)應(yīng)的手機(jī)或者模擬器
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk \
//鏈接庫(kù)
-L./AFNetworking \
-lAFNetworking
//將.m編譯成.o
test.o -o test

靜態(tài)庫(kù)其實(shí)就是一個(gè).o文件的合集

合并靜態(tài)庫(kù)

libtool

添加或更新靜態(tài)庫(kù)的目錄表

NAME
       libtool - create libraries
       ranlib - add or update the table of contents of archive libraries
libtool \
//代表要合并的是一個(gè)靜態(tài)庫(kù)
-static \
//輸出靜態(tài)庫(kù)的名稱
-o libCat.a \
//需要合并的靜態(tài)庫(kù)
libAFNetworking.a \
libSDWebImage.a

ar

ar壓縮目標(biāo)文件,并對(duì)其進(jìn)行編號(hào)和索引,形成靜態(tài)庫(kù)。同時(shí)也可以解壓縮靜態(tài)庫(kù),查看有哪些目標(biāo)文件:
ar -rc a.a a.o
-r: 像a.a添加or替換文件
-c: 不輸出任何信息
-t: 列出包含的目標(biāo)文件

生成workspace

![addFile.png](https://upload-images.jianshu.io/upload_images/2414707-87ed3515a891192e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

添加文件之前需要xcode中所有的窗口

動(dòng)態(tài)庫(kù)

//支持的架構(gòu)
ld -dylib -arch x86_64 \
//支持最小的系統(tǒng)版本
-macosx_version_min 10.15 \
-syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk \
//system:dyld相關(guān)的鏈接器
-lsystem -framework Foundation \
//符號(hào)全部導(dǎo)出
-all_load \
libTestExample.a -o libTestExample.dylib

動(dòng)態(tài)庫(kù)是.o文件鏈接過后的產(chǎn)物

什么是tdb格式?

tbd全稱是text-based stub libraries,本質(zhì)上就是?個(gè)YAML描述的?本?
件。
他的作?是?于記錄動(dòng)態(tài)庫(kù)的?些信息,包括導(dǎo)出的符號(hào)、動(dòng)態(tài)庫(kù)的架構(gòu)信息、動(dòng)
態(tài)庫(kù)的依賴信息
?于避免在真機(jī)開發(fā)過程中直接使?傳統(tǒng)的dylib。
對(duì)于真機(jī)來說,由于動(dòng)態(tài)庫(kù)都是在設(shè)備上,在Xcode上使?基于tbd格式的偽
framework可以??減少Xcode的??。

在向著上面的方式鏈接后,我們?cè)阪溄觿?dòng)態(tài)庫(kù)運(yùn)行時(shí)一直會(huì)image not found

12.png

我們通過otool -l test | grep 'DYLIB' -A 5遇到DYLIB向下查找5行(-B是向上)

          cmd LC_LOAD_DYLIB
      cmdsize 72
         name TestExample (offset 24)
   time stamp 2 Thu Jan  1 08:00:02 1970
      current version 0.0.0
compatibility version 0.0.0
--
          cmd LC_LOAD_DYLIB
      cmdsize 96
         name /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (offset 24)
   time stamp 2 Thu Jan  1 08:00:02 1970
      current version 1675.129.0
compatibility version 300.0.0
--
          cmd LC_LOAD_DYLIB
      cmdsize 56
         name /usr/lib/libobjc.A.dylib (offset 24)
   time stamp 2 Thu Jan  1 08:00:02 1970
      current version 228.0.0
compatibility version 1.0.0
--
          cmd LC_LOAD_DYLIB
      cmdsize 56
         name /usr/lib/libSystem.B.dylib (offset 24)
   time stamp 2 Thu Jan  1 08:00:02 1970
      current version 1281.100.1
compatibility version 1.0.0
--
          cmd LC_LOAD_DYLIB
      cmdsize 104
         name /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (offset 24)
   time stamp 2 Thu Jan  1 08:00:02 1970
      current version 1675.129.0
compatibility version 150.0.0

我們可以看到其他的動(dòng)態(tài)庫(kù)的name都是一個(gè)路徑TestExample只有一個(gè)名字
動(dòng)態(tài)庫(kù)的路徑是保存在自己的mach-o中的

install_name_tool

NAME
       install_name_tool - change dynamic shared library install names

SYNOPSIS
       install_name_tool  [-change  old  new  ]  ...  [-rpath  old  new  ] ...
       [-add_rpath new ] ... [-delete_rpath new ] ... [-id name] file

DESCRIPTION
       Install_name_tool changes the dynamic shared library install names  and
       or  adds,  changes  or  deletes the rpaths recorded in a Mach-O binary.
       For this tool to work when the install names or rpaths are  larger  the
       binary  should  be  built  with  the ld(1) -headerpad_max_install_names
       option.

       -change old new
              Changes the dependent shared library install name old to new  in
              the specified Mach-O binary.  More than one of these options can
              be specified.  If the Mach-O binary does  not  contain  the  old
              install  name  in  a  specified  -change  option  the  option is
              ignored.
       -id name
              Changes the shared library  identification  name  of  a  dynamic
              shared  library  to name.  If the Mach-O binary is not a dynamic
              shared library and the -id option is specified it is ignored.

       -rpath old new
              Changes the rpath path name old to new in the  specified  Mach-O
              binary.   More  than  one of these options can be specified.  If
              the Mach-O binary does not contain the old rpath path name in  a
              specified -rpath it is an error.

       -add_rpath new
              Adds  the  rpath  path  name new in the specified Mach-O binary.
              More than one of these options can be specified.  If the  Mach-O
              binary  already  contains  the  new rpath path name specified in
              -add_rpath it is an error.

       -delete_rpath old
              deletes the rpath path name old in the specified Mach-O  binary.
              More  than one of these options can be specified.  If the Mach-O
              binary does not contains the old rpath path  name  specified  in
              -delete_rpath it is an error.

執(zhí)行Install_name_tool -id 路徑 目標(biāo)文件

@rpath

Install_name_tool命令中提供的路徑是絕對(duì)路徑,有什么可以比較方便的解決路徑問題呢, @rpath
@rpath代表的誰鏈接我,誰提供路徑,這個(gè)是因?yàn)锧rpath存在鏈接文件的mach-o中,鏈接時(shí),傳遞給被鏈接的Mach-o中的@rpath
我們上面的命令可以改為Install_name_tool -id @rpath/Frameworks/TestExample.framework/TestExample TestExample然后在需要鏈接的文件中Install_name_tool -add_rpath 路徑 目標(biāo)文件
@executable_path:表示可執(zhí)?程序所在的?錄,解析為可執(zhí)??件的絕對(duì)路徑。
@loader_path:表示被加載的Mach-O 所在的?錄,每次加載時(shí),都可能
被設(shè)置為不同的路徑,由上層指定。

XCFramework

XCFramework:是蘋果官?推薦的、?持的,可以更?便的表示?個(gè)多
個(gè)平臺(tái)和架構(gòu)的分發(fā)?進(jìn)制庫(kù)的格式。
需要Xcode11以上?持。
是為更好的?持Mac Catalyst和ARM芯?的macOS。
專?在2019年提出的framework的另?種先進(jìn)格式。

iOS/iPad:arm64
iOS/iPad Simulator: x86_64 arm64
Mac Catalyst: x86_64 arm64
Mac: x86_64 arm64

和傳統(tǒng)的framework相?:

  1. 可以?單個(gè).xcframework?件提供多個(gè)平臺(tái)的分發(fā)?進(jìn)制?件;
  2. 與Fat Header相?,可以按照平臺(tái)劃分,可以包含相同架構(gòu)的不同平
    臺(tái)的?件;
  3. 在使?時(shí),不需要再通過腳本去剝離不需要的架構(gòu)體系。
  • xcodebuild
    將文件進(jìn)行編譯打包
xcodebuild archive -project 'SYTimer.xcodeproj' \
-scheme 'SYTimer' \
-configuration Release \
//指定編譯平臺(tái)
-destination 'generic/platform=iOS Simulator' \
//輸出路徑
-archivePath '../archives/SYTimer.framework-iphonesimulator.xcarchive' \
//將編譯的產(chǎn)物拷貝到目錄中
SKIP_INSTALL=NO

指定他的編譯環(huán)境進(jìn)行打包

//編譯為真機(jī)環(huán)境下
xcodebuild archive -project 'SYTimer.xcodeproj' \
-scheme 'SYTimer' \
-configuration Release \
-destination 'generic/platform=iOS' \
-archivePath '../archives/SYTimer.framework-iphoneos.xcarchive' \
SKIP_INSTALL=NO

平常我們打包時(shí)都是多架構(gòu)打包在一塊的

  • lipo:創(chuàng)建或操作通用文件
  • 胖二進(jìn)制 :多個(gè)架構(gòu)打包到一起

動(dòng)態(tài)庫(kù)合并只能合并不同架構(gòu)的

lipo -output 
//指定輸出名稱
SYTimer 
-create 
//真機(jī)環(huán)境下的
../archives/SYTimer.framework-iphoneos.xcarchive/Products/Library/Frameworks/SYTimer.framework/SYTimer 
//模擬器環(huán)境下的
../archives/SYTimer.framework-iphonesimulator.xcarchive/Products/Library/Frameworks/SYTimer.framework/SYTimer

提取出特定架構(gòu)下的動(dòng)態(tài)庫(kù)

lipo -output SYTimer-x86_64 -extract x86_64 ../archives/SYTimer.framework-iphonesimulator.xcarchive/Products/Library/Frameworks/SYTimer.framework/SYTimer

但是還需要前面,dSYM之類信息

xcframework目前只能通過命令行生成

xcodebuild -create-xcframework \
-framework '../archives/SYTimer.framework-iphoneos.xcarchive/Products/Library/Frameworks/SYTimer.framework' \
-framework '../archives/SYTimer.framework-iphonesimulator.xcarchive/Products/Library/Frameworks/SYTimer.framework' \
-output 'SYTimer.xcframework'

就會(huì)根據(jù)生成不同平臺(tái)的framework
還需要把調(diào)試符添加進(jìn)去

xcodebuild -create-xcframework \
-framework '../archives/SYTimer.framework-iphoneos.xcarchive/Products/Library/Frameworks/SYTimer.framework' \
-debug-symbols '/Users/xxx/xxx/archives/SYTimer.framework-iphoneos.xcarchive/BCSymbolMaps/6142AB7C-A46D-33C9-A32B-405B93A1D680.bcsymbolmap' \
-debug-symbols '/Users/xxx/xxx/archives/SYTimer.framework-iphoneos.xcarchive/BCSymbolMaps/314A0F21-A400-3D1F-ACBE-258D8A3C919F.bcsymbolmap' \
-framework '../archives/SYTimer.framework-iphonesimulator.xcarchive/Products/Library/Frameworks/SYTimer.framework' \
-debug-symbols '/Users/xxx/xxx/archives/SYTimer.framork-iphonesimulator.xcarchive/dSYMs/SYTimer.framework.dSYM' \
-output 'SYTimer.xcframework'

這里-debug-symbols需要的是絕對(duì)路徑。

生成的xcframework.png

  • weak_framework

我們?cè)?xcconfig中配置

// 2. -F: frmaework 所在的目錄
FRAMEWORK_SEARCH_PATHS = $(inherited) ${SRCROOT}
// 1. -I :頭文件
HEADER_SEARCH_PATHS = $(inherited) ${SRCROOT}/SYTimer.framework/Headers
// 路徑
LD_RUNPATH_SEARCH_PATHS = $(inherited)
// 3. 名稱
// null -》 runtime -〉 nil
// weak_import
// library
OTHER_LDFLAGS = $(inherited) -Xlinker -weak_framework -Xlinker "SYTimer"

設(shè)置了weak_framework當(dāng)沒有找到定義的符號(hào)是就會(huì)顯示為null。

鏈接兩個(gè)相同的靜態(tài)庫(kù)

OTHER_LDFLAGS = $(inherited) -l"AFNetworking" -l"AFNetworking2"
鏈接兩個(gè)相同的靜態(tài)庫(kù),不同的名字,不會(huì)發(fā)生沖突,因?yàn)橐氲臅r(shí)候默認(rèn)是-noall_load,會(huì)做個(gè)代碼剝離,如果找到了就不會(huì)進(jìn)行鏈接。

動(dòng)態(tài)庫(kù)鏈接動(dòng)態(tài)庫(kù)

我們通過cocoapods導(dǎo)入時(shí)只是生成鏈接器的參數(shù),并不會(huì)真正導(dǎo)入。

  • 導(dǎo)入動(dòng)態(tài)庫(kù)的時(shí)候通過他給我們的腳本動(dòng)態(tài)的拷貝到ipa包中。
    我們?cè)?code>Podfile中使用use_frameworks!
if [[ "$CONFIGURATION" == "Debug" ]]; then
  install_framework "${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework"
fi
if [[ "$CONFIGURATION" == "Release" ]]; then
  install_framework "${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework"
fi
  • 在我們項(xiàng)目的target下再導(dǎo)入一次

如果動(dòng)態(tài)庫(kù)想使用APP中的符號(hào),我們可以OTHER_LDFLAGS添加
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -Xlinker -undefined -Xlinker dynamic_lookup
使用-undefined會(huì)有風(fēng)險(xiǎn),如果沒有定義的符號(hào)也會(huì)通過,我們也可以用
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -Xlinker -U -Xlinker _OBJC_CLASS_$_LGAppObject來指定特定的符號(hào)

動(dòng)態(tài)庫(kù)鏈接靜態(tài)庫(kù)

Podfile中不使用use_frameworks!
可正常運(yùn)行
如果想隱藏靜態(tài)庫(kù)的符號(hào)可使用-hidden-l
OTHER_LDFLAGS = $(inherited) -ObjC -Xlinker -hidden-l"AFNetworking"

靜態(tài)庫(kù)鏈接靜態(tài)庫(kù)

我們需要手動(dòng)配置鏈接的靜態(tài)庫(kù)信息
LIBRARY_SEARCH_PATHSOTHER_LDFLAGS

靜態(tài)庫(kù)鏈接動(dòng)態(tài)庫(kù)

app = app + 靜態(tài)庫(kù) 所以和動(dòng)態(tài)鏈接動(dòng)態(tài)差不多

cocoapods 即導(dǎo)入靜態(tài)庫(kù)又導(dǎo)入動(dòng)態(tài)庫(kù)

platform :ios, '14.1'
target :'LGNetworkManager' do
  use_frameworks!
  # 靜態(tài)庫(kù)、動(dòng)態(tài)庫(kù)
  # 指定需要被編譯成static_framework的庫(kù)
  $static_framework = ['AFNetworking']
  
  pre_install do |installer|
  installer.pod_targets.each do |pod|
        if $static_framework.include?(pod.name)
            def pod.build_type;
              Pod::Target::BuildType.static_framework
            end
        end
    end
  end
  pod 'SDWebImage'
end

Module

Module(模塊)-最小的代碼單元
一個(gè)Module是機(jī)器代碼和數(shù)據(jù)的最小單元,可以獨(dú)立于其他代碼單元進(jìn)行鏈接。
通常,Module是通過編譯單個(gè)原文件生成的目標(biāo)文件。例如,當(dāng)前的test.m被編譯成目標(biāo)文件test.o時(shí),當(dāng)前的目標(biāo)文件就代表了一個(gè)Module。

AFN中的module

//framework module 名稱 AFNetworking
framework module AFNetworking {
  umbrella header "AFNetworking-umbrella.h"
//將所有的頭文件重新導(dǎo)出
  export *
//將上面子module全部導(dǎo)出
  module * { export * }
}

umbrella代表一個(gè)目錄代表傘柄, 這個(gè)目錄下所有.h代表傘骨

AFNetworking-umbrella.png

這一個(gè)文件里包含所有的頭文件
explicit顯示指明子module名稱
在文件中通過@import就可以直接導(dǎo)入模塊,例@import AFNetworking.AFHTTPSessionManager;
其實(shí)只要開啟了module#include#import最后都會(huì)轉(zhuǎn)換成@import
更多用法可參考官網(wǎng)

一般生成 framework后會(huì)自動(dòng)生成一個(gè)module,如果要手動(dòng)創(chuàng)建一個(gè),在創(chuàng)建完.modulemap, 還需要在build settings中配置module file map

framework module LGOCFramework {
    umbrella "Headers"
    export *
    module * {
        export *
    }
}

展開就是下面

framework module LGOCFramework {
    // umbrella<目錄>
    umbrella header "LGOCFramework.h"
  
    explicit module LGTeacher {
        header "LGTeacher.h"
        export *
    }
    explicit module LGStudent {
        header "LGStudent.h"
        export *
    }
}

swiftframework是沒有橋接文件的,我們就需要module,如果我們只想在framework中使用,需要將其設(shè)置為私有的。
文件命名為xxx.private.modulemap

framework module LGSwiftFramework_Private {
    module LGOCStudent {
        header "LGOCStudent.h"
        export *
    }
}

最后在build settings中配置Private Module file map

swift通過 libtool合并靜態(tài)庫(kù)后在xcconfig中配置

// OTHER_CFLAGS:傳遞給用來編譯C或者OC的編譯器,當(dāng)前就是clang
OTHER_CFLAGS="-fmodule-map-file=${SRCROOT}/LGSwiftC/Public/LGSwiftA.framework/module.modulemap" "-fmodule-map-file=${SRCROOT}/LGSwiftC/Public/LGSwiftB.framework/module.modulemap"

// SWIFT_INCLUDE_PATHS: 傳遞給SwiftC編譯器,告訴他去下面的路徑中查找module.file
SWIFT_INCLUDE_PATHS="${SRCROOT}/LGSwiftC/Public/LGSwiftB.framework"  "${SRCROOT}/LGSwiftC/Public/LGSwiftA.framework"

apinotes

我們?cè)谕ㄟ^OC轉(zhuǎn)swift類時(shí)通過宏定義一個(gè)個(gè)轉(zhuǎn)

// 通過指定NS_SWIFT_NAME宏,我們可以添加一些詳細(xì)信息以使函數(shù)清晰可見,從而使其變得如下所示:
// 規(guī)范
- (nullable NSString *)teacherNameForIndex:(NSUInteger)index NS_SWIFT_NAME(teacherName(forIndex:));

// NS_REFINED_FOR_SWIFT從現(xiàn)在開始,Swift的Clang Importer將做一些額外的工作并將該方法導(dǎo)入為私有方法,并以雙下劃線字符開頭__,例如:
//- (BOOL)changeTeacherName:(nullable NSDictionary<NSString *, id> *)options;
- (BOOL)changeTeacherName:(nullable NSDictionary<NSString *, id> *)options NS_REFINED_FOR_SWIFT;

如果量太多我們就可以使用apinotes,文件為SDK名稱.apinotes文件放在SDK目錄下。
這個(gè)格式是yaml格式

#yaml
---
Name: OCFramework
Classes:
- Name: LGToSwift
//Swift名
  SwiftName: ToSwift
  Methods:
  - Selector: "changeTeacherName:"
    Parameters:
    - Position: 0
      Nullability: O
    MethodKind: Instance
    SwiftPrivate: true
//設(shè)置不可以使用
    Availability: nonswift
    AvailabilityMsg: "這個(gè)不能用"
  - Selector: "initWithName:"
    MethodKind: Instance
    DesignatedInit: true

具體信息可以通過官網(wǎng)查詢

符號(hào)與庫(kù)總結(jié).jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容