iOS-SDK開發(fā)經(jīng)驗分享

本文目標:掌握封裝SDK的全部技巧及跳坑指南

本文目標:掌握封裝及開發(fā)SDK的全部技巧

文章比較長,建議分模塊閱讀

內(nèi)容提要:不同場景下如何封裝及開發(fā)SDK

  • .a靜態(tài)庫創(chuàng)建
  • 直接創(chuàng)建Framework庫
  • 在已有工程中創(chuàng)建
  • 創(chuàng)建Framework工程進行封裝
  • 創(chuàng)建Bundle資源庫文件
  • 含界面SDK如何進行依賴開發(fā)
  • 使用腳本創(chuàng)建Framework庫,解決合并的煩惱
  • Swift 如何創(chuàng)建Framework庫

知識準備

  • 終端命令
真機和模擬器上的庫文件合并 
Framework庫合并的是Framework內(nèi)包含的二進制文件,合并后替換庫中的文件,沒有.a后綴
lipo -create xxx.a(真機) xxx.a(模擬器) -output 新名字.a
查看SDK支持的架構(gòu)
lipo -info XXX.a  輸出: i386 armv7 x86_64 arm64

arm7: 在最老的支持iOS7的設(shè)備上使用
arm7s: 在iPhone5和5C上使用
arm64: 運行于iPhone5S的64位 ARM 處理器 上
i386: 32位模擬器上使用
x86_64: 64為模擬器上使用
注意: 高位兼容地位(32位兼容16位),arm7版本可以在arm7s上運行
需要在對應(yīng)架構(gòu)設(shè)備上運行,才能生成對應(yīng)架構(gòu)的包

  • category的處理

category是項目開發(fā)中經(jīng)常用到的,把category打包成靜態(tài)庫是沒有問題的,但是在使用這個靜態(tài)庫時,
調(diào)用category中的方法時會發(fā)生找不到該方法的運行時錯誤(selector not recognized),
解決的辦法是在使用靜態(tài)庫的工程中配置other linker flags的值為 -ObjC -all_load

  • 對圖片資源和UI界面xib或nib文件的處理

.a和.framework兩種靜態(tài)庫,通常都是把需要用的到圖片或者xib文件存放在一個bundle文件中,而該bundle文件的名字和.a或.framework的名字相同。
.a文件中無法存放圖片或xib文件,很容易理解,但是.framework從本質(zhì)上說也是一個bundle文件,為什么不把圖片或者xib文件直接放在.framework中而單獨再創(chuàng)建個bundle文件呢?
那是因為iOS系統(tǒng)不會去掃描.framework下的圖片等資源文件,也不會在項目中顯示,也就是說即使放在 .framework目錄下,系統(tǒng)根本就不會去掃描,因此也無法發(fā)現(xiàn)使用

  • Debug和Release

Debug和Release,在我看來主要是針對其面向的目標不同的而進行區(qū)分的。
Debug通常稱為調(diào)試版本,通過一系列編譯選項的配合,編譯的結(jié)果通常包含調(diào)試信息,而且不做任何優(yōu)化,以為開發(fā)人員提供強大的應(yīng)用程序調(diào)試能力。
Release通常稱為發(fā)布版本,是為用戶使用的,一般客戶不允許在發(fā)布版本上進行調(diào)試。所以不保存調(diào)試信息,同時,它往往進行了各種優(yōu)化,以期達到代碼最小和速度最優(yōu)。為用戶的使用提供便利

開發(fā)指南

網(wǎng)上找了一個動畫工程,作為我們開刀的對象
下載原始工程
如果你有耐性,可以和我一起走完整個流程。當然每個模塊都是獨立的,你可以進行針對性的閱讀

一、.a靜態(tài)庫創(chuàng)建

  • 創(chuàng)建靜態(tài)庫工程 >> 刪除自動創(chuàng)建的.m文件 >> 清空頭文件里的信息 >> 導入你要封裝的系統(tǒng)庫文件
創(chuàng)建靜態(tài)庫工程 libLoader(名字你高興就好)
刪除自動創(chuàng)建的.m文件,清空頭文件里的信息
導入你要封裝的系統(tǒng)庫文件
  • 點擊目標工程 >> Build Phases >> Editor >> add build Phases(是否公開頭文件選項) >> 設(shè)置公開訪問的頭文件(或在Target Membership中直接設(shè)置)

    目標工程 > Build Phases > 點擊左側(cè)加號 > add build Phases(是否公開頭文件選項) > 設(shè)置公開訪問的頭文件(或在Target Membership中直接設(shè)置)
添加頭文件選項
設(shè)置私有和暴露頭文件
設(shè)置私有和暴露頭文件
選擇sdk支持的系統(tǒng)版本
  • 參數(shù)設(shè)置
    • Build Settings >> Dead Code Stripping設(shè)置為NO
    • Build Settings >> Strip Debug Symbol During Copy 全部設(shè)置為NO
    • Build Settings >> Strip Style設(shè)置為Non-Global Symbols
    • Build Settings >> Base SDK >> Latest iOS(iOS 選擇最新的)
Dead Code Stripping設(shè)置為NO
Strip Debug Symbol During Copy 全部設(shè)置為NO
Strip Style設(shè)置為Non-Global Symbols
Base SDK >> Latest iOS(iOS 選擇最新的)
  • 在設(shè)備 和 模擬器 下分別按下command + B進行編譯 >> 查看Product目錄 >> Show in Finder 查看編譯成功的靜態(tài)庫
  • debug模式下運行生成 Debug-iphoneos 和 Debug-iphonesimulator兩個文件夾
  • release模式下運行生成 Release-iphoneos 和 Release-iphonesimulator文件夾
切換編譯模式
分別查看.a庫文件
  • 合并Debug模式下的真機和模擬器下的靜態(tài)庫文件
使用終端進行合并
cd 文件保存目錄
lipo -create 模擬器.a(路徑) 真機.a(路徑) -output 重命名.a
查看架構(gòu)模式
lipo -info XXX.a  查看是否滿足運行要求
  • 使用.a庫文件
    創(chuàng)建文件夾libAdvanced用于保存靜態(tài)庫信息 >> 替換剛剛合并的.a文件 >> 添加用到的圖片等資源文件 >> 導入工程驗證
靜態(tài)庫完成
  • 創(chuàng)建新工程驗證
  • 如果架構(gòu)報錯 Build Settings >> BuildActiveArchitecture Only Debug改為NO

二、直接創(chuàng)建Framework庫

<p id="jump"></p>

Framework是資源的集合,將靜態(tài)庫和其頭文件包含到一個結(jié)構(gòu)中,讓Xcode可以方便地把它納入到你的項目中。本質(zhì)也是一個bundle文件

  • 在已有工程中創(chuàng)建
    • 創(chuàng)建Framework
      點擊目標工程 >> 點擊下面左下角加號 >> 創(chuàng)建


      創(chuàng)建Framework
    • 參數(shù)配置
      點擊目標工程 >> 選擇你創(chuàng)建的Framework >> 點擊工程設(shè)置 >> 做出如下修改

      Build Settings >> Dead Code Stripping >> 設(shè)置為NO

      Build Settings >> Strip Debug Symbol During Copy >> 全部設(shè)置為NO

      Build Settings >> Strip Style >> 設(shè)置為Non-Global Symbols

      Build Settings >> Base SDK >> Latest iOS(iOS 選擇最新的)

      Build Settings >>  Link With Standard Libraries >> 設(shè)置為 NO

      Build Settings >>  Mach-O Type >> Static Library

      對于Mach-O Type有兩種情況:(1)選擇 Static Library 打出來的是靜態(tài)庫;(2)選擇 Relocatable Object File 打出來是動態(tài)庫。
其他參數(shù)修改類似
  • 選擇framework支持的系統(tǒng)版本

  • 將需要打包的文件拖入到Framework中


    將需要打包的文件拖入到Framework中
  • 設(shè)置需要公開的文件


    設(shè)置暴露頭文件
  • 選擇運行模式(debug 或 Release)分別在真機和模擬器下common + B 編譯生成對應(yīng)的Framework庫

  • 合并二進制文件并替換

cd 到保存文件目錄下
lipo -create xxx/Debug-iphoneos/LibLoaderFramework.framework/LibLoaderFramework xxx/Debug-iphonesimulator/LibLoaderFramework.framework/LibLoaderFramework -output LibLoaderFramework
lipo -info LibLoaderFramework
輸出
Architectures in the fat file: LibLoaderFramework are: i386 arm64 
然后替換二進制文件
image.png
  • 刪除Framework


    image.png
  • 如果沒有用到info.plist文件可以刪除,避免在工程中發(fā)生沖突
  • 驗證
    導入完整Framework到工程,移除打包前的代碼,對庫進行驗證
  • 建立Framework工程進行創(chuàng)建
    • 使用xcode直接創(chuàng)建Framework工程

    • 把需要編譯的文件導入到工程中

    • 設(shè)置需要公開的頭文件


      image.png
    • 選擇Framework支持的系統(tǒng)版本

    • 配置參數(shù)

 參數(shù)配置基本都一樣
點擊目標工程 >> 選擇你創(chuàng)建的Framework >> 點擊工程設(shè)置 >> 做出如下修改
  Build Settings >> Dead Code Stripping >> 設(shè)置為NO
  Build Settings >> Strip Debug Symbol During Copy >> 全部設(shè)置為NO
  Build Settings >> Strip Style >> 設(shè)置為Non-Global Symbols
  Build Settings >> Base SDK >> Latest iOS(iOS 選擇最新的)
  Build Settings >>  Link With Standard Libraries >> 設(shè)置為 NO
  Build Settings >>  Mach-O Type >> Static Library
  對于Mach-O Type有兩種情況:(1)選擇 Static Library 打出來的是靜態(tài)庫;(2)選擇 Relocatable Object File 打出來是動態(tài)庫。
-  選擇Debug(或Release)模式分別在模擬器和真機上 command + B 編譯

- 合并真機和模擬器下編譯的二進制文件
cd到你想要保存合并后文件的目錄下
lipo -create xxx.framework/xxx ooo.framework/ooo -output ooo。
查看文件支持的架構(gòu)
lipo -info LibLoaderFramework
將合并成功的二進制文件替換為framework中的二進制文件,如果沒有用到info.plist文件,可以刪除,避免在工程中發(fā)生沖突
  • 創(chuàng)建新的工程,導入Framework進行驗證
如果工程無法聯(lián)想出Framework頭文件,導入路徑形式如下:
#import <LibLoaderFramework/PublicHeader.h>

三、創(chuàng)建Bundle資源庫文件

  • 創(chuàng)建Bundle工程


    創(chuàng)建Bundle工程
  • 配置幾個編譯設(shè)置

因為你正在創(chuàng)建一個在iOS上使用的bundle,這與默認的OS X不同。
 Build Settings >> Base SDK >> Latest iOS (iOS 10.2選擇最新)
 Build Settings >> Product Name >> ${TARGET_NAME}替換為你的工程名XXXX(直接寫工程名就好)
################注意事項######################
默認情況下,有兩種resolutions(分辨率)的圖片可以產(chǎn)生一些有趣的現(xiàn)象。
例如,當你導入一個retina@2x版本的圖片時,普通版的和Retina版的將會合并成一個多resolution的TIFF(標簽圖像文件格式,Tagged Image File Format)。
Build Settings > COMBINE_HIDPI_IMAGES設(shè)置為NO
  • 如何添加資源文件

    • 直接拖入
    • 選擇圖片或其他資源文件 > Target Membership > 選擇bundle目標
  • 編譯工程并查看


    編譯工程并查看
  • Bundle文件使用時需要真實路徑

    NSBundle *bundle = [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"LoaderBundle" withExtension:@"bundle"]];
    NSString *resourceStr = [bundle pathForResource:@"IMG_0017" ofType:@"JPG"];
    我們可以創(chuàng)建NSBundle分類避免重復書寫    
  • 創(chuàng)建工程驗證

四、含界面SDK如何進行依賴開發(fā)

在無法看到真實效果的情況下為iOS開發(fā)一個UI控件庫是極其困難的,所以我們需要掌握依賴開發(fā)的知識

  • 創(chuàng)建Framework工程
  • 參數(shù)設(shè)置:參考如上第二章節(jié)
  • 創(chuàng)建驗證工程
  • 關(guān)閉Framework工程
  • 添加Framework工程的xxxx.xcodeproj到驗證工程并連接到靜態(tài)庫如圖操作:若未找到庫,對庫進行編譯
    添加Framework工程的xxxx.xcodeproj到驗證工程并連接到靜態(tài)庫
  • 導入庫的公開頭文件,對驗證工程進行編譯
如果工程無法聯(lián)想出Framework頭文件,導入路徑形式如下:
#import <LibLoaderFramework/PublicHeader.h>

像這樣使用嵌套工程的好處是你可以對庫本身做出修改,而不用離開示例工程,即使你同時改變兩個地方的代碼也一樣。每次你編譯工程,你都要檢查是否將頭文件的public/project關(guān)系設(shè)置正確。如果實例工程中缺失了任何需要的頭文件,它都不能被編譯。

五、使用腳本創(chuàng)建Framework庫

  • 創(chuàng)建.a的靜態(tài)庫工程
    (創(chuàng)建方式與參數(shù)配置參照第一節(jié)不再贅述)
  • 使用腳本創(chuàng)建Framework目錄結(jié)構(gòu),此時不包含二進制文件
  • 添加 New Run Script Phases
  • 雙擊面板標題欄Run Script,重命名為Build Framework。
    • 這個面板允許你在構(gòu)建時運行一個Bash腳本
    • 你希望讓腳本在build的過程中何時執(zhí)行,就把這個面板拖動到列表中相對應(yīng)的那一位置。
    • 對于該framework工程來說,腳本最后執(zhí)行,因此你可以讓它保留在默認的位置即可。


      使用腳本創(chuàng)建Framework目錄結(jié)構(gòu)
#set –e確保腳本的任何地方執(zhí)行失敗,則整個腳本都執(zhí)行失敗。
set -e

#導出framework路徑
export FRAMEWORK_LOCN="${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework"

# 創(chuàng)建當前版本真實頭文件夾
mkdir -p "${FRAMEWORK_LOCN}/Versions/A/Headers"

# 創(chuàng)建引用路徑
/bin/ln -sfh A "${FRAMEWORK_LOCN}/Versions/Current"

/bin/ln -sfh Versions/Current/Headers "${FRAMEWORK_LOCN}/Headers"

/bin/ln -sfh "Versions/Current/${PRODUCT_NAME}" \
"${FRAMEWORK_LOCN}/${PRODUCT_NAME}"

# 拷貝公共頭文件到framework中
/bin/cp -a "${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/" \ 
"${FRAMEWORK_LOCN}/Versions/A/Headers"

#######################簡化目錄也可用使用如下腳本#######################

#set –e確保腳本的任何地方執(zhí)行失敗,則整個腳本都執(zhí)行失敗。
set -e

#導出的文件路徑
export FRAMEWORK_LOCN="${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework"

# 創(chuàng)建真是文件路徑
mkdir -p "${FRAMEWORK_LOCN}/Headers"

# 拷貝公共頭文件到framework中
/bin/cp -a "${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/" \
"${FRAMEWORK_LOCN}/Headers"
這個腳本做了如下三個操作:
1.創(chuàng)建了libLoader.framework/Versions/A/Headers目錄
2.創(chuàng)建了一個framework所需要的三個連接符號([symbolic links](http://en.wikipedia.org/wiki/Symbolic_link))

當前版本文件夾
Versions/Current => A
頭文件夾
Headers => Versions/Current/Headers
二進制文件
libLoader => Versions/Current/libLoader

3.將公共頭文件從你之前定義的公共頭文件路徑拷貝到Versions/A/Headers目錄下,-a參數(shù)確保修飾次數(shù)作為拷貝的一部分不會改變,防止不必要的重新編譯。
構(gòu)建成功后的Framework目錄
  • 多架構(gòu)(Multi-Architecture)編譯
    解決Framework或.a庫合并的煩惱,此處用的是.a工程,使用Framework工程類似
  • iOS app需要在許多不同的CPU架構(gòu)下運行:
 arm7: 在最老的支持iOS7的設(shè)備上使用
 arm7s: 在iPhone5和5C上使用 
 arm64: 運行于iPhone5S的64位 ARM 處理器 上
 i386: 32位模擬器上使用
 x86_64: 64為模擬器上使用

每個CPU架構(gòu)都需要不同的二進制數(shù)據(jù),當你編譯一個應(yīng)用時,無論你目前正在使用那種架構(gòu),Xcode都會正確地依照對應(yīng)的架構(gòu)編譯。例如,如果你想跑在虛擬機上,Xcode只會編譯i386版本(或者是64位機的x86_64版本)。
這意味著編譯會盡可能快地進行,當你歸檔一款app或者構(gòu)建app的發(fā)布版本(release mode)時,Xcode會構(gòu)建上述三個用于真機的ARM架構(gòu)。因此這樣app就可以跑在所有設(shè)備上了。不過,其他的編譯架構(gòu)又如何呢?讓我們一起往下走

  • 創(chuàng)建 Aggregate 集合
    點擊目標工程 > 添加新目標 > Cross-Platform > Aggregate > next > 命名為Framework


    命名為Framework

為什么使用集合(Aggregate)目標來創(chuàng)建一個framework呢?為什么這么不直接?因為OS X對庫的支持更好一些,事實上,Xcode直接為每一個OS X工程提供一個Cocoa Framework編譯目標?;诖?,你將使用集合編譯目標,作為Bash腳本的連接串來創(chuàng)建神奇的framework目錄結(jié)構(gòu)。
你是不是開始覺得這個方法有些懵逼了?

  • 添加依賴庫
    為了確保每當這個新的framework目標被創(chuàng)建時,靜態(tài)鏈接庫都會被編譯,你需要往靜態(tài)庫目標中添加依賴(Dependency)。在庫工程中選擇Framework目標,在Build Phases中添加一個依賴。展開Target Dependencies面板,添加


    添加依賴庫
  • 添加多平臺編譯腳本
    這個目標的主要編譯部分是多平臺編譯,你將使用一個腳本來做到這一點。和你之前做的一樣
    選擇Framework目標 >> Build Phases >> 左側(cè) “+” 按鈕 >> New Run Script Phases >> 命名MultiPlatform Build
    ![MultiPlatform Build


  • 寫入編譯framewo編譯腳本

    #set –e確保腳本的任何地方執(zhí)行失敗,則整個腳本都執(zhí)行失敗。
    set -e

    #標示 如果已經(jīng)插入腳本 退出
    if [ -n "$IYQ_MULTIPLATFORM_BUILD_IN_PROGRESS" ]; then
    exit 0
    fi
    export IYQ_MULTIPLATFORM_BUILD_IN_PROGRESS=1

    # 自定義變量
    IYQ_FRAMEWORK_NAME=${PROJECT_NAME}
    IYQ_INPUT_STATIC_LIB="lib${PROJECT_NAME}.a"
    IYQ_FRAMEWORK_LOCATION="${BUILT_PRODUCTS_DIR}/${IYQ_FRAMEWORK_NAME}.framework"

    #構(gòu)建靜態(tài)庫 傳參 "${1}"
    function build_static_library {
    # 重新構(gòu)建庫
        xcrun xcodebuild -project "${PROJECT_FILE_PATH}" \
        -target "${TARGET_NAME}" \
        -configuration "${CONFIGURATION}" \
        -sdk "${1}" \
        ONLY_ACTIVE_ARCH=NO \
        BUILD_DIR="${BUILD_DIR}" \
        OBJROOT="${OBJROOT}" \
        BUILD_ROOT="${BUILD_ROOT}" \
        SYMROOT="${SYMROOT}" $ACTION
    }

    #合并
    function make_fat_library {

        xcrun lipo -create "${1}" "${2}" -output "${3}"
    }

    # 1 正則判斷 真機還是模擬器 (iphoneos/iphonesimulator)
    if [[ "$SDK_NAME" =~ ([A-Za-z]+) ]]; then
    IYQ_SDK_PLATFORM=${BASH_REMATCH[1]}
    else
    echo "Could not find platform name from SDK_NAME: $SDK_NAME"
    exit 1
    fi

    # 2 SDK版本
    if [[ "$SDK_NAME" =~ ([0-9]+.*$) ]]; then
    IYQ_SDK_VERSION=${BASH_REMATCH[1]}
    else
    echo "Could not find sdk version from SDK_NAME: $SDK_NAME"
    exit 1
    fi

    # 3 其他平臺判斷 如果 則 否則
    if [ "$IYQ_SDK_PLATFORM" == "iphoneos" ]; then
    IYQ_OTHER_PLATFORM=iphonesimulator
    else
    IYQ_OTHER_PLATFORM=iphoneos
    fi

    # 4 其他平臺路徑
    if [[ "$BUILT_PRODUCTS_DIR" =~ (.*)$IYQ_SDK_PLATFORM$ ]]; then
    IYQ_OTHER_BUILT_PRODUCTS_DIR="${BASH_REMATCH[1]}${IYQ_OTHER_PLATFORM}"
    else
    echo "Could not find other platform build directory."
    exit 1
    fi

    #調(diào)用上面構(gòu)建函數(shù) 如果當前運行的是真機則構(gòu)建模擬器
    build_static_library "${IYQ_OTHER_PLATFORM}${IYQ_SDK_VERSION}"

    # 如果你現(xiàn)在正在為模擬器編譯,那么Xcode會默認只在該系統(tǒng)對應(yīng)的結(jié)構(gòu)下編譯,例如i386 或 x86_64。為了在這兩個結(jié)構(gòu)下都進行編譯,這里調(diào)用了build_static_library,基于iphonesimulator SDK重新編譯,確保這兩個結(jié)構(gòu)都進行了編譯。
    if [ "$RW_SDK_PLATFORM" == "iphonesimulator" ]; then
    build_static_library "${SDK_NAME}"
    fi

    # 合并庫
    make_fat_library "${BUILT_PRODUCTS_DIR}/${IYQ_INPUT_STATIC_LIB}" \
    "${IYQ_OTHER_BUILT_PRODUCTS_DIR}/${IYQ_INPUT_STATIC_LIB}" \
    "${IYQ_FRAMEWORK_LOCATION}/${IYQ_FRAMEWORK_NAME}"

    # 確保文件存在 相當于-dpR,保持文件的連接(d),保持原文件的屬性(p)并作遞歸處理(R)
    cp -a "${IYQ_FRAMEWORK_LOCATION}/${IYQ_FRAMEWORK_NAME}" \
    "${IYQ_OTHER_BUILT_PRODUCTS_DIR}/${IYQ_FRAMEWORK_NAME}.framework/${IYQ_FRAMEWORK_NAME}"

    # 拷貝到指定目錄下
    ditto "${IYQ_FRAMEWORK_LOCATION}" "${SRCROOT}/BuildFramework/${IYQ_FRAMEWORK_NAME}.framework"
  • 在工程目錄下的BuildFramework文件下查看,并導入工程驗證
    #import <libLoader/LoaderProgressView.h>

    BuildFramework在工程目標下

  • SDK存在圖片,xib等資源文件的情況

  • 添加bundle目標工程

  • bundle創(chuàng)建詳細操作參考第三節(jié)內(nèi)容

  • bundle目標工程進行編譯

  • 添加bundle資源庫依賴


    添加bundle資源庫依賴
  • 如果想把你的編譯包copy到指定位置,在腳本后面加入如下代碼

  # 拷貝bundle到指定目錄下
  ditto "${BUILT_PRODUCTS_DIR}/${IYQ_FRAMEWORK_NAME}.bundle" \
  "${SRCROOT}/BuildFramework/${IYQ_FRAMEWORK_NAME}.bundle"

六、swift 工程如何創(chuàng)建Framework庫

  • swift支持靜態(tài)庫嗎?

  • iOS 8已經(jīng)開放了動態(tài)庫的權(quán)限。

  • Swift 不在支持靜態(tài)庫,這也就間接放棄了 iOS 7。

  • 項目中如果使用了自制的動態(tài)庫,能否上傳到AppStore?

  • 創(chuàng)建的動態(tài)庫需要在 General >> Embedded Binaries 中添加才能使用

  • 蘋果把這種 Framework 稱為 Embedded Framework。

  • 我們創(chuàng)建的這個動態(tài)庫其實也不能給其他程序使用,只能是在我們的 App Extension 和 APP 之間共用。所有這種情況對 AppStore 上架沒有影響,可以正常發(fā)布。

  • 創(chuàng)建swift語言的Framework項目

  • 對外公開的 方法和類 需要添加 public 前綴

    對外公開的方法需要添加 `public` 前綴

    注意:如果還允許 **override **和繼承的話,可以使用 **open **關(guān)鍵字。(關(guān)于訪問控制的詳細說明,可以參考我之前的這篇文章:Swift - 訪問控制(fileprivate,private,internal,public,open)

  • 分別在真機和模擬器上編譯
    為客戶提供使用的正式包請選擇release模式下編譯

  • 合并Framework二進制文件

終端命令
cd 到Products目錄
真機和模擬器上的庫文件合并 
lipo -create xx/aa.framework/aa oo/aa.framework/aa -output aa
查看SDK支持的架構(gòu)
lipo -info LibLoaderFramework
  • 合并Mudules目錄下的內(nèi)容
  • 最后Framework的目錄結(jié)果


    image.png
  • 導入工程進行驗證
    因為是動態(tài)庫,此處也需要導入,否則工程會崩潰
    image.png

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

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

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