1. 程式人生 > >cocoapods應用第一部分-xcode創建.framework相關

cocoapods應用第一部分-xcode創建.framework相關

all 輸入 一次 oot 不出 模擬 builds bject pos

問題的提出: 隨著項目的越來越大,可能會出現好幾個團隊共同維護一個項目的情況,比如:項目組A負責當中的A塊,項目組B負責當中的B塊.....這幾塊彼此之間既獨立,也相互聯系.對於這樣的情況,能夠採用約定的方式,比方,你僅僅改動你那塊,不要改動公共的.假設要改動公共的,那麽必需要通知一下其他組,大家共同決定怎麽改動,這樣的方式有一個非常大的問題,非常有可能不經意間就改了別的團隊的代碼.還有維護的越來越復雜等. 諸如此類的問題,非常自然的我們會考慮每一個團隊建立一個靜態庫 IOS的靜態庫有兩種,.a和.framework, 動態庫.framework居多. 靜態庫建議也生成.framework模式的,優點是.framework包括了相關的.h文件等..a文件還要自己加入相關的.h文件 靜態庫:鏈接時,靜態庫會被完整地拷貝到可運行文件裏。被多次使用就有多份冗余拷貝.比如我們在我們的程序中使用了百度地圖的.a文件,另外一個應用也使用了百度地圖.a.這樣整個系統中,會出現兩個 百度地圖.a文件
動態庫:鏈接時不復制,程序執行時由系統動態載入到內存,供程序調用,系統僅僅載入一次,多個程序共用。節省內存.系統提供的庫基本上都屬於此類,比如UIKit等,A應用和B應用中都用到了UIKit,系統僅僅載入了一份在內存中.IOS中對於第三方的動態庫,非常遺憾,眼下還不支持的. 一:framework的制作 從xcode6開始,已經提供了制作.framework的選項了 技術分享 以下我們用系統自帶的來新建.framework.然後再加入一個依賴庫 AFNetworking 1) xcode的菜單條 File -> New Project 建立一個名為 YohunlUtilsLib 的Cocoa Touch Framework的project. 將Target 改為 7.0(因為如今大多數應用都還要支持7.0sdk,故此處我們改動為支持7.0) 技術分享

這時候,編譯一下,你可能會遇到警告 技術分享
(null): Embedded dylibs/frameworks only run on iOS 8 or later
別著急,這個是因為 從IOS8開始,建立的framework可以是動態的(並非全然意義上的動態,這裏的動態,事實上還是要嵌入到我們的應用中,而不可以從網上下載,然後用dlopen動態載入的).
我們要改動 Mach-O Type.從默認的Dynamic Library 改為 Static Library,再編譯,警告消失 技術分享

那麽選擇 Dynamic Library 還是 Static Library 有什麽影響呢? 我已經實際的檢驗過了.(我採用了一個包括了 第三方庫 AFnetworking的測試project)
Static Library 支持IOS8.0 sdk下面的,從眼下來看,大多數project都還要支持7.0 sdk,所以我們最經常使用的就是Static Library 當我們使用 Static Library時候,生成的framework直接如同加入普通文件的形式加入進來就能夠了.它會自己主動在 技術分享




只是當我們執行的時候,會提示: 當生成後,加入到演示樣例project中,
技術分享

好吧,這樣的模式的加入,看來有些問題呀,還要自己加入依賴庫,這些依賴庫都是系統的,依據提示自己加入就能夠了 再執行,OK


當我們使用 Dynamic Library模式(僅僅有IOS8.0及以上才支持)的時候.如同普通文件一樣加入到演示樣例project中去的話,執行,會出現提示: dyld: Library not loaded: @rpath/NetTestLib.framework/NetTestLib
Referenced from: /Users/yohunl/Library/Developer/CoreSimulator/Devices/B1DBCA26-C113-4C74-BB81-297D4AF1E0C8/data/Containers/Bundle/Application/C1B4F6D5-96FD-4245-8E6D-4F1C569EEF6F/TestFramework.app/TestFramework
Reason: image not found
技術分享

解決的方式 在project的配置 Embedded Binaries以下加入.而不是在 Linked Frameworks and Libraries下加入.這樣的方式,不須要加入 AFNetworking所須要的系統庫,這一點不知道是什麽原因!!!假設有知道原因的,請也告知我一下啊 技術分享

再執行,OK

2) 命令行,進入文件夾下 pod init 建立一個podfile文件,由於我們制作的.framework須要用到AFNetworking網絡庫 PS:你也能夠用隨意的方式建立這個podfile文件 打開它,由於我採用 pod init命令建立的,打開後你會發現它已經有內容了 技術分享
改動其內容為 platform :ios, ‘7.0‘ inhibit_all_warnings!
target ‘YohunlUtilsLib‘ do pod ‘AFNetworking‘ end
target ‘YohunlUtilsLibTests‘ do end
再運行 pod install 建立依賴 打開project,加入一個文件 YONetwork.h,在當中加入方法 @interfaceYONetwork :NSObject
/**
*
獲取github上用戶的repo
*
*
@paramuser username
*
@paramsuccess成功的回調
*
@paramfailure失敗的回調
*/

- (
void)getGithubReposForUser:(NSString*)user withSuccess:(void(^)(idresponseObject))success failure:(void(^)(NSError*error))failure;


/**
*
測試 getGithubReposForUser:withSuccess:failure
*/

- (
void)test; @end #import"YONetwork.h"
#import
"AFNetworking.h"
@implementationYONetwork
- (
void)getGithubReposForUser:(NSString*)user withSuccess:(void(^)(idresponseObject))success failure:(void(^)(NSError*error))failure
{
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManagermanager];
[manager
GET:[NSStringstringWithFormat:@"https://api.github.com/users/%@/repos", user] parameters:nilsuccess:^(AFHTTPRequestOperation*operation,id responseObject) {
success(responseObject);
}
failure:^(AFHTTPRequestOperation*operation,NSError*error) {
failure(error);
}];
}


- (
void) test {
[
selfgetGithubReposForUser:@"yohunl"withSuccess:^(idresponseObject) {
NSLog(@"getGithubReposForUser response = %@",responseObject);
}
failure:^(NSError*error) {
NSLog(@"getGithubReposForUser error = %@",error);
}];
}
@end 技術分享

編譯執行 (command + B),生成對應的.framework文件 菜單 - organizer 技術分享
能夠看到文件夾結構例如以下: 技術分享
當中的 YohunlUtilsLib.framework 就是我們要的 : 註意,YohunlUtilsLib.framework中並沒有包括AFNetworking庫的內容,這一點我們能夠用例如以下的命令來驗證. 命令進入 Debug-iphoneos $ lipo -info YohunlUtilsLib.framework/YohunlUtilsLib 輸出 Architectures in the fat file: YohunlUtilsLib.framework/YohunlUtilsLib are: armv7 arm64 說明我們生成的真機framework:YohunlUtilsLib.framework 包括了兩種架構 armv7 arm64 分離出每一種架構 $ mkdir armV7 當前文件夾建立文件夾,用於存放分離後的架構,和分離出的.o文件 $ lipo YohunlUtilsLib.framework/YohunlUtilsLib -thin armv7 -output ./armv7/YohunlUtilsLib_armv7 分離出armv7架構到目錄armV7下 $ cd armV7 進入目錄 $ ar -x YohunlUtilsLib_armv7 分離出armv7架構的全部的.o文件 分離後,如圖: 技術分享
能夠看到,最後的.framework中,並沒有包括我們pod加入的 AFNetworking.所以 當我們把我們生成的YohunlUtilsLib.framework給別人使用過的時候,別人自己要在項目中加入 AFNetworking,否則會提示找不到的錯誤. 驗證的方式能夠參見 http://jiapumin.iteye.com/blog/2119102 主要是利用命令
3) 我們使用命令來合並我們生成的真機和模擬器的framework 建立一個新的target
技術分享
target建立後 技術分享
加入例如以下的合並模擬器和真機的腳本
# Constants
SF_TARGET_NAME=${PROJECT_NAME}
#自己定義的用來存放最後合並的framework
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal



#IPHONE_DEVICE_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos

WORKSPACE_NAME=${PROJECT_NAME}.xcworkspace
YO_SCHEME=${PROJECT_NAME}

#clean build是先清除原來的build
xcodebuild -workspace ${WORKSPACE_NAME} -scheme ${YO_SCHEME} -sdk iphonesimulator -configuration
"${CONFIGURATION}"clean build
xcodebuild -workspace ${WORKSPACE_NAME} -scheme ${YO_SCHEME} -sdk iphoneos -configuration
"${CONFIGURATION}"clean build

# build project
#xcodebuild -project "${PROJECT_FILE_PATH}" -target "${TARGET_NAME}" -configuration "${CONFIGURATION}" -sdk iphoneos BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}" CONFIGURATION_BUILD_DIR="${IPHONE_DEVICE_BUILD_DIR}/arm64" SYMROOT="${SYMROOT}" ARCHS=‘arm64‘ VALID_ARCHS=‘arm64‘ $ACTION

#xcodebuild -project "${PROJECT_FILE_PATH}" -target "${TARGET_NAME}" -configuration "${CONFIGURATION}" -sdk iphoneos BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}" CONFIGURATION_BUILD_DIR="${IPHONE_DEVICE_BUILD_DIR}/armv7" SYMROOT="${SYMROOT}" ARCHS=‘armv7 armv7s‘ VALID_ARCHS=‘armv7 armv7s‘ $ACTION

# Copy the framework structure to the universal folder (clean it first)
#由於framework的合並,lipo僅僅是合並了最後的二進制可運行文件,所以其他的須要我們自己復制過來
#先移除原來的
rm -rf
"${UNIVERSAL_OUTPUTFOLDER}"
mkdir -p
"${UNIVERSAL_OUTPUTFOLDER}"
cp -R
"${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework"

#合並模擬器和真機的架構
lipo -create
"${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}""${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"-output"${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}"

open
"${UNIVERSAL_OUTPUTFOLDER}"




技術分享


對於以上的腳本,當中用到了非常多的 xcode提前定義的變量,這些變量怎麽來的呢?你能夠在命令行下, 輸入 xcodebuild -workspace YohunlUtilsLib.xcworkspace -scheme YohunlUtilsLib -sdk iphonesimulator -configuration Debug -showBuildSettings > xcodebuild_showBuildSettings.txt 來將全部的xcode提前定義變量都導入到文本xcodebuild_showBuildSettings.txt 中,然後你就能夠選用你須要的啦
當然了,我們一般都應該合並release模式的,而不是debug模式的framework,這個能夠在 技術分享
技術分享

ccmmand+B 編譯 假設不出錯的話,應該會彈出 技術分享

到此處,我們的framework建立好了,以下能夠建立一個測試project來測試一下,能否夠了
4)建立一個single View Application的測試上述framework的project TestFrameworkDemo 將上一步生成的 Release-universal/YohunlUtilsLib.framework 增加到project TestFrameworkDemo 再寫一個測試用例: 技術分享

執行,這時候,你會收到錯誤提示 技術分享
還記得前面說過吧,我們打包的framework並不包括 此時,我們有兩種方式解決問題: 1. 將我們生成 YohunlUtilsLib.framework 過程中生成的libAFNetworking.a 拷貝過來,加入到project中(當然了,你要自己合並 libAFNetworking的真機和模擬器的.a文件) [這樣的方式的優點是能夠保證我們的YohunlUtilsLib.framework使用到的libAFNetworking和我們一樣的版本號,保證了兼容性,,但同一時候也添加了集成的復雜性,我們要申明我們的framework用到了哪些第三方和第三方的版本號信息] 2.在TestFrameworkDemo project中,添加 podFile文件,在當中添加 依賴 pod ‘AFNetworking‘ 又一次pod install一下 [推薦這樣的方式,由於,我們用到的第三方都能夠使用pod管理,方便],以下就以這樣的方法來說明 技術分享

執行,OK!!! 源代碼在 https://github.com/yohunl/TestFrameworkDemo.git framework在 https://github.com/yohunl/YohunlUtilsLib.git
二:使用 pod 的命令 pod lib create 來創建 使用pod的framework 採用cocoapods自帶的命令,比較方便的http://guides.cocoapods.org/making/using-pod-lib-create 比如 pod lib create BZLib.能夠自帶demo的 命令例如以下 pod lib create YohunlUtilsPod 註意:各個版本號的cocoapods生成的演示樣例project結構什麽的,會有點不一樣,比方最新的帶有demo的生成的libproject就本身就是target的名字,可是之前版本號target的名字是 名字_example
pod lib create project名 使會讓你確認4個問題,由此來建立project,4個問題都是非常easy的,你能夠自行選擇 技術分享
技術分享


註意到了沒?這裏我們的 YohunlUtilsPod 文件夾下,並沒有podfile文件,那麽我們建立的庫要怎麽依賴第三方的啊.這裏就是 YohunlUtilsPod.podspec 文件出場了,在這個文件裏,能夠制定我們生成的framework依賴於什麽.有關於spec文件,是重要文件,原則上,僅僅要我們把這個文件交給別人,別人就能夠加入我們的lib到project裏了 技術分享

編輯YohunlUtilsPod.podspec 文件(此文件實際上是 ruby格式的,假設你用ruby相關的編輯器打開,就能高亮顯示了),改動內容為 Pod::Spec.new do |s|
s.name = "YohunlUtilsPod"
s.version = "1.0.0"
s.summary = "
測試pod生成frameworkYohunlUtilsPod."

s.description = "
測試用的,我們用來測試使用pod lib create 生成的frameworkproject"

s.homepage = "https://github.com/yohunl/YohunlUtilsPod"
# s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2"
s.license = ‘MIT‘
s.author = { "yohunl" => "[email protected]" }
s.source = { :git => "https://github.com/yohunl/YohunlUtilsPod.git", :tag => s.version.to_s }

# s.social_media_url = ‘https://twitter.com/<TWITTER_USERNAME>‘

s.platform = :ios, ‘7.0‘
s.requires_arc = true

s.source_files = ‘Pod/Classes/**/*‘
s.resource_bundles = {
‘YohunlUtilsPod‘ => [‘Pod/Assets/*.png‘]
}

# s.public_header_files = ‘Pod/Classes/**/*.h‘
# s.frameworks = ‘UIKit‘, ‘MapKit‘
s.dependency ‘AFNetworking‘
end 驗證podspec文件是否正確是使用命令 在podspec所在文件夾下運行 pod lib lint 技術分享
假設提示錯誤的話,它會給出具體的提示,你照著改動就好了,備註:我已經將源代碼上傳到了github上(你也能夠上傳你的私有gitserver,一般公司都應該有自己的gitserver)
更改完後,在project中再增加 YONetwork.h和.YONetwork.m
技術分享 再執行 pod install 假設提示 SZ-lingdaiping:Example yohunl$ pod install
Updating local specs repositories
Analyzing dependencies
Fetching podspec for `YohunlUtilsPod` from `../`
[!] Unable to satisfy the following requirements:

- `YohunlUtilsPod (from `../`)` required by `Podfile`
- `YohunlUtilsPod (from `../`)` required by `Podfile` - `YohunlUtilsPod (= 0.1.0)` required by `Podfile.lock`
那麽刪掉 Podfile.lock文件,由於我們更改了podspec文件中的庫的版本了
看到沒,是在 Development Pods目錄下,由於並沒有上傳到官方去,所以,在此處是 私有的,所以在Development Pods目錄下 .
接下來,如同第一個一樣,加入一個新的target,加入 run script腳本 ,執行它,得到 技術分享
建立一個測試project 技術分享
註意上面圖裏面的文字,此處由於我們的frameworkproject採用dynamic 模式的(上文有論述!!!) 所以須要在Embedded Binaries下加入對應的庫.至於為什麽還要加入 AFNetworking.framework,上面也有論述,是由於我們打包的.framework並沒有包括AFNetworking.framework,假設不加上,執行起來,還是要報錯的哦
好了,第一部分講完了 那麽我們怎麽使用 像我們使用其他開源庫那樣的,僅僅要在demoproject裏加入一句 pod ‘YohunlUtilsPod‘ 然後pod install一下就能夠加入呢?(當然了,這樣的方式,我們通常是直接源代碼模式的framework加入demoproject)
這就是第二部分要講的.


參考文檔: http://maxao.free.fr/xcode-plugin-interface/build-settings.html#variables ttps://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/XcodeBuildSettingRef/0-Introduction/introduction.html ttp://outofmemory.cn/shell/learn-shell-in-30-minutes/ http://www.cnblogs.com/wendingding/p/3893095.html http://www.cnblogs.com/brycezhang/p/4117180.html http://wenva.github.io/2015/07/08/創建自己的CocoaPods私有倉庫.html http://insert.io/framework-ios8-xcode6/







cocoapods應用第一部分-xcode創建.framework相關