前言
翻譯已與 raywenderlich 社區(qū)取得聯(lián)系(可翻譯10篇文章)抒钱,原文鏈接
是否想過(guò)把參與過(guò)的多個(gè)項(xiàng)目中功能相近的代碼拆分成可復(fù)用的模塊呢铆,是否想過(guò)與其他開(kāi)發(fā)者分享你寫的模塊贷屎?
也許你想像 iOS SDK 按功能來(lái)組織 API 一樣來(lái)模塊化你的代碼罢防,也許也想像知名三方庫(kù)那樣發(fā)布自己的代碼。
通過(guò)這篇文章你將會(huì)學(xué)會(huì)如何創(chuàng)建 Framework 以及如何進(jìn)行發(fā)布唉侄。
iOS 8咒吐,Xcode 6 中,蘋果提供了一種新的開(kāi)發(fā)模板属划,Cocoa Touch Framework恬叹。這使得創(chuàng)建 Framework 更加容易。
Framework 有一下三個(gè)主要目的:
- 代碼封裝
- 代碼模塊化
- 代碼復(fù)用
你可以在你的其他 App 中同眯,團(tuán)隊(duì)成員绽昼,或 iOS 社區(qū)分享你的 Framework。swift 的訪問(wèn)控制機(jī)制使得 framework 在代碼模塊之間提供了健壯可靠的接口须蜗。
swift 中硅确,module 是作為一個(gè)編譯發(fā)布的代碼單元。framework 和 App 都是一種 module明肮。
在這篇教程中菱农,我們將會(huì)拆解一個(gè)已存在的 App 為例子,通過(guò)下面的步驟把部分代碼拆分出來(lái)打包成 framework :
- 為 rings widget 創(chuàng)建一個(gè)新的 framework
- 將代碼和測(cè)試單元移植到 framework 中
- 導(dǎo)入 framework 到 App 中
- 打包成 cocoapods
- 為你的 framework 設(shè)置代碼倉(cāng)庫(kù)
完成上面步驟后柿估,你已經(jīng)成功將該 App 中的部分代碼打包成了可移植的 framework循未。
開(kāi)始
Phonercise 是一款簡(jiǎn)單的呈現(xiàn)蘋果手表 Activity 應(yīng)用數(shù)據(jù)的 App,另外還會(huì)記錄你手機(jī)的物理狀態(tài)秫舌。主界面的三個(gè)環(huán)分別代表移動(dòng)的妖,站立,運(yùn)動(dòng)足陨。
該項(xiàng)目需要在真機(jī)上進(jìn)行調(diào)試嫂粟,并打開(kāi)音量,開(kāi)始吧钠右。
移動(dòng)手機(jī)赋元,搖晃手機(jī),保持站立來(lái)分別記錄移動(dòng)飒房,運(yùn)動(dòng)搁凸,站立的數(shù)據(jù)。
該 App 的邏輯如下:
- ActionViewController 包含 view 的生命周期管理和動(dòng)作邏輯狠毯。
- 所有包含視圖邏輯的文件都在 Three Ring View 這個(gè)文件夾下护糖。該文件夾下有管理視圖的 ThreeRingView.swift 類,管理音頻的 Fanfare.swift 類嚼松,和管理管理自定義視圖的其他類嫡良。
下面開(kāi)始將環(huán)的控制打包成可復(fù)用的 framework锰扶。
創(chuàng)建 Framework
framework 是自包含,可復(fù)用的代碼和其他資源的組織單元寝受。你可以將 framework 導(dǎo)入其他 App 中坷牛,甚至可以在 iOS,tvOS很澄,watchOS 和 macOS 跨平臺(tái)使用京闰。
如果你使用過(guò)其他編程語(yǔ)言,你應(yīng)該聽(tīng)過(guò)節(jié)點(diǎn)模塊甩苛,包蹂楣,gems,jars 等等讯蒲。framework 是 Xcode 對(duì)于包或者模塊的實(shí)現(xiàn)方式痊土。比如 iOS SDK 中通用的 framework:Foundation, UIKit, AVFoundation, CloudKit 等。
設(shè)置 Framework
Xcode 6˙中開(kāi)始新增了 Cocoa Touch Framework 代碼模板墨林,這使得創(chuàng)建 framework 變得非常容易赁酝。首先創(chuàng)建 framework 的項(xiàng)目。
- Xcode 中萌丈,通過(guò) File/New/Project 創(chuàng)建一個(gè)新項(xiàng)目赞哗。
- 選擇 iOS/Framework & Library/Cocoa Touch Framework 創(chuàng)建一個(gè)新的 framework。
- 點(diǎn)擊 Next
- 設(shè)置 Product Name 為 ThreeRingControl辆雾。使用你自己的 Organization Name 和 Organization Id恩替覅而肪笋。點(diǎn)擊 Include Unit Tests。這樣項(xiàng)目將會(huì)包含測(cè)試單元來(lái)確保項(xiàng)目中沒(méi)有 bug度迂。
- 點(diǎn)擊 Next
- 在文件選擇框中藤乙,選擇在 Phonercise 項(xiàng)目同級(jí)目錄中創(chuàng)建項(xiàng)目。
- 點(diǎn)擊 Create
現(xiàn)在已成功創(chuàng)建了一個(gè) framework惭墓。
添加代碼和資源
現(xiàn)在你的 framework 中還沒(méi)有代碼坛梁。從 Phonercise 項(xiàng)目中把以下八個(gè)文件拖拽到當(dāng)前項(xiàng)目中:
- CircularGradient.swift
- coin07.mp3
- Fanfare.swift
- RingLayer.swift
- RingTip.swift
- ThreeRingView.swift
- Utilities.swift
- winning.mp3
點(diǎn)擊了 Copy items if needed,確保文件被拷貝進(jìn)了新項(xiàng)目而不是只添加了文件的引用腊凶。framework 需要自己的源碼文件而不是文件引用划咐。
編譯,確保編譯沒(méi)有任何警告和錯(cuò)誤钧萍。
將 Framework 添加到項(xiàng)目中
回到 Phonercise 項(xiàng)目中褐缠。刪除 Three Ring View 組下的六個(gè)文件和 Helper Files 文件夾下兩個(gè) MP3 文件。點(diǎn)擊 Move to Trash风瘦。
編譯队魏,出現(xiàn) “Use of undeclared type 'ThreeRingView” 錯(cuò)誤信息。
Phonercise 項(xiàng)目導(dǎo)航器中右鍵万搔,點(diǎn)擊 Add Files to "Phonercise"胡桨。在文件選擇器中選擇 ThreeRingControl.xcodeproj官帘。這樣把 ThreeRingControl.xcodeproj 作為子項(xiàng)目添加進(jìn)來(lái)。
注意:也可以直接添加 ThreeRingControl.framework 到項(xiàng)目中昧谊。然而添加整個(gè)項(xiàng)目會(huì)讓同時(shí)開(kāi)發(fā) framework 和 App 變得更容易刽虹。你對(duì) framework 項(xiàng)目做的任何改變都將自動(dòng)應(yīng)用到 App 上。
雖然這兩個(gè)項(xiàng)目在同一工作空間中揽浙,Phonercise 仍然無(wú)法訪問(wèn) ThreeRingControl状婶。
通過(guò)鏈接 framework 到 App 的 target 能夠解決這個(gè)問(wèn)題意敛。打開(kāi) ThreeRingControl 項(xiàng)目的 Products 文件夾馅巷,里面有一個(gè) ThreeRingControl.framework 文件。該文件打包了二進(jìn)制代碼草姻,頭文件钓猬,資源等。
點(diǎn)擊 Phonercise 項(xiàng)目的項(xiàng)目導(dǎo)航器撩独,點(diǎn)擊 Phonercise target敞曹,選擇 General tab。
滾動(dòng)到 Embedded Binaries 選擇综膀。把 ThreeRingControl.xcodeproj Products 文件夾下的 ThreeRingControl.framework 拖拽到該選項(xiàng)中澳迫。
這樣同時(shí)為 Embedded Binaries 和 Linked Frameworks and Binaries 添加了 framework 的入口。
這樣 App 就知道如何查找該 framework剧劝,編譯橄登,出現(xiàn)更多相同錯(cuò)誤。
訪問(wèn)控制
此時(shí)雖然 framework 已經(jīng)是該項(xiàng)目的一部分了讥此,但該項(xiàng)目代碼仍然無(wú)法訪問(wèn)拢锹。
進(jìn)入 ActionViewController.swift,在該文件的頂部添加如下代碼進(jìn)行導(dǎo)入萄喳。
import ThreeRingControl
導(dǎo)入后仍然沒(méi)有解決錯(cuò)誤信息卒稳。因?yàn)?swift 使用了訪問(wèn)控制權(quán)限來(lái)讓開(kāi)發(fā)者決定哪些東西可以暴露給其他用戶。
swift 默認(rèn)使用 internal 訪問(wèn)控制權(quán)限他巨,這使得代碼僅在模塊內(nèi)可見(jiàn)充坑。
雖然很麻煩,但訪問(wèn)控制權(quán)限讓開(kāi)發(fā)者能夠隱藏核心功能以防被修改染突,或者顯示的通過(guò) internal 來(lái)暴露給其他用戶捻爷。
swift 有三個(gè)等級(jí)的訪問(wèn)控制權(quán)限。通過(guò)下面的規(guī)則來(lái)進(jìn)行選擇:
- Public: 對(duì) App 或其他 framework 可見(jiàn)觉痛。
- Internal: 對(duì)該 framework 可見(jiàn)
- Fileprivate: 對(duì)該編譯文件可以見(jiàn)
- Private: 對(duì)該類可見(jiàn)
創(chuàng)建 Cocoapod 源
創(chuàng)建 Pod
在終端進(jìn)入到 ThreeRingControl 目錄下役衡。運(yùn)行下面命令:
pod spec create ThreeRingControl
該命令會(huì)在當(dāng)前目錄下創(chuàng)建 ThreeRingControl.podsepc 文件。該模板文件描述了 pod 以及如何進(jìn)行編譯薪棒。通過(guò) vi 打開(kāi)手蝎。
該模板文件包含大量注釋和通用設(shè)置建議
- 使用下面代碼替換 Spec Metadata:
s.name = "ThreeRingControl"
s.version = "1.0.0"
s.summary = "A three-ring control like the Activity status bars"
s.description = "The three-ring is a completely customizable widget that can be used in any iOS app. It also plays a little victory fanfare."
s.homepage = "http://raywenderlich.com"
2.該 iOS framework 使用了 MIT 協(xié)議榕莺,使用下面的代碼替換 Spec License:
s.license = "MIT"
3.該 framework 僅用于 iOS 平臺(tái),使用下面的代碼替換 Platform Specifics:
s.platform = :ios, "10.0"
4.使用下面代碼替換 Source Location棵介。當(dāng)你想通過(guò) pod 進(jìn)行發(fā)布钉鸯,需要將這里替換成 GitHub repo 的地址和提交的 tag。
s.source = { :path => '.' }
5.使用下面代碼替換 Source Code:
s.source_files = "ThreeRingControl", "ThreeRingControl/**/*.{h,m,swift}"
6.添加 Resources 項(xiàng):
s.resources = "ThreeRingControl/*.mp3"
這樣可以把音頻文件包含進(jìn) framework 的 bundle 中邮辽。
7.刪除 Project Linking 和 Project Setting 項(xiàng)唠雕。
8.指定該 pod 代碼使用的 swift 版本號(hào)。
s.pod_target_xcconfig = { 'SWIFT_VERSION' => '3' }
9.刪除多余的注釋(注釋以#開(kāi)頭)
使用 Pod
這一節(jié)會(huì)帶領(lǐng)你完成最后一步吨述,發(fā)布 pod 到 GitHub岩睁。
發(fā)布到 Pod
創(chuàng)建代碼倉(cāng)庫(kù)
如果你還沒(méi)有 GitHub 賬號(hào),創(chuàng)建賬號(hào).
創(chuàng)建一個(gè)托管該 pod 代碼的新倉(cāng)庫(kù)揣云。把該倉(cāng)庫(kù)命名為 ThreeRingControl捕儒,也可以使用任何其他名字。確保 .gitignore 選項(xiàng)為 swift license 為 MIT邓夕。
點(diǎn)擊創(chuàng)建倉(cāng)庫(kù)刘莹。
克隆倉(cāng)庫(kù)
回到終端創(chuàng)建一個(gè)新的文件夾。下面的命令會(huì)創(chuàng)建一個(gè)名為 repo 的文件夾焚刚。
mkdir repo
cd repo
克隆剛才創(chuàng)建的 GitHub 倉(cāng)庫(kù)点弯。替換下面命令中 URL 為 GitHub 倉(cāng)庫(kù)的鏈接。
git clone URL
這會(huì)創(chuàng)建一個(gè) Git 文件夾矿咕,并把之前創(chuàng)建的 README 和 LICENSE 文件克隆下來(lái)抢肛。
把代碼拷貝到克隆下來(lái)的文件夾中
把 ThreeRingControl 文件夾中的文件拷貝到 repo/ThreeRingControl 文件夾中。
打開(kāi)拷貝的 ThreeRingControl.podsepc痴腌,更新 s.source 信息:
s.source = { :git => "URL", :tag => "1.0.0" }
把 URL 設(shè)置你的 GitHub 上代碼倉(cāng)庫(kù)鏈接雌团。
提交代碼
提交并把代碼 push 到 GitHub 上。
cd ThreeRingControl/
git add .
git commit -m "initial commit"
git push
打標(biāo)記
運(yùn)行下面命令給倉(cāng)庫(kù)打上標(biāo)記士聪,以便 Podspec 能夠匹配锦援。
git tag 1.0.0
git push --tags
歡迎關(guān)注我的簡(jiǎn)書,我會(huì)定期做一些技術(shù)分享:)