你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> Cocoapods 應用第一部分

Cocoapods 應用第一部分

編輯:IOS開發基礎

1.jpg

問題的提出:

隨著項目的越來越大,可能會出現好幾個團隊共同維護一個項目的情況,例如:項目組A負責其中的A塊,項目組B負責其中的B塊.....這幾塊彼此之間既獨立,也相互聯系.對於這種情況,可以采用約定的方式,比如,你只修改你那塊,不要修改公共的.如果要修改公共的,那麼必須要通知一下其它組,大家共同決定怎麼修改,這種方式有一個很大的問題,很有可能不經意間就改了別的團隊的代碼.還有維護的越來越復雜等.

諸如此類的問題,很自然的我們會考慮每個團隊建立一個靜態庫

iOS的靜態庫有兩種,.a和.framework,  動態庫.framework居多.   靜態庫建議也生成.framework模式的,好處是.framework包含了相關的.h文件等..a文件還要自己添加相關的.h文件

靜態庫:鏈接時,靜態庫會被完整地復制到可執行文件中,被多次使用就有多份冗余拷貝.例如我們在我們的程序中使用了百度地圖的.a文件,另外一個應用也使用了百度地圖.a.這樣整個系統中,會出現兩個 百度地圖.a文件

動態庫:鏈接時不復制,程序運行時由系統動態加載到內存,供程序調用,系統只加載一次,多個程序共用,節省內存.系統提供的庫基本上都屬於此類,例如UIKit等,A應用和B應用中都用到了UIKit,系統只加載了一份在內存中.IOS中對於第三方的動態庫,很遺憾,目前還不支持的.

一:framework的制作

從xcode6開始,已經提供了制作.framework的選項了

blob.png

下面我們用系統自帶的來新建.framework.然後再添加一個依賴庫 AFNetworking

1) xcode的菜單欄  File -> New Project  建立一個名為  YohunlUtilsLib 的Cocoa Touch Framework的工程. 將Target 改為 7.0(由於現在大多數應用都還要支持7.0sdk,故此處我們修改為支持7.0)

這時候,編譯一下,你可能會遇到警告

blob.png

(null): Embedded dylibs/frameworks only run on iOS 8 or later

別著急,這個是由於 從IOS8開始,建立的framework可以是動態的(並不是完全意義上的動態,這裡的動態,其實還是要嵌入到我們的應用中,而不能夠從網上下載,然後用dlopen動態加載的).

我們要修改 Mach-O Type.從默認的Dynamic Library 改為 Static Library,再編譯,警告消失

blob.png

那麼選擇 Dynamic Library 還是   Static Library 有什麼影響呢? 我已經實際的檢驗過了.(我采用了一個包含了 第三方庫 AFnetworking的測試工程)

Static Library 支持IOS8.0 sdk以下的,從目前來看,大多數工程都還要支持7.0 sdk,所以我們最常用的就是Static Library

當我們使用   Static Library時候,生成的framework直接如同添加普通文件的形式添加進來就可以了.它會自動在

blob.png

不過當我們運行的時候,會提示:

當生成後,添加到示例工程中,

blob.png

好吧,這種模式的添加,看來有些問題呀,還要自己添加依賴庫,這些依賴庫都是系統的,根據提示自己添加就可以了

再運行,OK

當我們使用 Dynamic Library模式(只有iOS8.0及以上才支持)的時候.如同普通文件一樣添加到示例工程中去的話,運行,會出現提示:

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

blob.png

解決的方式

在工程的配置  Embedded Binaries下面添加.而不是在 Linked Frameworks and Libraries下添加.這種方式,不需要添加 AFNetworking所需要的系統庫,這一點不知道是什麼原因!!!如果有知道原因的,請也告知我一下啊

blob.png

再運行,OK

2)  命令行,進入目錄下  pod init 建立一個podfile文件,因為我們制作的.framework需要用到AFNetworking網絡庫 PS:你也可以用任意的方式建立這個podfile文件

打開它,因為我采用 pod init命令建立的,打開後你會發現它已經有內容了

blob.png

修改其內容為

platform :ios, '7.0'
inhibit_all_warnings!
target 'YohunlUtilsLib' do
pod 'AFNetworking'
end
target 'YohunlUtilsLibTests' do
end

再執行 pod install 建立依賴

打開工程,添加一個文件  YONetwork.h,在其中添加方法

@interfaceYONetwork :NSObject
/**
*  獲取github上用戶的repo
*
*  @paramuser   用戶名
*  @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

blob.png

編譯運行 (command + B),生成相應的.framework文件

菜單 -  organizer

blob.png

可以看到目錄結構如下:

blob.png

其中的 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文件

分離後,如圖:

blob.png

可以看到,最後的.framework中,並沒有包含我們pod添加的 AFNetworking.所以 當我們把我們生成的YohunlUtilsLib.framework給別人使用過的時候,別人自己要在項目中添加 AFNetworking,否則會提示找不到的錯誤.

驗證的方式可以參見 http://jiapumin.iteye.com/blog/2119102  主要是利用命令

3) 我們使用命令來合並我們生成的真機和模擬器的framework

建立一個新的target

blob.png

target建立後

blob.png

添加如下的合並模擬器和真機的腳本

# 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}"

blob.png

對於以上的腳本,其中用到了很多的 xcode預定義的變量,這些變量怎麼來的呢?你可以在命令行下, 輸入

xcodebuild -workspace YohunlUtilsLib.xcworkspace -scheme YohunlUtilsLib -sdk iphonesimulator -configuration Debug -showBuildSettings > xcodebuild_showBuildSettings.txt

來將所有的xcode預定義變量都導入到文本xcodebuild_showBuildSettings.txt 中,然後你就可以選用你需要的啦

當然了,我們一般都應該合並release模式的,而不是debug模式的framework,這個可以在

blob.png

blob.png

ccmmand+B 編譯

如果不出錯的話,應該會彈出

blob.png

到此處,我們的framework建立好了,下面可以建立一個測試工程來測試一下,是否可以了

4)建立一個single View Application的測試上述framework的工程 TestFrameworkDemo

將上一步生成的 Release-universal/YohunlUtilsLib.framework 加入到工程 TestFrameworkDemo

再寫一個測試用例:

blob.png

運行,這時候,你會收到錯誤提示

blob.png

還記得前面說過吧,我們打包的framework並不包含

此時,我們有兩種方式解決這個問題:

1. 將我們生成 YohunlUtilsLib.framework 過程中生成的libAFNetworking.a 拷貝過來,添加到工程中(當然了,你要自己合並 libAFNetworking的真機和模擬器的.a文件) [這種方式的好處是可以保證我們的YohunlUtilsLib.framework使用到的libAFNetworking和我們一樣的版本,保證了兼容性,,但同時也增加了集成的復雜性,我們要申明我們的framework用到了哪些第三方和第三方的版本信息]

2.在TestFrameworkDemo 工程中,增加 podFile文件,在其中加入 依賴  pod 'AFNetworking'

重新pod install一下 [推薦這種方式,因為,我們用到的第三方都可以使用pod管理,方便],下面就以這種方法來說明

blob.png

運行,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生成的示例工程結構什麼的,會有點不一樣,比如最新的帶有demo的生成的lib工程就本身就是target的名字,但是之前版本target的名字是 名字_example

pod lib create 工程名  使會讓你確認4個問題,由此來建立工程,4個問題都是很簡單的,你可以自行選擇

blob.png

blob.png

注意到了沒?這裡我們的 YohunlUtilsPod 目錄下,並沒有podfile文件,那麼我們建立的庫要怎麼依賴第三方的啊.這裡就是 YohunlUtilsPod.podspec 文件出場了,在這個文件中,可以制定我們生成的framework依賴於什麼.有關於spec文件,是關鍵文件,原則上,只要我們把這個文件交給別人,別人就可以添加我們的lib到工程裡了

blob.png

編輯YohunlUtilsPod.podspec 文件(此文件實際上是 ruby格式的,如果你用ruby相關的編輯器打開,就能高亮顯示了),修改內容為

Pod::Spec.new do |s|
s.name             = "YohunlUtilsPod"
s.version          = "1.0.0"
s.summary          = "測試pod生成framework的YohunlUtilsPod."
s.description      = "測試用的,我們用來測試使用pod lib create 生成的framework工程"
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/'
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

blob.png

如果提示錯誤的話,它會給出詳細的提示,你照著修改就好了,備注:我已經將源碼上傳到了github上(你也可以上傳你的私有git服務器,一般公司都應該有自己的git服務器)

更改完後,在工程中再加入  YONetwork.h和.YONetwork.m

blob.png

再運行 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腳本 ,運行它,得到

blob.png

建立一個測試工程

blob.png

注意上面圖裡面的文字,此處因為我們的framework工程采用dynamic 模式的(上文有論述!!!)  所以需要在Embedded Binaries下添加相應的庫.至於為什麼還要添加 AFNetworking.framework,上面也有論述,是因為我們打包的.framework並沒有包含AFNetworking.framework,如果不加上,運行起來,還是要報錯的哦

好了,第一部分講完了

那麼我們怎麼使用 像我們使用其它開源庫那樣的,只要在demo工程裡添加一句

pod ‘YohunlUtilsPod' 然後pod install一下就可以添加呢?(當然了,這種方式,我們一般是直接源碼模式的framework加入demo工程)

這就是第二部分要講的.

參考文檔:

  • http://maxao.free.fr/xcode-plugin-interface/build-settings.html#variables

  • https://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/XcodeBuildSettingRef/0-Introduction/introduction.html

  • http://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/

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved