从零开始,打造自己的首个 iOS 框架

如果你曾试图创建自己的iOS框架,你知道这不是一个头脑发热作出的决定 — 管理依赖以及写测试用例一点也不简单。本教程将会带你从头到尾创建你的第一个iOS框架,让你可以创建自己的框架。

我们将在框架暴露一个名为 RGBUIColor(red:green:blue) 的函数,这个函数根据参数返回一个新的UIColor。我们将使用 Swift 创建它,并使用 Carthage 作为依赖管理器。在 Carthage、CocoaPods 或者 git submodules 中都可以使用我们的框架。

让我们开始吧!

设置 Xcode 工程

  • 选择 File → New → Project。
  • 在左边栏选择 iOS → Framework & Library,然后在右侧选择 “Cocoa Touch Library”。
  • 点击“Next”并且填写弹出的选项。确保勾选了“Include Unit Tests”复选框。

  • 选择工程的保存位置。
  • 取消选择“在我的 Mac 上创建 Git 版本库”,我们稍后将手动创建它。
  • 点击“创建”,工程将在 Xcode 中打开。
  • 转到File → Save As Workspace,使用同样的名字将你的 Xcode 工程保存到相同的路径下。我们之所以将工程放到工作区中,是因为我们将把Carthage依赖作为子模块加入进来;Xcode必须确保它们在一个工作区中才能 build 它们。
  • 用 File → Close Project 关闭 Xcode 工程。
  • 用 File → Open 打开工作区。
  • 点击 Xcode 左上方的 scheme 并选择“Manage Schemes”。我们需要将我们的 scheme 标记为“shared”,以便工程可以用Carthage构建。

    https://github.com/Carthage/Carthage#share-your-xcode-schemes

  • 定位到“RGB”scheme,选中“Shared”复选框然后点击“Close”。

让我们移步到终端去。

初始化 Git

首先,导航到你存储工程所在的目录。

  • 运行 git init 来初始化一个空的版本库。
  • 创建一个.gitignore,将我们不希望在git中追踪的一些讨厌的Xcode文件和依赖文件排除出去。

这里是一个稍作修改的,Swift工程使用的标准的.gitignore文件。

https://github.com/github/gitignore/blob/master/Swift.gitignore

我们增加了.DS_Store,并删除了fastlane和多余的注释。

.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 和依赖

  • 在你的工程目录下创建一个名为 Cartfile 的文件,并添加运行时依赖。我们将添加 Curry。

github "thoughtbot/Curry"

  • 创建一个 Cartfile.private 文件。它将包含私有的依赖,例如我们的测试框架。我们将使用 Quick 和 Nimble。

github "Quick/Quick"

github "Quick/Nimble"

  • 创建一个 bin/setup 脚本。它用来给我们的贡献者(以及我们)一个简单的方法来设置工程以及依赖。

mkdir bin

touch bin/setup

chmod +x bin/setup

  • 打开 bin/setup,写入如下内容:

#!/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 命令来安装iOS依赖。

我们使用了 --use-submodules 已使我们的依赖作为子模块被添加进来。这样当用户希望脱离 Carthage 的时候,也能使用我们的框架。我们使用 --no-use-binaries,这样我们的依赖就是在我们的系统上 build 的。

bin/setup创建好之后,让我们运行它,以便Carthage下载我们的依赖。

  • 在终端中运行 bin/setup。

现在我们需要设置我们的工程,来构建和链接新的依赖。

向工作区添加依赖

因为我们的依赖是一些子模块,我们需要把他们添加到我们的工作区。

打开 Carthage/Checkouts,然后把每一项依赖的.xcodeproj 添加到工作区的根目录。可以把他们从 Finder 拖入 Xcode 工程的导航器。

当你完成之后,导航器应该看起来像这样:

链接运行时依赖

  • 在导航器中选择“RGB”并且在中间的工具条选择“RGB”目标,选择“Build Phases”选项卡并展开“Link binary with libraries”小节。
  • 点击“+”图标并从 Curry-iOS 目标中选择 Curry.framework。
  • 点击“Add”。

链接开发依赖

  • 在中间的工具条选择“RGBTests”目标。
  • 使用跟上文相同的过程,在该目标的“Link binary with libraries”小节添加 Quick 以及 Nimble 框架。当我们在每个目标添加依赖的时候,Xcode 会自动将他们添加到“Build Settings”选项卡的“Framework Search Paths”中。我们可以将它们从“RGB”和“RGBTests”目标中移除,由于是在相同的工作区中,Xcode将他们看作隐式依赖。
  • Select the target, locate the “Framework Search Paths” setting, highlight it, and press “backspace” on your keyboard.
  • 选择该目标,定位到“Framework Search Paths”设置,使其高亮,然后点击键盘上的退格键。

  • 接着,看一下导航器中的“RGB”工程;你将会看见根级有三个新的框架。为了保持这个区域有序,高亮所有这三项,右击并选择“New group from selection”,将它们放入一个有名字的组。我将给我的组取名“Frameworks”。

    现在 Carthage 设置好了,让我们添加 CocoaPods。

添加 CocoaPods 支持

要添加 CocoaPods 支持,我们需要在工程的根目录创建一个 .podspec 文件,并且写入我们的工程信息。

  • 创建一个名为 RGB.podspec 的文件。
  • 把下面的示例复制粘贴到该文件中。
  • 在选项中填入你工程的细节。有更多的选项可供你填写,但下面这些是这个项目需要的。

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."

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

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

spec.authors = { "Your Name" => ‘[email protected]‘ }

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

spec.platform = :ios, "9.1"

spec.requires_arc = true

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

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

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

end

需要注意的一行是 spec.dependency "Curry", ‘~> 1.4.0‘。因为我们要支持 CocoaPods,我们期望我们框架的使用者使用 CocoaPods 而不是 Carthage,所以我们必须在这里以及 Cartfile 中指定依赖。

一旦设置好之后我们可以运行 pod lib lint 命令来测试一切是否配置妥当。如果运行没问题,我们将看到类似这样的结果:

当工程和依赖设置好之后,我们已经基本就绪,可以写代码了。当我们这么做之前,让我们创建我们的第一个 commit。

git commit -am "Project and dependencies set up"

编写第一个测试

打开 RGBTests/RGBTests.swift 来看一看缺省的模板。它使用 @testable 以及 XCTest,但我们将把两者都换掉。

我们将移除 @testable,因为我们想要测试公有 API,也就是框架的用户将会使用的部分。当我们的框架发展变大,我们可能需要 @testable 来测试没有公开暴露的部分;总的来说我们想要避免这样的情况,使得我们要测试的是暴露给使用者的部分。这个特性在测试应用而不是框架的时候最有用。

下面是 Apple Docs中关于可测试性的部分:

通过可测试性,你现在可以在不暴露内部程序的情况下,编写 Swift 2.0 框架及应用的测试。在测试源代码中使用 @testable import {ModuleName} 使得所有公有或内部的程序对 XCTest 目标可用,而对其它框架或应用目标不可用。

我们将使用 Quick 和 Nimble 用于测试。Quick 提供了一个良好的测试接口,拥有十分类似于 RSpec 和 Specta 的行为驱动的风格;Nimble 给予我们很多强大的断言,以及用更少的样本文件编写匿名代码的能力。

一旦做了这些改变,测试文件看起来将类似于这样:

import Quick

import Nimble

import RGB

class RGBTests: QuickSpec {

override func spec() {

describe("RGB") {

it("works") {

expect(true).to(beTrue())

}

}

}

}

用 ?U 或 Product → Test 运行测试,它们应该是绿的。

然后……我们成功了!

开玩笑的。让我们写点真正的测试。

我们希望调用 RGBUIColor(red: 195, green: 47, blue: 52) 返回一个漂亮的“thoughtbot red”UIColor。

代码看起来类似于:

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”组,选择“New File”。

创建一个名为 RGBUIColor.swift 的 Swift 文件并保存。在里面写上如下实现:

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 添加回来,然后你的测试就通过了。

正因为有这个错误的经验,我们在开始的时候从 import 中移除了 @testable。这有助于我们在向其它人发布我们的框架之前,早点捕捉到这类错误。

为了纠正这个错误,让我们把这个函数标记为 public,就像这样:

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

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

}

让我们运行测试!

我们绿了!

让我们提交这个小婊砸。

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

以上就是全部内容了!

就是这么溜。尽管步骤很多,但是我们已经成功地创建了一个可以发布到 GitHub,还有点用的框架。事实上,我们在 GitHub 上已经发布了这个框架的源代码。

https://github.com/jakecraige/RGB

我们已经迫不及待地想看到你将会创建什么样的出色的开源项目了。

时间: 2024-10-14 03:55:55

从零开始,打造自己的首个 iOS 框架的相关文章

[转]1小时内打造你自己的PHP MVC框架

简介 MVC框架在现在的开发中相当流行,不论你使用的是JAVA,C#,PHP或者IOS,你肯定都会选择一款框架.虽然不能保证100%的开发语言都会使用框架,但是在PHP社区当中拥有*多数量的MVC框架.今天你或许还在使用Zend,明天你换了另一个项目也许就会转投Yii,Laravel或者CakePHP的怀抱.如果你刚开始使用一种框架,当你看它的源码的时候你会觉得一头雾水,是的,这些框架都很复杂.因为这些流行的框架并不是短时间之内就写出来就发行的,它们都是经过一遍又一遍的编写和测试加上不断的更新函

Webrtc的ios框架编译

1.WebRTC的iOS框架的选择 目前两个比较活跃的开源WebRTC实现. Google WebRTC: 项目地址是: https://code.google.com/p/webrtc/ Ericsson Research OpenWebRTC: 项目地址是: https://github.com/EricssonResearch/openwebrtc 我们戴维营教育为了给学生实战项目中运用WebRTC视频通话技术,选择Google的WebRTC项目来构建iOS App的开发框架,因为目前Ch

IOS框架概览

iOS是运行在iPhone.iPod Touch或iPad上的操作系统,之前叫做iPhone OS,iOS与Mac OS X有共同的基础架构和底层技术.但iOS是根据移动设备的特点而设计的,所以和Mac OS X系统略有区别,比如对多点触摸和加速感应器的支持. 下面来看看iOS框架简介: iOS 的系统架构分为四个层次:核心操作系统层(Core OS layer).核心服务层(Core Services layer).媒体层(Media layer)和可触摸层(Cocoa Touch layer

GPUImage ==> 一个基于GPU图像和视频处理的开源iOS框架

Logo 项目介绍: GPUImage是Brad Larson在github托管的开源项目. GPUImage是一个基于GPU图像和视频处理的开源iOS框架,提供各种各样的图像处理滤镜,并且支持照相机和摄像机的实时滤镜: 基于GPU的图像加速,因此可以加速对实时摄像头视频.电影以及image的滤镜和其它效果处理,并且能够自定义图像滤镜.另外, GPUImage支持ARC. 使用GPUImage处理图片比Core Image更简单,只需要将过滤器赋给图片对象即可,不用考虑context或者设备等其

打造安全的App!iOS安全系列之 HTTPS 进阶

原文地址 上一篇<iOS安全系列之一:HTTPS>被CocoaChina转载,还顺便上了下头条: 打造安全的App!iOS安全系列之 HTTPS,高兴之余也有些诚惶诚恐,毕竟那篇文章只是介绍了比较偏应用的初级知识,对于想要深入了解HTTPS的同学来说是远远不够的,刚好本人最近工作上也遇到并解决了一些HTTPS相关的问题,以此为契机,决定写这篇更深入介绍HTTPS的文章. 本文分为以下四节: 中间人攻击:介绍中间人攻击常见方法,并模拟了一个简单的中间人攻击: 校验证书的正确姿势:介绍校验证书的一

iOS框架介绍

iOS框架介绍 Cocoa Touch GameKit  实现对游戏中心的支持,让用户能够在线共享他们的游戏相关的信息 iOS设备之间蓝牙数据传输   从iOS7开始过期   局域网游戏  http://www.cnblogs.com/KidReborn/archive/2011/10/17/2215641.html iAd     用来在应用中提供广告条 广告条与用户UI视图进行合并,与苹果的iAd服务一起工作,自动处理.加载和呈现富媒体广告以及应答在那些广告条上的点击等所有相关的工作.htt

【iOS开发-6】iOS框架以及手册的在线阅读和PDF版本的iOS Technology Overview下载

看一下官方文档,就可知:iOS框架就是iOS开发的整个技术,只不过apple把所以的技术都分类封装到不同的框架里面,便于需要的人调用. 当然,至于iOS框架从底层到顶层分为Core OS.Core Services.Media.Cocoa Touch四个层,可以简单理解成把那么多框架分成四个类而已. (1)iOS框架大概介绍 iOS的开发框架有很多,差不多71个,两年前只有40个左右,可以预见只会越来越多. 但是常用的也就十几个,比如CFNetwork.Foundation.UIKit这些,而诸

从零开始实现一个简易的Java MVC框架(三)--实现IOC

Spring中的IOC IoC全称是Inversion of Control,就是控制反转,他其实不是spring独有的特性或者说也不是java的特性,他是一种设计思想.而DI(Dependency Injection),即依赖注入就是Ioc的一种实现方式.关于Ioc和DI的具体定义和优缺点等大家可以自行查找资料了解一下,这里就不详细赘述,总之spring的IoC功能很大程度上便捷了我们的开发工作. 在实现我们的Ioc之前,我们先了解一下spring的依赖注入,在spring中依赖注入有三种方式

【代码篇】从零开始一步步搭建自己的golang框架

前言 import cycle not allowed 不知道是不是有很多学习golang的新人会遇到这样的问题.包循环引用这个问题,让人很头疼,尤其是在项目越来越复杂的时候,出现这么一句报错,这意味着你可能需要修改很多代码,这对一个新人来讲压力很大.通常来讲,解决这个错误的办法是将需要引用的那个包抽象成接口,解耦后调用.但这不是我这个篇章想要讲的内容.这个系列主要讲的是如何从代码组织架构方面去避免这个问题.从零开始一步步搭建自己的golang框架.这个篇章将实现以下的功能: 一个通用的基础框架