- 存放類的地方
- 存放圖片資源的地方
- 打包生成的方式
第一步:創(chuàng)建一個新的"Cocoa Touch Static Library"工程
Static Library生成的是libSerenity.a的靜態(tài)庫文件.
而我們最終要生成的是Serenity.framework的方式.
創(chuàng)建:
第二步:創(chuàng)建主框架的頭文件
如果你希望其他開發(fā)者以<Serenity/Serenity.h> 的方式來使用你自己的靜態(tài)庫.那么你需要確保你的項目中包含該頭文件.例如:
#import <Foundation/Foundation.h>
#import <Serenity/Widget.h>
(ps : Widget.h 是你項目中的其他文件)
一旦你創(chuàng)建了framew得頭文件,你需要將這些頭文件列為"public"的狀態(tài).
第三步 : 更新Public類型頭文件的地址
默認情況下,靜態(tài)庫項目將私人的和public頭文件復制在同一文件夾路徑下: /usr/local/include. 為了避免錯誤的將私人標題復制到我們的框架,我們想確保我們的public頭文件復制到一個單獨的目錄中. 例如 :$(PROJECT_NAME)Headers. 要去修改這些設定.
編譯后
修改后
$(PROJECT_NAME)Headers
再次編譯
接下來考慮: 添加一些新的資源到Framework
不管你什么時候要添加一些新的類,你將要考慮是否將這些.h文件是否置為public的狀態(tài),因為默認是Project的狀態(tài),默認不會拷貝到你剛剛創(chuàng)建的自定義的頭文件路徑.
這里添加一個新的NewSource的類測試.
測試結(jié)果:
第四步 : Disable Code Stripping
We do not want to strip any code from the library; we leave this up to the application that is linking to the framework. To disable code stripping we must modify the following configuration settings:
"Dead Code Stripping" => No (for all settings)
"Strip Debug Symbols During Copy" => No (for all settings)
"Strip Style" => Non-Global Symbols (for all settings)
第五步 : 開啟所有architecture支持
我們需要我們的framework可以用于所有的不同設備,所有不同的架構體系
"Build Active Architecture Only" => No (for all settings)
第六步: 生成架構(以framework的形式)
首先 : 創(chuàng)建文件目錄布局
set -e
mkdir -p "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Versions/A/Headers"
# Link the "Current" version to "A"
/bin/ln -sfh A "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Versions/Current"
/bin/ln -sfh Versions/Current/Headers "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Headers"
/bin/ln -sfh "Versions/Current/${PRODUCT_NAME}" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/${PRODUCT_NAME}"
# The -a ensures that the headers maintain the source modification date so that we don't constantly
# cause propagating rebuilds of files that import these headers.
/bin/cp -a "${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Versions/A/Headers"
編譯生成
生成的目錄結(jié)構:
Serenity.framework/
Headers/ -> Versions/Current/Headers
Serenity -> Versions/Current/Serenity
Versions/
A/
Headers/
Serenity.h
Widget.h
Current -> A
接下來: 生成Framework的發(fā)布目標
-
創(chuàng)建一個新的Aggregate 目標
-
添加Static Library作為獨立的目標
-
修改配置Architecture
-
構建其他平臺
添加腳本
set -e
set +u
# Avoid recursively calling this script.
if [[ $SF_MASTER_SCRIPT_RUNNING ]]
then
exit 0
fi
set -u
export SF_MASTER_SCRIPT_RUNNING=1
SF_TARGET_NAME=${PROJECT_NAME}
SF_EXECUTABLE_PATH="lib${SF_TARGET_NAME}.a"
SF_WRAPPER_NAME="${SF_TARGET_NAME}.framework"
# The following conditionals come from
# https://github.com/kstenerud/iOS-Universal-Framework
if [[ "$SDK_NAME" =~ ([A-Za-z]+) ]]
then
SF_SDK_PLATFORM=${BASH_REMATCH[1]}
else
echo "Could not find platform name from SDK_NAME: $SDK_NAME"
exit 1
fi
if [[ "$SDK_NAME" =~ ([0-9]+.*$) ]]
then
SF_SDK_VERSION=${BASH_REMATCH[1]}
else
echo "Could not find sdk version from SDK_NAME: $SDK_NAME"
exit 1
fi
if [[ "$SF_SDK_PLATFORM" = "iphoneos" ]]
then
SF_OTHER_PLATFORM=iphonesimulator
else
SF_OTHER_PLATFORM=iphoneos
fi
if [[ "$BUILT_PRODUCTS_DIR" =~ (.*)$SF_SDK_PLATFORM$ ]]
then
SF_OTHER_BUILT_PRODUCTS_DIR="${BASH_REMATCH[1]}${SF_OTHER_PLATFORM}"
else
echo "Could not find platform name from build products directory: $BUILT_PRODUCTS_DIR"
exit 1
fi
# Build the other platform.
xcrun xcodebuild -project "${PROJECT_FILE_PATH}" -target "${TARGET_NAME}" -configuration "${CONFIGURATION}" -sdk ${SF_OTHER_PLATFORM}${SF_SDK_VERSION} BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}" SYMROOT="${SYMROOT}" $ACTION
# Smash the two static libraries into one fat binary and store it in the .framework
xcrun lipo -create "${BUILT_PRODUCTS_DIR}/${SF_EXECUTABLE_PATH}" "${SF_OTHER_BUILT_PRODUCTS_DIR}/${SF_EXECUTABLE_PATH}" -output "${BUILT_PRODUCTS_DIR}/${SF_WRAPPER_NAME}/Versions/A/${SF_TARGET_NAME}"
# Copy the binary to the other architecture folder to have a complete framework in both.
cp -a "${BUILT_PRODUCTS_DIR}/${SF_WRAPPER_NAME}/Versions/A/${SF_TARGET_NAME}" "${SF_OTHER_BUILT_PRODUCTS_DIR}/${SF_WRAPPER_NAME}/Versions/A/${SF_TARGET_NAME}"
重要提示 :
- 你可以在這里修改你的打包生成的Framework的名稱
SF_TARGET_NAME=${PROJECT_NAME}
- 你可以修改為
SF_TARGET_NAME=Serenity
- 如果你有使用Cocoapods,你需要編譯workspace 而不是project,如果你需要修改workspace相關內(nèi)容,你可以修改一下腳本代碼
xcrun xcodebuild ONLY_ACTIVE_ARCH=NO -workspace "${PROJECT_DIR}/${PROJECT_NAME}.xcworkspace" -scheme "${TARGET_NAME}" -configuration "${CONFIGURATION}" -sdk ${SF_OTHER_PLATFORM}${SF_SDK_VERSION} BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}" SYMROOT="${SYMROOT}" $ACTION
PS : 注意修改workspace setting.修改為legacy build system即可
構建與驗證
編譯Aggregate.
打開終端
lipo -info /Users/liliguang/...../Serenity.framework/Serenity(文件直接拖到終端)
終端打印信息
Architectures in the fat file: /Users/liliguang/...../Serenity.framework/Serenity are: i386 armv7 x86_64 arm64
需要注意的是: 在這里面編譯生成之后是沒有包含armv7s, 關于iPhone5,5c的架構是armv7s,我測試過是在iPhone5,5c上運行也是沒有問題的.最好也自己測試一下.
Resources and Bundles (資源包)
-
第一步 : 創(chuàng)建Bundle
-
第二步 : 設置Bundle
默認的設置只配置了Mac OS X
修改打包的Bundle Name
-
第三步 : 移除 HIDPI Mac OS X Build 設定
我們創(chuàng)建了一個OS X包,它包括并且選擇合并HIDPI(視網(wǎng)膜和non-retina)媒體資源.tiff文件.你不希望這種行為,你需要禁用它,否則你將無法加載映像資產(chǎn)包。
簡單來說,你現(xiàn)在加載了Bundle中的資源.同時項目中也可以通過assets中加載.避免沖突.你將所有的資源全部放在Bundle中使用.因為這是給別人使用的內(nèi)容.
-
給Bundle中添加資源
無論你什么會后添加資源,請選擇Bundle
-
第四步 : 添加Bundle到你的Aggregate中
-
第五步 : 讀取Bundle資源
// Load the framework bundle.
+ (NSBundle *)frameworkBundle {
static NSBundle* frameworkBundle = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
NSString* mainBundlePath = [[NSBundle mainBundle] resourcePath];
NSString* frameworkBundlePath = [mainBundlePath stringByAppendingPathComponent:@"Bundle.bundle"];
frameworkBundle = [NSBundle bundleWithPath:frameworkBundlePath];
});
return frameworkBundle;
}
代碼自己簡單研究下就可以了.
注意路徑正確就好@"Bundle.bundle"
如果你的項目中需要資源. 你在發(fā)布的時候,需要將.framework與.bundle一起發(fā)給其他開發(fā)者.開發(fā)者直接拖動這兩個文件到他們項目中就可以了...
(這里有個想法,能不能只拖動一個就可以了呢???)
思考其他Framework :
1.需不需要Bundle?也就是有沒有相關的登錄界面的UI素材?
2.有沒有包含資源在一起的Framework創(chuàng)建方式?
我自己對比了一下,其他的SDK,其中也有很多關于Bundle在里面,應該也是和這種方式類似.
也有其他的創(chuàng)建Framework的方式,比如cocoa touch Framework,可以創(chuàng)建靜態(tài)庫和動態(tài)庫.這種方式適合于純方法創(chuàng)建.不適合帶有UI的Framework. 擇優(yōu)選擇吧.
總結(jié)
當開發(fā)一個框架時,滿足你想減少構建時間同時確保你的內(nèi)容大致匹配你的第三方開發(fā)者磺箕。我們實現(xiàn)這一平衡,只是構建static library,把static library當做像framework一樣使用匈织。