服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - IOS - iOS组件依赖避免冲突的小技巧分享

iOS组件依赖避免冲突的小技巧分享

2021-05-26 16:20波儿菜 IOS

这篇文章主要给大家介绍了关于iOS组件依赖避免冲突的小技巧,文中通过示例代码介绍的非常详细,对各位iOS开发者们具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

问题缘由

本文以 ybimagebrowser[1] 组件举例。

ybimagebrowser 依赖了 sdwebimage,在使用 cocoapods 集成到项目中时,可能会出现一些依赖冲突的问题,最近社区提了多个 issues 并且在 insights -> traffic -> popular content 中看到了此类问题很高的关注度,所以不得不着手解决。

严格的版本限制

一个开源组件的迭代过程中,保证上层接口的向下兼容就不错了。为了优化性能并且控制内存,ybimagebrowser 没有直接用其最上层的接口,而是单独使用了下载模块和缓存模块,sdwebimage 的迭代升级很容易导致笔者的组件兼容不了,所以之前一直是类似这样依赖的:

?
1
s.dependency 'sdwebimage', '~> 5.0.0'

这样做的好处是限制足够小版本范围,降低 sdwebimage 接口变动导致组件代码错误的风险。但如果 sdwebimage 升级到 5.1.0,不管相关 api 是否变动,cocoapods 都视为依赖冲突。

其它组件依赖了不同版本的 sdwebimage

当两个组件依赖了同一个组件的不同版本,并且依赖的版本没有交集,比如:

?
1
2
a.dependency 'sdwebimage', '~> 4.0.0'
b.dependency 'sdwebimage', '~> 5.0.0'

那么 a 和 b 同时集成进项目会出现依赖冲突。

解决方案

使用 cocoapods 集成项目非常便捷,对于组件使用者来说,总是想在任何场景下都能轻易集成,并且能在将来享受组件的更新优化,显然前面提到的问题可能会影响集成的便捷性。

更模糊的版本限制

很多时候一个大版本的组件不会改动 api,并且对于社区流行的组件我们可以寄一定希望于其做好向下兼容,所以放宽依赖的版本限制能覆盖将来更多的版本(规则参考:podspec dependency[2]):

?
1
s.dependency 'sdwebimage', '>= 5.0.0'

为什么不干脆去掉版本限制呢?

因为 ybimagebrowser 3.x 是基于 sdwebimage 5.0.0 开发的,笔者可以明确不兼容 5.0.0 之前的版本,所以在 sdwebimage 将来迭代版本出现相关 api 不兼容之前,这个限制都是“完美”覆盖所有版本的。

避免依赖冲突的暴力方案

当有其它组件依赖了不同版本的 sdwebimage,粗暴的解决方案如下:

• 直接修改其它组件依赖的 sdwebimage 版本。

• 将 ybimagebrowser 手动导入项目,并且修改代码去适应当前的 sdwebimage 版本。

• 社区朋友一个 issue 中提到的方法:在 ~/.cocoapods/repos 目录下找到 ybimagebrowser 文件夹,更改对应版本的 podspec.json 文件里对 sdwebimage 的依赖版本。

显然,上面的几种方案不太优雅,手动导入项目难以享受组件的更新优化,修改本地 repo 信息会因为 repo 列表的更新而复位。

避免依赖冲突的优雅方案

出现依赖冲突是必须要解决的问题,其它组件依赖的版本限制可以视为不变量,解决方案可以从组件的制作方面考虑。

要做到的目标是,既满足部分用户快速集成组件,又能让部分用户解决依赖冲突的前提下保证能享受组件将来的更新优化。

答案就是subspec,以下是 ybimagebrowser.podspec 部分代码(完整代码[3]):

?
1
2
3
4
5
6
7
8
s.subspec "core" do |core|
core.source_files = "ybimagebrowser/**/*.{h,m}"
core.dependency 'sdwebimage', '>= 5.0.0'
end
s.subspec "nosd" do |core|
core.source_files = "ybimagebrowser/**/*.{h,m}"
core.exclude_files = "ybimagebrowser/webimagemediator/ybibdefaultwebimagemediator.{h,m}"
end

由此,用户可以自由的选择是否需要依赖 sdwebimage,在 podfile 里的观感大致是这样:

?
1
2
3
4
// 依赖 sdwebimage
pod 'ybimagebrowser'
// 不依赖 sdwebimage
pod 'ybimagebrowser/nosd'

那么在 ybimagebrowser 代码中应该如何区分是否依赖了 sdwebimage 并且提供默认实现呢?

第一步是设计一个抽象接口(这个接口不依赖 sdwebimage):

?
1
2
3
@protocol ybibwebimagemediator <nsobject>
// download methode, caching methode, and so on.
@end

第二步是在ybimagebrowser.h中定义一个遵循该接口的属性:

?
1
2
/// 图片下载缓存相关的中介者(赋值可自定义)
@property (nonatomic, strong) id<ybibwebimagemediator> webimagemediator;

第三步是实现一个默认的中介者(这个类依赖了 sdwebimage):

?
1
2
3
4
5
@interface ybibdefaultwebimagemediator : nsobject <ybibwebimagemediator>
@end
@implementation ybibdefaultwebimagemediator
//通过 sdwebimage 的 api 实现 <ybibwebimagemediator> 协议方法
@end

第四步是在内部代码中通过条件编译导入并初始化默认中介者:

?
1
2
3
4
5
6
7
#if __has_include("ybibdefaultwebimagemediator.h")
#import "ybibdefaultwebimagemediator.h"
#endif
...
#if __has_include("ybibdefaultwebimagemediator.h")
_webimagemediator = [ybibdefaultwebimagemediator new];
#endif

第五步在 ybimagebrowser.podspec 中也可以看到,在不依赖 sdwebimage 的集成方式时排除了两个文件:ybibdefaultwebimagemediator.{h.m}。

由此便实现了目标:

• 用依赖 sdwebimage 的集成方式快速集成。

• 使用不依赖 sdwebimage 的集成方式避免各种情况下的依赖冲突,但注意这种情况需要自行实现一个遵循<ybibwebimagemediator>协议的中介者。

以上便是避免依赖冲突的小技巧,希望读者朋友能提出更好的建议或意见

延伸 · 阅读

精彩推荐
  • IOS解析iOS开发中的FirstResponder第一响应对象

    解析iOS开发中的FirstResponder第一响应对象

    这篇文章主要介绍了解析iOS开发中的FirstResponder第一响应对象,包括View的FirstResponder的释放问题,需要的朋友可以参考下...

    一片枫叶4662020-12-25
  • IOSiOS 雷达效果实例详解

    iOS 雷达效果实例详解

    这篇文章主要介绍了iOS 雷达效果实例详解的相关资料,需要的朋友可以参考下...

    SimpleWorld11022021-01-28
  • IOSiOS布局渲染之UIView方法的调用时机详解

    iOS布局渲染之UIView方法的调用时机详解

    在你刚开始开发 iOS 应用时,最难避免或者是调试的就是和布局相关的问题,下面这篇文章主要给大家介绍了关于iOS布局渲染之UIView方法调用时机的相关资料...

    windtersharp7642021-05-04
  • IOSIOS开发之字典转字符串的实例详解

    IOS开发之字典转字符串的实例详解

    这篇文章主要介绍了IOS开发之字典转字符串的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握这样的方法,需要的朋友可以参考下...

    苦练内功5832021-04-01
  • IOS关于iOS自适应cell行高的那些事儿

    关于iOS自适应cell行高的那些事儿

    这篇文章主要给大家介绍了关于iOS自适应cell行高的那些事儿,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    daisy6092021-05-17
  • IOSiOS通过逆向理解Block的内存模型

    iOS通过逆向理解Block的内存模型

    自从对 iOS 的逆向初窥门径后,我也经常通过它来分析一些比较大的应用,参考一下这些应用中某些功能的实现。这个探索的过程乐趣多多,不仅能满足自...

    Swiftyper12832021-03-03
  • IOSiOS中tableview 两级cell的展开与收回的示例代码

    iOS中tableview 两级cell的展开与收回的示例代码

    本篇文章主要介绍了iOS中tableview 两级cell的展开与收回的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    J_Kang3862021-04-22
  • IOSIOS 屏幕适配方案实现缩放window的示例代码

    IOS 屏幕适配方案实现缩放window的示例代码

    这篇文章主要介绍了IOS 屏幕适配方案实现缩放window的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    xiari5772021-06-01