创建CocoaPods的Framework Swift组件化之路(下)
系统: Mac OS 10.15.2, XCode 11.3,swift 5.0
写作时间:2019-12-23
1. 说明
开发iOS App,基本上没有从零开始构建。因为系统以及提供了很多Framework,比如UIKit, Foundation, WebKit,MapKit等,GitHub上也有很多开源的Framework,Alamofire, Kingfisher等。
动态库与静态库的区别。
- Static library - 代码在编译时链接linked, 以后就不会再发生变化.
但是, iOS static libraries不允许包含images/assets
(只有代码). 曲线救国的方式是,用一个bundle去加入images/assets
.
Dynamic library
- 代码或者assets
在运行时runtime才链接 linked,也就是里面的内容会发生变化.
但是, 只有Apple官方才允许为iOS创建dynamic libraries. 如果你的项目有动态库,则App会审核失败.
- Framework - 编译后的代码实现一个任务… 所以Framework, 可以包含字符串,图片资源文件,storyboard,static framework , dynamic framework, 或者其它Framework, 并且可以分版本管理.(iOS 8以后允许创建)
此文创建的Framework依赖了第三方的Framework,比如Alamofire。
从零开始创建没有依赖的Framework请参考 – 创建CocoaPods的Framework Swift组件化之路(上)
2. 工程代码下载
https://github.com/zgpeace/IceCreamShopFramework
这里包含
- 开始的项目: IceCreamShop_Starter
- 完成的项目: IceCreamShop_Finisher
- Framework: Libraries/RWPickFlavor
3. 创建Framework
File > new > project > Framework & Library > Framework
下一步, Product Name
写为RWPickFlavor, 保存到新建的Libraries文件夹里面
新建Podfile文件
cd ~/yourProjectPath/Libraries/RWPickFlavor
pod init
open -a Xcode Podfile
Podfile内容填充如下
platform :ios, '12.0'target 'RWPickFlavor' dopod 'Alamofire', '~> 4.7'pod 'MBProgressHUD', '~> 1.1.0', :modular_headers => true
end
这样子组件就有了第三方Framework的依赖Alamofire
,
MBProgressHUD
。
4. Swift Static Library
4.1 CocoaPods版本小于1.5.0, CocoaPods不能使用static libraries. 如果pod包含了Swift代码,需要在Podfile中标注 use_frameworks!
. CocoaPods 在1.5.0以后, CocoaPods就可以用静态库static libraries!
如果在Podfile省略了use_frameworks!
, CocoaPods 将用静态库static libraries代替Framework. 你的 Objective-C
依赖需要以module的方式集成寄来, 但是. MBProgressHUD
是Objective-C
不支持modules的依赖. 幸运的是, 在MBProgressHUD依赖的后面,增加脚本 :modular_headers => true
, CocoaPods 会添加 module支持.
4.2 pod安装依赖库
pod install
4.3 打开新工程
open RWPickflavor.xcworkspace
XCode打开的工程视图
4.4 从工程IceCreamShop-Stater拷贝下面5个文件夹到RWPickflavor Framework里面。(文件夹:Categories, Controllers, Models, Views
, Resources)
RWPickflavor在文件夹下显示如下:
4.5 接着,打开工程RWPickFlavor.xcworkspace
,选择File ▸ Add Files to “RWPickFlavor”
… 把新加的5个文件夹加入到工程,显示如下:
4.6 打开RWPickFlavor中的Images.xcassets
, 删除 AppIcon
和 logo
images。
4.7 工程RWPickFlavor xcworkspace
, 需要确认Main.storyboard
中的对象链接是正确的. 确认下面3个对象的链接:
- Choose Your Flavor
- Ice Cream View
- Pick Flavor Data Source
因为拷贝storyboard到不同的工程project, 你需要确认上面的对象的Module都设置为CocoaPod的工程RWPickFlavor. 记得保存Command-S
.
5. 工程IceCreamShop-Stater移除多余文件
- 在文件夹中IceCreamShop-Stater打开工程IceCreamShop.xcworkspace, 删除下面4个文件夹
- Categories
- Controllers
- Models
- Views
打开
Info.plist
文件,找到分组Supporting Files group
, 删除行Mainstoryboard file base name
。打开工程中中的
Images.xcassets
, 删除background
images。运行工程,显示的是一个黑屏。
创建Pod的最困难的部分已经完成!恭喜!
6. 创建Github仓库
创建一个新的仓库给Framework用
仓库名字为RWPickFlavor,笔者新建的仓库链接如下:
https://github.com/zgpeace/RWPickFlavor新建另一个仓库给Podspec用,名字命名为RWPodSpecs,并勾选初始化README。 CocoaPods要求
pod specs repo
至少有一个提交,否则不工作.
链接如下:
https://github.com/zgpeace/RWPodSpecs
7. 设置Podspec
如果没有Podspec, RWPickFlavor
只是一堆文件. Podspec
是CocoaPod
的描述信息. Podspec
包括pod的名字,版本,Git下载地址URL.
你需要为RWPickFlavor
创建创建RWPickFlavor.podspec
. 执行如下命令:
cd ~/yourProjectPath/Libraries/RWPickFlavor
pod spec create RWPickFlavor
open -a Xcode RWPickFlavor.podspec
把RWPickFlavor.podspec
里面的内容,替换为:
Pod::Spec.new do |s|# 1
s.platform = :ios
s.ios.deployment_target = '12.0'
s.name = "RWPickFlavor"
s.summary = "RWPickFlavor lets a user select an ice cream flavor."
s.requires_arc = true# 2
s.version = "0.1.0"# 3
s.license = { :type => "MIT", :file => "LICENSE" }# 4 - Replace with your name and e-mail address
s.author = { "Keegan Rush" => "keeganrush@gmail.com" }# 5 - Replace this URL with your own GitHub page's URL (from the address bar)
s.homepage = "https://github.com/TheCodedSelf/RWPickFlavor"# 6 - Replace this URL with your own Git URL from "Quick Setup"
s.source = { :git => "https://github.com/TheCodedSelf/RWPickFlavor.git", :tag => "#{s.version}" }# 7
s.framework = "UIKit"
s.dependency 'Alamofire', '~> 4.7'
s.dependency 'MBProgressHUD', '~> 1.1.0'# 8
s.source_files = "RWPickFlavor/**/*.{swift}"# 9
s.resources = "RWPickFlavor/**/*.{png,jpeg,jpg,storyboard,xib,xcassets}"# 10
s.swift_version = "4.2"end
8. 创建许可证License
像其它pod, 你需要创建LICENSE许可证文件.
比如拷贝MIT License 的内容, 并保存为文件名为LICENSE — 没有扩展名 — 到路径~/yourProjectPath/Libraries/RWPickFlavor
. 比替换内容里面的年份[year] 和 名字[fullname] !
Choose a License 这是一个特别好的网站,帮助你如何选择一个适合你的开源open-source license.
9. 推送到Git
把Pod推送到远程git,替换掉 [Your RWPickFlavor Git URL]
为你的git地址(比如笔者的https://github.com/zgpeace/RWPickFlavor
).
cd ~/Documents/Libraries/RWPickFlavor
git init
git add .
git commit -m "Initial commit"
git tag 0.1.0
git remote add origin [Your RWPickFlavor Git URL]
git push -u origin master --tags
恭喜你,完成了你的第一个有依赖的Framework。
Last one more thing…
10. 应用你新建的CocoaPod
首先需要把你的Podspec
增加到私有仓库private specs repo
; 这个让CocoaPods找到你安装的pod. 幸运的是, 你已经创建了为Podspec
创建了Git 仓库.
在RWPickFlavor路径下,输入一下命令。替换掉[Your RWPodSpecs Git URL]
为你的Podspec
的路径(比如笔者的为:https://github.com/zgpeace/RWPodSpecs
):
pod repo add RWPodSpecs [Your RWPodSpecs Git URL]
pod repo push RWPodSpecs RWPickFlavor.podspec
上面标示创建了本地的RWPodSpecs
保存在你机器的路径~/.cocoapods
, 并把RWPickFlavor.podspec推送到了里面.
最后在Starter的工程里面,替换掉Podfile
的内容如下:
platform :ios, '12.0'source 'https://github.com/CocoaPods/Specs.git'
source '[Your RWPodSpecs Git URL Goes Here]'target 'IceCreamShop' dopod 'RWPickFlavor', '~> 0.1.0'pod 'MBProgressHUD', '~> 1.1.0', :modular_headers => true
end
确保替换掉[Your RWPodSpecs Git URL Goes Here]
为你的RWPodSpecs的Git地址(比如笔者的为:https://github.com/zgpeace/RWPodSpecs
). 你不需要包含Alamofire
在Podfile
, 以为依赖以及配置好在RWPickFlavor.podspec
. 你需要增加一行给MBProgressHUD
,这样子可以增加配置信息:modular_headers =>
.
运行
pod install
替换掉AppDelegate.swift
的内容如下:
import UIKit
import RWPickFlavor@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {// MARK: Instance Variablesvar window: UIWindow?func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {window = UIWindow(frame: UIScreen.main.bounds)window?.rootViewController = createRootViewController()window?.makeKeyAndVisible()return true}func createRootViewController() -> UIViewController {let bundle = Bundle(for: PickFlavorViewController.self)let storyboard = UIStoryboard(name: "Main", bundle: bundle)return storyboard.instantiateInitialViewController() ?? UIViewController()}}
运行的时候发现错误,重复的Images.xcassets
, XCode 10 以后不能有重复的内容,要不删掉项目的,或者File > Workspace Setting > Build System > Legacy Build System.
最终运行起来:
参考
https://www.raywenderlich.com/5823-how-to-create-a-cocoapod-in-swift
https://stackoverflow.com/questions/15331056/library-static-dynamic-or-framework-project-inside-another-project
https://www.vadimbulavin.com/static-dynamic-frameworks-and-libraries/
https://stackoverflow.com/questions/50718018/xcode-10-error-multiple-commands-produce
创建CocoaPods的Framework Swift组件化之路(下)相关推荐
- 百度App Objective-C/Swift 组件化混编之路(一)
作者丨郭金.陈佳 来源丨百度App技术 一. 背景 1.1 Swift 发展历史 2010 年 7 月,克里斯(Chris Lattner)开始设计 Swift.完成基础架构后,克里斯带领开发小组陆续 ...
- 百度App Objective-C/Swift 组件化混编之路(二)- 工程化
作者丨张渝.郭金 来源丨百度App技术 前文<百度App Objective-C/Swift 组件化混编之路>已经介绍了百度App 引入 Swift 的影响面评估以及落地的实施步骤,本文主 ...
- swift 组件化_打造完备的iOS组件化方案:如何面向接口进行模块解耦?
作者 | 黑超熊猫zuik,一个修行中的 iOS 开发,喜欢搞点别人没搞过的东西,钻研过逆向工程.VIPER 架构和组件化. 关于组件化的探讨已经有不少了,在之前的文章 iOS VIPER架构实践(三 ...
- android国籍组件,android组件化之路
问题:实际业务变化快,而工程内各个功能模块耦合度太高,不能对功能模块进行快速方便地拆分或组装.团队共同开发中,可能一个文件同时被多人修改,导致每次更新提交代码都需要消耗大量时间去merge代码.每次修 ...
- 组件化之路 - ViewModel一知半解
新的一年,优先把欠账补齐,关于Jetpack下Lifecycle.ViewModel.LiveData组件库,以及ViewModel+LiveData项目实践,如今也只差ViewModel还没有记录了 ...
- 蘑菇街App的组件化之路·续
原文:http://limboy.me/ios/2016/03/14/mgj-components-continued.html 蘑菇街 App 的组件化之路·续 前几天在「移动学习分享群」分享了关于 ...
- swift 组件化_京东商城订单模块基于 Swift 的改造方案与实践
ABI Stability & Module Stability 以及Swift优势 2019年Swift 5发布,标志这门语言迎来了一个重大的里程碑.与之前的版本相比除了一些基础语法的改变, ...
- 单文件组件的组件传值_移动端组件化架构(下)
我的组件化方案 对于项目架构来说,一定要建立于业务之上来设计架构.不同的项目业务不同,组件化方案的设计也会不同,应该设计最适合公司业务的架构. 架构设计 以我之前公司项目为例,项目是一个地图导航应用, ...
- 【超强干货】蘑菇街App的组件化之路
本文为『移动前线』群在3月10日的分享总结整理而成,转载请注明来自『移动开发前线』公众号. 嘉宾介绍 蘑菇街李忠(花名银时,网名 limboy),多年客户端开发经验,目前主要负责移动端基础架构设计及核 ...
- 蘑菇街 App 的组件化之路
在组件化之前,蘑菇街 App 的代码都是在一个工程里开发的,在人比较少,业务发展不是很快的时候,这样是比较合适的,能一定程度地保证开发效率. 慢慢地代码量多了起来,开发人员也多了起来,业务发展也快了起 ...
最新文章
- 物联网技术概论的课程编号_课程 物联网应用实战 7月班仅剩3个席位
- python五十一:动态导入模块,通过字符串导入模块
- Python中随机森林的实现与解释
- git submoule 更新_微软Surface Duo双屏手机键盘更新:支持分体式输入
- python慢在哪里_求大神分析一下我的python脚本慢在哪里?
- write up杂项:想蹭网先解开密码
- emq auth mysql_EMQ X 认证鉴权(一)——基于 MySQL 的 MQTT 连接认证
- bat 两个文本字符替换_Excel中最全最实用的文本函数公式大全
- 互联网岗位介绍和成长
- JDBC 与ODBC的区别
- sp_help 查看表结构 alter column修改字段长度
- 硬件厂商 Linux社区 代码,Linux企业版需加强的10个方面
- qj71c24n通讯实例_通信模块QJ71C24N应用篇手册三菱QJ71C24N用户手册 - 广州凌控
- protoc安装配置
- 暗影精灵3 PLUS 安装黑苹果
- python调用virustota接口api实现上传文件返回查毒结果
- [渝粤教育] 徐州工业职业技术学院 药物分离技术 参考 资料
- linux上的两种可执行程序
- ISO三体系,招投标企业认证最多的资质
- 对一个数组排序之后求相邻数的最大差值