语言: swift, 版本:swift4.2,XCode:10.2
写作时间:2019-07-02
Framework简介
有没有遇到这种场景:
- 同时维护过几个项目,发现一个项目有个bug,修复bug。其它项目也会有相应的问题,这个时候一般是git来cherry pick修复代码到其它项目。
- 一个二维码扫一扫的功能,项目一组的同学开发了,项目二组的同学过来说,这份代码也分享一份呗。然后就代码copy。
上面的场景的解决方案就是代码模块化modularize,java有jar包,Nodejs有packages,iOS就用framework。像Alamofire,Snapkit,Kingfisher。PodFile引入,pod update就能解决。这篇文章就是记录如何实现这个功能。
1. 下载demo工程
demo工程:https://github.com/zgpeace/KnobControl/tree/start
目录为Starter, 运行后效果如下:
这个项目里面主要有两个类Knob.swift
负责圆圈的逻辑,ViewController.swift
负责调用圆圈的逻辑,这里framework就是要复用Knob.swift
这个类,把原来工程的类删掉。然后通过framework的方式引入进来,实现代码分享的功能。
创建framework
- StarterPrepare文件夹里面的项目是经过改进的项目可以直接运行。
- 创建framework。Xcode, 选择 File ▸ New ▸ Project….
Choose iOS ▸ Framework & Library ▸ Cocoa Touch Framework.
- 选择下一步, 填写信息如下KnobControl,最后create选择StarterPrepare的根目录,和KnobShowcase文件夹在同一层级。
- 在KnobControl中copy来自KnobShowcase的文件
Knob.swift
,KnobRender.swift
,RotationGestureRecognizer.swift
. - 删除KnobShowcase的文件
Knob.swift
,KnobRender.swift
,RotationGestureRecognizer.swift
. - 集成Binary
右键点击 KnobShowcase > Add Files to “KnobShowcase” > select KnobControl.xcodeproj > 增加 KnobControl.xcodeproj 作为 sub-project.
- build and run 发现错误
虽然framework跟project在同一个room里面,还是需要在targets中建立连接。先看看KnobControl的目录结构,找到KnobControl.framework文件
选择最上面KnobShowcase > the project editor > KnobShowcase target > General tab > Embedded Binaries section > 把 KnobControl.framework 拖到 KnobControl.xcodeproj Embedded Binaries. Linked Frameworks and Libraries也会同步加进来。
运行发现还是有错误。 - 访问权限
打开文件ViewController.swift, import头文件KnobControl.
import KnobControl
方法需要修改为public修饰,因为默认的方法修饰为Internal,是指同一个framework里面可见。
运行还是失败…
- 修改StoryBoard权限
用到storyboards的时候, 关联的自定义classes,需要在Identity inspector中设置class name 和 module . storyboard创建的时候,Knob 是APP的module一部分, 现在它在framework中.
更新storyboard告诉它到哪里可以找到自定义的custom view:
Main.Storyboard > 选择 Knob in the Document outline >
Identity inspector > under Custom Class > 修改Module 为 KnobControl a
运行成功
创建本地pod
- 清除KnobShowcase中与KnobControl.xcodeproj的链接。
- 创建Pod,在Terminal中运行
pod spec create KnobControl
这句话创建了文件KnobControl.podspec
- 替换KnobControl.podspec 的内容
s.name = "KnobControl"
s.version = "1.0.0"
s.summary = "A knob control like the UISlider, but in a circular form."
s.description = "The knob control 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"
s.license = "MIT"
s.platform = :ios, "12.2"
s.source = { :path => '.' }
s.source_files = "KnobControl"
在end之前加上swift版本的说明
s.swift_version = "4.2"
- 验证Podspec的正确性, 在Terminal中运行
pod spec lint
显示error,因为source是local的。所以目前不需要验证Podspec。
- 创建pod, 在Terminal中运行
pod init
运行后,就创建了Podfile文件
- Podfile文件内容修改如下:
platform :ios, '12.0'
target 'KnobShowcase' do
use_frameworks!
pod 'KnobControl', :path => '../KnobControl'
end
# Workaround for Cocoapods issue #7606
post_install do |installer|
installer.pods_project.build_configurations.each do |config|
config.build_settings.delete('CODE_SIGNING_ALLOWED')
config.build_settings.delete('CODE_SIGNING_REQUIRED')
end
end
- 保存Podfile文件内容,Terminal中运行
pod install
运行成功以后,创建了KnobShowcase.xcworkspace文件。
同时Terminal会有警告:
修复方法如下, 选择KnobShowcase根目录下打开项目KnobShowcase.xcodeproj > KnobShowcase target > Build Settings tab > search > ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES > 选择Other选项,在弹框里填入内容 $(inherited)
.
再次运行pod install
, 警告消失了。
- 打开项目KnobShowcase.xcworkspace,查看发现有两个Targets
Pods-KnobShowcase: pod project把其它pod和当前项目合并为最终结果的一个framework: Pods-KnobShowcase.
KnobControl: pod 集成进来的三方库. - 查看文件目录在Development Pods, 因为是local pod的原因。
pod仓库上传到git
- 创建git仓库
- 下载远程仓库
创建目录
mkdir repo
cd repo
clone 仓库
git clone URL
显示clone成功
Cloning into 'KnobControl'...
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (4/4), done.
- 接着,copy文件夹KnobControl的内容到repo/KnobControl.
打开copy过来的KnobControl.podspec, 修改s.source的内容:
s.source = { :git => "URL", :tag => "1.0.0" }
- 推送到远程仓库
cd KnobControl/
git add .
git commit -m "Initial commit"
git push -u origin master
- 给git仓库打tag
KnobControl.podspec
s.version = "1.0.0"
打tag,并推送到git仓库
git tag 1.0.1
git push --tags
- 检查创建的spec
pod spec lint
结果是验证通过。
- 更新在KnobShowcase中的Podfile引入pod内容如下:
pod 'KnobControl', :git => 'URL', :tag => '1.0.0'
s.homepage = 'URL'
- Terminal中更新三方库
pod update
运行项目成功。
发布pod到公网
平时用开源三方库很方便,类似如下:
pod ‘ZgpeaceKnobControl’, ‘1.0.1’
- 先注册为pod trunk用户
$ pod trunk register zgpeace@gmail.com 'zgpeace' --description='zgpeace macbook pro'
说明:
- 邮箱:zgpeace@gmail.com, 提交后,会收到验证邮件,点击确认后即可注册成功,这里没有密码,类似于邮箱跟电脑的绑定了连接session token。
- 用户名:zgpeace
- 描述:zgpeace macbook pro
- 打开邮箱 > 点击确认的pod trunk链接 > 显示注册成功
- terminal 验证信息
% pod trunk me
- Name: zgpeace
- Email: zgpeace@gmail.com
- Since: July 2nd, 02:47
- Pods:
- ZgpeaceKnobControl
- Sessions:
- July 2nd, 02:47 - November 7th, 18:03. IP: *.*.*.* Description: 15 inch macbook pro
-
- 发布pod到公网
如果用名字KnobControl,发现已经被注册了。
% pod trunk push ./KnobControl.podspec
Updating spec repo `master`
CocoaPods 1.7.3 is available.
To update use: `sudo gem install cocoapods`
Validating podspec
-> KnobControl (1.0.1)
- NOTE | xcodebuild: note: Using new build system
- NOTE | [iOS] xcodebuild: note: Planning build
- NOTE | [iOS] xcodebuild: note: Constructing build description
[!] You (zgpeace@gmail.com) are not allowed to push new versions for this pod. The owners of this pod are dev.mjun@gmail.com.
实际上主要简单重命名podspec文件的名字,比如加个前缀(例子:ZgpeaceKnobControl), 并且把文件的s.name也改为相同的名字即可.
s.name = "ZgpeaceKnobControl"
重新发布pod, 成功信息如下
% pod trunk push ./ZgpeaceKnobControl.podspec
Updating spec repo `master`
Validating podspec
-> ZgpeaceKnobControl (1.0.1)
- NOTE | xcodebuild: note: Using new build system
- NOTE | [iOS] xcodebuild: note: Planning build
- NOTE | [iOS] xcodebuild: note: Constructing build description
Updating spec repo `master`
--------------------------------------------------------------------------------
? Congrats
? ZgpeaceKnobControl (1.0.1) successfully published
? July 2nd, 02:57
? https://cocoapods.org/pods/ZgpeaceKnobControl
? Tell your friends!
--------------------------------------------------------------------------------
- 运用到项目
修改Podfile的引入为
pod 'ZgpeaceKnobControl', '1.0.1'
导入三方库
pod update
成功后运行项目,跟原来一样。
7. 总结
Framework给iOS提供了代码共享的解决方案,本地创建Framework可以验证重用代码的可行性,Local Pod可以验证通过pod方式引入三方库,发布到git可以共享pod,pod trunk push可以在公网共享三方库。
创建依赖的Framework请参考 – 创建CocoaPods的Framework Swift组件化之路(下)
代码下载
demo 原始代码(StarterPrepare文件夹)、中间代码(Intermediate文件夹)、本地Pod结果代码(Final文件夹)、公网pod结果代码(FinalPodPush文件夹):
https://github.com/zgpeace/KnobControl/tree/start
pod 仓库:
https://github.com/zgpeace/KnobControl
参考
https://www.raywenderlich.com/5109-creating-a-framework-for-ios
https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WhatAreFrameworks.html
https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/Introduction/Introduction.html#//apple_ref/doc/uid/10000123i
https://guides.cocoapods.org/making/getting-setup-with-trunk.html
https://guides.cocoapods.org/using/the-podfile.html