一步步建立本身的 iOS 框架

建立你的第一個iOS框架

若是你曾經試圖去建立一個本身的iOS框架的話,你應該知道這件事並非那些畏懼困難的人可以成功完成的-畢竟管理依賴和編寫測試並不容易。這篇文章將從開始到最終完成一步步的進行講解,以便你掌握後能夠更好的建立本身的框架。html

在教程中咱們會構建一個框架,框架裏面會暴露一個名爲RGBUIColor(red:green:blue)的函數,該函數會返回使用這些參數建立的UIColor對象。咱們會使用Swift語言,而且使用Carthage做爲依賴項的管理工具。咱們的框架將會支持經過CarthageCocoaPods或者git來使用。ios

讓咱們開始吧!git

建立Xcode工程

  1. 選擇 File -> New -> Projectgithub

  2. 在左側的選擇 iOS -> Framework & Library,右側選擇「Cocoa Touch Framework」。編程

  3. 點擊「下一步」,並填寫選項提示。確保以及勾選了「Include Unit Tests」。
    swift

  4. 選擇工程保存的位置。segmentfault

  5. 不要勾選「Create Git repository on My Mac」,咱們在後面手動進行設置。xcode

  6. 點擊「建立」而且打開工程。架構

  7. 選擇File -> Save As Workspace並使用工程相同的名字保存到相同的目錄中。之因此建立workspace是由於咱們須要添加Carthage中的依賴做爲子模塊;使用Xcode
    編譯他們的時候必須是在一個workspace中。app

  8. 選擇File -> Close Project關閉工程。

  9. 而後選擇File -> Open打開*workspace*文件。

  10. Xcode左上角的scheme並選擇「Manage Schemes」。咱們須要確保sheme勾選了「shared」,以便能使用「Carthage」來構建工程

初始化git

首先,切換到工程所在的目錄。

  1. 運行git init初始化空版本庫。

  2. 建立一個 .gitignore的文件。該文件會過濾一些Xcode或者依賴文件中一些咱們不想也不須要上傳的文件。

這裏是一個標準的Swift工程的gitignore文件,咱們只是添加了.DS_Store並移除了fastlane和一些多餘的部分。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

## OS X Finder

.DS_Store

 

## Build generated

build/

DerivedData

 

## Various settings

*.pbxuser

!default.pbxuser

*.mode1v3

!default.mode1v3

*.mode2v3

!default.mode2v3

*.perspectivev3

!default.perspectivev3

xcuserdata

 

## Other

*.xccheckout

*.moved-aside

*.xcuserstate

*.xcscmblueprint

 

## Obj-C/Swift specific

*.hmap

*.ipa

 

# Swift Package Manager

.build/

 

# Carthage

Carthage/Build

添加Carthage和依賴項

  1. 在工程的文件目錄下建立一個名爲Cartfile的文件以及運行時的依賴性。咱們添加**Curry]**([連接)

    github "thoughtbot/Curry"

  2. 建立一個名爲Cartfile.private的文件。它會負責私有的一些依賴就像咱們的測試框架同樣。咱們使用QuickNimble

    1

    2

    github "Quick/Quick"

    github "Quick/Nimble"

  3. 新建bin/setup腳本。它能夠提供一個簡單的方式來處理依賴和工程,不管時對於貢獻者仍是咱們本身。

    1

    2

    3

    mkdir bin

    touch bin/setup

    chmod +x bin/setup

  4. 打開bin/setup並將一下代碼加入:

    1

    2

    3

    4

    5

    6

    7

    #!/usr/bin/env sh

       if ! command -v carthage > /dev/null; then

           printf 'Carthage is not installed.n'

           printf 'See https://github.com/Carthage/Carthage for install instructions.n'

       exit 1

       fi  

       carthage update --platform iOS --use-submodules --no-use-binaries

在這個腳本里面,咱們假設用戶一句安裝了Carthage連接,而後咱們使用update命令來安裝那些依賴項。

咱們使用–use-submodules,全部那些依賴項會以子模塊的方式被添加。當用戶須要的時候,他就能夠直接使用咱們的框架而不須要使用Carthage。咱們使用了–no-use-binaries,全部這些依賴項都會在咱們本身的系統上進行編譯。

bin/setup建好後,咱們直接在終端運行腳本讓Cartfile自行下載依賴項。

如今咱們就能夠設置咱們的工程而且編譯這些依賴項了。

添加依賴到工做區

由於咱們的依賴是做爲子模塊,咱們須要將這些自模塊添加到工做區。

1.打開Carthage/Checkouts而後將每一個依賴項的.xcodeproj添加到工做區。你可使用直接拖拽到項目的工做區。

添加完結束後:

連接運行時依賴

  1. 在工做區的導航欄選擇」RGB」 ,而後在中間選擇」RGB」目標,進而選擇」Build Phases」,展開」Link binary with libraries」。

  2. 點擊」+」而後選擇Curry.framework框架的Curry-iOS

  3. 點擊添加。

連接開發依賴項

  1. 在中間的工具欄選擇」RGBTests」。

  2. 使用上面同樣的步驟,將」Quick」和」Nimble」框架添加到」Link binary with libraries」。
    當咱們將依賴添加到兩個目標的時候,Xcode會自動在」Build Settings」下添加」Framework Search Paths」。咱們能夠在」RGB」和」RGBTests」中移除,由於同處同一工做區, Xcode將他們自己的一部分。

  3. 選擇目標下的兩個目標,選中」Build Settings」下的」Framework Search Paths」,而後按「退格鍵」刪除。

  4. 接下來,在導航欄選擇」RGB」工程的時候,你就會看見下面you三個剛剛添加的三個框架。而後全選這三個框架,而後右擊選擇」New group from selection」而後將他們放到一個組裏, 我將組命名爲」Frameworks」。

如今Carthage已經設置完成,接下來是CocoaPods

添加CocoaPods支持

爲了添加CocoaPods支持,咱們須要在工程的根目錄新建.podspec,而且包含工程的信息。

  1. 新建RGB.podspec文件。

  2. 將下面的實例拷貝並複製到文件中(自行對照修改相應的部分)。

  3. 使用項目的信息來設置那些選項。更多的選項詳情連接,可是該工程中你所須要的那些選擇以下。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

Pod::Spec.new do |spec|

  spec.name = "RGB"

  spec.version = "1.0.0"

  spec.summary = "Sample framework from blog post, not for real world use.Functional JSON parsing library for Swift."

  spec.homepage = "https://github.com/jakecraige/RGB"

  spec.license = { :type => 'MIT', :file => 'LICENSE' }

  spec.authors = {

    "Jake Craige" => 'james.craige@gmail.com',

    "thoughtbot" => nil,

  }

  spec.social_media_url = "http://twitter.com/thoughtbot"      

  spec.source = { :git => "https://github.com/jakecraige/RGB.git", :tag => "v#{spec.version}", :submodules => true }

  spec.source_files  ="RGB/**/*.{h,swift}"

  spec.requires_arc = true

  spec.platform     = :ios

  spec.ios.deployment_target = "9.1"    

  spec.dependency "Curry", '~> 1.4.0'

end

這裏面須要注意到的一行是spec.dependency 「Curry」, ‘~> 1.4.0′。由於咱們須要支持CocoaPods,咱們假設框架的使用者會使用CocoaPods而不是Carthage
全部咱們咱們在最後一行也聲明依賴而不只僅只在Carthfile聲明。

當咱們設置好了以後,咱們在終端中運行pod lib lint命令測試全部的東西是否是都配置好了。若是沒錯的話,咱們能看見以下的提示:

當工程的依賴項設置好後,咱們就能夠寫代碼了。可是在咱們開始以前,先提交代碼。

1

git commit -am "Project and dependencies set up"

編寫第一個測試

打開RGBTests/RGBTests.swift文件,你能夠看見一個默認的模版。她使用了@testableXCTest(,可是接下來咱們會做出一些調整。

首先,咱們會移除@testable,由於咱們須要測試那些框架使用者可能調用的API接口。隨着框架的增加,咱們可能會須要@testable去測試那些不是做爲公共接口暴露的部分;總的來講,就是咱們想避免測試那些暴露給使用者的接口。這個特性在測試應用的時候會更加有效,而不是在框架測試中。

來源於蘋果關於測試部分的文檔:

伴隨者可測試性,你係那種可以在Swift 2.0框架和應用中編寫測試而且不須要要測試全部的internalpublic部分。在XCTest目標而不是其餘框架或者應用的測試代碼中
使用@testable import {ModuleName}

咱們使用QuickNimble做測試。Quick提供以一個行爲驅動類型的測試接口,與RSpecSpecta很是相近;Nimble給咱們提供了強大的斷言以及少許模版就能寫成異步代碼的能力。

寫完以後,代碼以下:

1

2

3

4

5

6

7

8

9

10

11

12

13

import Quick

import Nimble

import RGB

 

class RGBTests: QuickSpec {

    override func spec() {

        describe("RGB") {

            it("works") {

                expect(true).to(beTrue())

            }

        }

    }

}

使用快捷鍵CMD + U或者Product -> Test運行測試代碼,會顯示測試成功。

因此,到如今已經完成了!

開玩笑而已。讓咱們來一些真正的測試。

咱們暴露一個RGBUIColor(red: 195, green: 47, blue: 52)調用接口,接口會返回一個漂亮的thoughtbot red的UIColor。

代碼以下:

1

2

3

4

5

6

7

8

9

10

11

12

13

describe("RGBUIColor") {

    it("is a correct representation of the values") {

        let thoughtbotRed = UIColor(

            red: CGFloat(195/255),

            green: CGFloat(47/255),

            blue: CGFloat(52/255),

            alpha: 1

        )

        let color = RGBUIColor(red: 195, green: 47, blue: 52)

 

        expect(color).to(equal(thoughtbotRed))

    }

}

若是你此時運行此時的話,會像預料中的那樣-失敗。由於Swift語言的類型檢查會組織咱們運行一個沒有定義的RGBUIColor函數。接下來讓咱們完成它。

編寫實現代碼

右擊RGB選擇新建一個文件。建立一個名爲RGBUIColor.swift的文件,並將下面的代碼拷貝過去。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

import Curry

 

func RGBUIColor(red red: Int, green: Int, blue: Int) -> UIColor {

    return curry(createColor)(red)(green)(blue)

}

 

private func createColor(red: Int, green: Int, blue: Int) -> UIColor {

    return UIColor(

        red: CGFloat(red/255),

        green: CGFloat(green/255),

        blue: CGFloat(blue/155),

        alpha: 1

    )

}

這裏使用Curry做爲一個運行時的依賴性的例子來使用。這裏採用了一個不標準的使用斌強沒有提供任何值。讓咱們繼續測試!

第一眼看過去,咱們可能會感到很奇怪。咱們明明已經定義了RGBUIColor函數啊?

確實咱們定義了該函數可是,咱們並無將她聲明爲public

這意味着,若是有人繫有人使用咱們的框架的話,他們是不能使用這個函數接口的。若是你想看見什麼不一樣的話,將@testable添加回來,你會發現你的測試經過了。

經過這個錯誤咱們就知道爲何要在iomport前面將@testable移除。這能讓咱們在發佈框架以前更好的捕捉到錯誤。

讓咱們將函數聲明爲public,來修復這個問題。運行測試,問題解決了。而後咱們提交代碼。

1

git commit -am "Completed my first iOS framework!"

原文出處: Jake Craige   譯文出處:BNCoding(@BigNerdCoding ) 

問啊-定製化IT教育平臺,牛人一對一服務,有問必答,開發編程社交頭條 官方網站:www.wenaaa.com


QQ羣290551701 彙集不少互聯網精英,技術總監,架構師,項目經理!開源技術研究,歡迎業內人士,大牛及新手有志於從事IT行業人員進入!

相關文章
相關標籤/搜索