黑客技术

点击右侧关注,了解黑客的世界!

Java开发进阶

点击右侧关注,掌握进阶之路!

Python开发

点击右侧关注,探讨技术话题!

作者 | 波儿菜

前言

今天在重温《程序员的自我修养》中关于符号表的章节时,突然脑子灵光一现,想到了这个知识的一个应用场景,所以便有了这篇文章。

若对 iOS 组件化不太了解,可以看笔者的另一篇文章:解读 iOS 组件化与路由的本质1,本文主要是谈一下如何利用弱符号来实现 iOS 组件化解耦。

强弱符号简述

函数和全局变量编译后需要有唯一的符号名,在链接时才不会混淆。程序员所写代码中的变量名会经过修饰后作为符号名,比如 C 中fun会被修饰为_fun。而符号分为弱符号强符号,对于 C/C++ 来说,编译器默认函数和已初始化的全局变量为强符号,未初始化的全局变量为弱符号,可以使用__attribute__ ((weak))定义一个弱符号,编译器决议符号时有如下规则:

• 不允许强符号被多次定义。

• 多个符号名重复且只有一个强符号时,选择强符号。

• 多个符号名重复且都是弱符号时,选择占用空间最大的一个。

也就是说,符号名是可以重复的,只要保证最多一个强符号。

核心思路

谈到这里可能很多人都明白笔者要做什么了。iOS 组件化核心的问题是解耦,需要在不导入目标业务模块的情况下通过一些方式调用到目标业务,那么只需要在目标业务模块中定义一个强符号,在使用方定义一个弱符号就能轻易解决。

具体实施

虽然思路是明确了,但是大家都是很懒的,总是想方设法减小一些实施成本。笔者简单设计了一下,非常容易理解,代码见 DEMO2

比如EAim业务模块,建一个文件EAimRouter.m专门放置相关路由方法:

void ERouterGotoEAimController(NSString *name, void(^callBack)(void)) {EAimController *vc = [EAimController new];vc.name = name;vc.callBack = callBack;[UIViewController.yb_top.navigationController pushViewController:vc animated:YES];}

这些路由 C 语言方法和EAim业务模块是一个 repo 的,它们也就是解耦所需的强符号。为了让弱符号相关代码统统由EAim业务方来维护,所以有必要额外建立一个 repo,这里叫做EAimMediator.h,仅仅是一个头文件:

__attribute__ ((weak)) void ERouterGotoEAimController(NSString *name, void(^callBack)(void)) {ERouterNotFound(name, callBack, nil);}

EAimMediator.h repo 是由调用方去导入的,很明显这个文件是和具体业务解耦的。这些 C 方法也就是解耦所需的弱符号。若当前业务模块导入了EAim模块,则这个方法会被EAim中定义的同名方法ERouterGotoEAimController覆盖;若没有导入EAim模块,就会走ERouterNotFound进行容错处理。

ERouterNotFound是放在EMediator.h/.m中的,统一处理路由未找到的情况:

void ERouterNotFound(id params, ...) {if (params) {va_list argList;va_start(argList, params);id arg = params;do {NSLog(@"cur arg: %@", arg);} while ((arg = va_arg(argList, id)));va_end(argList);}NSLog(@"router not found");}

EMediator.h/.m的存在是有意义的,专门放路由相关的处理算法逻辑,作为公共业务组件,由所有需要的业务模块导入。

优劣分析

实现组件化解耦一般有三种方式:Protocol、Block、Runtime 动态调用,它们的优劣具体可参考 解读 iOS 组件化与路由的本质1

弱符号方式和使用 Protocol 方式一样,没有一个统一的拦截地方,所以若要实现所有路由的拦截将需要手动调用一次拦截方法,这是不及 Block 和 Runtime 方式的缺点。

弱符号方式比 Block 和 Runtime 方式优越的地方是不需要很多的硬编码,为什么说很多?因为弱符号的那个声明编译器是不会检查是否与对应的强符号一模一样,所以这个可以说是硬编码,只是可以通过复制粘贴简单处理,并且由于弱符号维护方也是相应的业务团队,所以这个成本算比较低。

弱符号方式比 Protocol 和 Block 优越的地方是不需要注册,编译器会自动的根据前面提到的规则静态 (或动态) 决议符号引用的地址。

弱符号方式还有一个优点是代码很简洁,几乎只有强符号和对应的一个弱符号,没有大量的中间层处理代码。不过它有一个问题需要注意,就是当项目包含 Swift 时可能需要进行一些复杂的转换,或许纯 Swift 项目可以通过 Swift 语言本身的特性进行设计。

后语

目前来看,这似乎是一个可行的 iOS 组件化解耦的方案。不过整个过程只是笔者今天的一个小灵感,方案实施可能有一些隐患,场景也没有完全实践过,所以欢迎各位大佬批评指正 ????。

参考

[1]https://juejin.im/post/5d3fb0966fb9a06b1c740736 
[2]https://github.com/indulgeIn/YBRouterAndDecouplingDemo

 推荐↓↓↓ 

????16个技术公众号】都在这里!

涵盖:程序员大咖、源码共读、程序员共读、数据结构与算法、黑客技术和网络安全、大数据科技、编程前端、Java、Python、Web编程开发、Android、iOS开发、Linux、数据库研发、幽默程序员等。

万水千山总是情,点个 “在看” 行不行

弱符号实现 iOS 组件化解耦相关推荐

  1. iOS组件化及架构设计

    关于组件化 网上组件化的文章很多.很多文章一提到组件化,就会说解耦,一说到解耦就会说路由或者runtime.好像组件化 == 解耦 == 路由/Runtime,然而这是一个非常错误的观念.持有这一观点 ...

  2. 解读 iOS 组件化与路由的本质

    前言 虽然 iOS 组件化与路由的话题在业界谈了很久,但是貌似很多人都对其有所误解,甚至没搞明白"组件"."模块"."路由"."解 ...

  3. iOS-解读 iOS 组件化与路由的本质

    前言 虽然 iOS 组件化与路由的话题在业界谈了很久,但是貌似很多人都对其有所误解,甚至没搞明白"组件"."模块"."路由"."解 ...

  4. iOS 组件化与路由的本质

    前言 虽然 iOS 组件化与路由的话题在业界谈了很久,但是貌似很多人都对其有所误解,甚至没搞明白"组件"."模块"."路由"."解 ...

  5. iOS 组件化的三种方案

    组件化 本文主要介绍iOS组件化的三种方案 1.常⽤的三种方案 URL Scheme Target - Action Protocol - Class 匹配 1.1. URL Scheme路由 使 U ...

  6. iOS组件化开发从开始到完整总结

    一.组件化介绍 需求来源 随着项目规模不断扩大,业务模块增多,开发过程中会有多条产品线(多人或多小组开发不同的功能);如果用传统的开发模式,会导致代码臃肿,编译速度越来越慢,开发效率低下,代码维护成本 ...

  7. iOS 组件化,插件化,模块化设计思路分析

    iOS 组件化,插件化设计思路分析 前言 随着用户的需求越来越多,对App的用户体验也变的要求越来越高.为了更好的应对各种需求,开发人员从软件工程的角度,将App架构由原来简单的MVC变成MVVM,V ...

  8. iOS组件化-带你一步步实现项目的组件化

    https://blog.csdn.net/u014205965/article/details/78025799 iOS组件化(上篇)- 拆分基础组件 https://www.jianshu.com ...

  9. android 蘑菇街组件化,4. IOS 组件化(蘑菇街的路由+协议式)

    为了研究组件化,我们主要是讨论 蘑菇街的路由+协议式 和 中间件 讨论第一种方式,并参考 蘑菇街IOS组件化 ,我们来实现一个可以运行的demo,并讨论优缺点. 路由 用MGJRouter 单例,通过 ...

最新文章

  1. 返回指针值的函数(1)
  2. ECMA262 Edition5 Object,Object的属性和方法,Object.prototype的方法.
  3. mysql if begin end_MySQL存储过程例子,不能在if else里面用begin end否则会报错Erro_MySQL...
  4. LinkedList源码详解
  5. thinkcmf ajax,thinkcmfx 中如何用jquery ajax提交数据,自己尝试去做之后,还是没法提交,求助!...
  6. mysql mha配置idrac远程关机_iDRAC远程管理功能试用_戴尔 PowerEdge R810(Xeon E7520/16GB/3*146GB)_服务器评测与技术-中关村在线...
  7. Redis执行monitor命令报错 (error) NOAUTH Authentication required.
  8. 如何通过手机访问本地编写的html页面
  9. Apache Pulsar PMC 成员翟佳入选「2020 中国开源先锋 33 人」
  10. Tensorflow从指定链接下载文件
  11. 记录从网页下载ppt的过程。
  12. shell脚本下的教你如果运用for,while,unti循环,以及区别l
  13. 苹果App Store搜索出Bug,网友:完美避开所有正确答案
  14. request与response的笔记梳理
  15. 4-20ma转换0-10v信号隔离器,0-5v电压放大模块
  16. 案牍写作中要留意的问题
  17. python怎么编写在线excel_超简单:用Python让Excel飞起来(零基础学python,用python实现办公自动化)...
  18. ps -ef和ps -aux的区别
  19. cassandra install troubleshooting
  20. 一次失败的j2v8集成

热门文章

  1. js判断ipad还是安卓_JavaScript判断ios还是android系统
  2. Ajax 验证用户输入的验证码是否与随机生成的一致
  3. Linux系统日志及分析
  4. String 类型操作 16进制转10进制
  5. 局域网两个不同网段互相访问
  6. 【免费】iPhone上最好用的短信群发软件: 高速短信4.1
  7. python _ 统计红楼梦人员姓名出现次数
  8. 太赞了!别再说 不能用Python开发美观的GUI程序了!
  9. 在暗影精灵游戏本上安装 Centos7
  10. uni-app、微信小程序低功耗蓝牙开发及使用