广告位联系
返回顶部
分享到

iOS Lotusoot模块化工具应用的动态思路

IOS 来源:互联网 作者:秩名 发布时间:2022-08-01 21:35:48 人浏览
摘要

下文,写的是 Swift 依赖 OC 库,没有命名空间 组件化的要点-约定 个人觉得 例如,URL 路由的注册,就是把约定的信息,传过去。作为服务。 Lotusoot 包含服务调用,短链的注册与调用 下

下文,写的是 Swift 依赖

OC 库,没有命名空间

组件化的要点-约定

个人觉得

例如,URL 路由的注册,就是把约定的信息,传过去。作为服务。

Lotusoot 包含服务调用,短链的注册与调用

下面着重讲服务调用,短链略

场景

project 有两个依赖 A (协议) 和 B (协议的实现者,提供服务)

project 引用 A,知道了协议信息

project 不引用 B , project 对 B 一无所知

这样 project 把 B 去掉,编译的更快

B 依赖 A, 引用 A, 实现 A 的协议,提供服务

调用服务

1

2

3

4

5

6

7

8

// 拿到 key

let lotus = s(AccountLotus.self)

// kv 取得提供服务的实例

let accountModule: AccountLotus = LotusootCoordinator.lotusoot(lotus: lotus) as! AccountLotus

// 调用服务

accountModule.login(username: "zhoulingyu", password: "wow") { (error) in

    print(error ?? "1234")

}

第 3 步,调用服务很简单

第 2 步,挺精彩,充分使用了 Swift 编译时的静态特性

协议的方法,编译时确定了

需要几个参数,啥类型的,一般都可以显式使用

不用看到一个参数字典,啊,这是啥

1

2

3

// 第 2 步。从下面取

// 键值对,值是提供服务的对象

var lotusootMap: Dictionary = Dictionary<String, Any>()

第 1 步, 拿到键

这里把协议名,作为 key

1

2

3

4

5

6

7

8

9

10

11

// 使用泛型,取其描述

// 协议,转协议名

public extension String {

    init<Subject>(_ instance: Subject) {

        self.init(describing: instance)

    }

}

/// 通过 Subject 快速获取字符串

public func s<Subject>(_ instance: Subject) -> String {

    return String(instance)

}

注册服务

1, Project 没有 import B ( 提供服务 ), 怎么使用 B 的功能?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

public static func registerAll(serviceMap: Dictionary<String, String>) {

        for (lotus, lotusootName) in serviceMap {

            // lotus, 协议名

            // lotusootName, 包名.类名

            let classStringName = lotusootName

            // 反射,产生类

            // 提供服务的类,一定是 NSObject 的子类,拥有 init 方法 ( 这是个约定 )

            let classType = NSClassFromString(classStringName) as? NSObject.Type

            if let type = classType {

                // 产生对应的实例,强转为遵守协议的 ,即可

                let lotusoot = type.init()

                register(lotusoot: lotusoot, lotusName: lotus)

            }

        }

    }

2, 这里使用 python 脚本注册,编译的时候拿到信息 协议名:包名.类名

通过约定, 标记

1

2

3

4

// @NameSpace(ZLYAccountModule)

// @Lotusoot(AccountLotusoot)

// @Lotus(AccountLotus)

class AccountLotusoot: NSObject, AccountLotus {}

python 脚本找出标记,整合,放入 plist 文件中

1, 脚本入口

1

2

3

4

5

6

7

8

9

10

11

lotusootSuffix = 'Lotusoot'

length = len(sys.argv)

if length != 3 and length != 4:

    print 'parameter error'

    os._exit(1)

if length == 4:

    lotusootSuffix = sys.argv[3]

    lotusootFiles = findLotusoots(scanPath, lotusootSuffix + '.swift')

else:

    // 走这里

    lotusootFiles = findAmbiguityLotusoots(scanPath)

翻阅每一个 swift 文件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

def findAmbiguityLotusoots(path):

    list = []

    for root, subFolders, files in os.walk(path):

        # Ignore 'Target Support Files' and 'Pods.xcodeproj'

         // 不需要处理的,不处理

        if 'Target Support Files' in subFolders:

            subFolders.remove('Target Support Files')

        // 不需要处理的,略

        if 'Pods.xcodeproj' in subFolders:

            subFolders.remove('Pods.xcodeproj')

        // 每一个文件

        for f in files:

             // 每一个 Swift 文件

            if f.endswith('.swift'):

                // 获取标记的配置

                tup = getLotusootConfig(os.path.join(root, f))

                if tup[0] and tup[1] and tup[2]:

                    // 三者都满足,把文件路径,给添加了

                    list.append(f)

    return list

扫描每一行,

获取配置,上面看到的包名,命名空间

@NameSpace(ZLYAccountModule)

上面看到的类名

@Lotusoot(AccountLotusoot)

上面看到的 key ( 协议名 )

@Lotus(AccountLotus)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

def getLotusootConfig(file):

    lotus = ''

    lotusoot = ''

    namespace = ''

    // 翻阅,文件的每一行

    for line in open(file):

        // 上面看到的 key

        if getLotus(line):

            lotus = getLotus(line)

         // 上面看到的类名

        if getLotusoot(line):

            lotusoot = getLotusoot(line)

        // 上面看到的包名,命名空间

        if getNameSpace(line):

            namespace = getNameSpace(line)

    return (lotus, lotusoot, namespace)

… 还有好多,

逻辑是获取配置,写入一个 plist

运行的时候,启动

1

2

3

4

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {

        LotusootCoordinator.registerAll()

        return true

    }

注册就是,读取刚才写入的 plist, 作为 [协议名 : 包名.类名 ] 的字典,

1

2

3

4

5

6

7

@objc public static func registerAll() {

        let lotusPlistPath = Bundle.main.path(forResource: "Lotusoot", ofType: "plist")

        if let lotusPlistPath = lotusPlistPath {

            let map = NSDictionary(contentsOfFile: lotusPlistPath)

            registerAll(serviceMap:  map as! Dictionary<String, String>)

        }

    }

与上文,相呼应

动态思路

进入动态思路, 动态地注册 KV ( 协议名: 服务库名.类名)

上文有一个印象,知道场景,即可

写文,当写长,

怎样体现我,10 年工作经验?

上文没有,坚持凑字数

1,project 拿到 key (协议名) ,可以的

2,project 拿到所有的依赖信息

通过 MachO 可以

3,project 拿到服务类的名称

确保 module B 的类名 = key ( 协议 ) + Cls

MachO 拿到所有依赖库的名称, 每一个 + “.” + key ( 协议 ) + Cls= MachO 拿到所有依赖库的名称, 每一个 + “.” + module B 的类名

然后,看能不能实例化,

能够实例化,就 OK

试了一圈,不能够实例化,就报错

可能依赖 B, 没有添加

可能依赖 B 的类名,写错了

project 拿到服务类的名称, 优雅的

确保 module B 的类名 = key ( 协议 ) + Cls,

硬编码,是不好的

依赖 A ( 放协议的 ), 添加一个协议

1

2

3

public protocol Maid{

    var name: String{ get }

}

module B 里面,必须有一个叫 key (协议) + C 的类

该类,遵守 Maid 协议。

通过协议属性,返回 B 中服务类的名称

1

2

3

4

5

class AccountLotusC: NSObject, Maid{

    var name: String{

        return String(reflecting: AccountLotusoot.self)

    }

}

这个过程,与上文模块化利用协议的设计,比较一致

约定是,实现协议的服务模块,

一定有一个 key + C 的类

提供服务类的名称

硬编码,比较轻微

代码实现

1、MachO 获取命名空间

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

import MachO

lazy var moduleNames: [String] = { () -> [String] in

        // 找到 project 名称,一会去除

        let mainNameTmp = NSStringFromClass(LotusootCoordinator.self)

        guard let mainName = mainNameTmp.components(separatedBy: ".").first else{

            fatalError("emptyMainProject")

        }

        var result = [String]()

        let cnt = _dyld_image_count()

        // 处理所有的包,系统的,用户的

         for i in 0..<cnt{

             if let tmp = _dyld_get_image_name(i){

                 let name = String(validatingUTF8: tmp)

                 // 系统的,不用管

                 if let candidate = name, candidate.hasPrefix("/Users"){

                     if let tmp = candidate.components(separatedBy: "/").last{

                         // 去除 project 的

                         if tmp != mainName{

                             // 拿到用户依赖

                             result.append(tmp)

                         }

                     }

                 }

             }

         }

         return result

    }()

以上,模拟器 OK, 真机没试过 ( 手头没开发证书 )

2、包名+类名的验证

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

@objc public static func lotusoot(lotus: String) -> Any? {

        // 已经缓存了

        if let val = sharedInstance.lotusootMap[lotus]{

            return val

        }

        else{

            var i = 0

            let names = LotusootCoordinator.sharedInstance.moduleNames

            let cnt = names.count

            // 遍历,用户包

            while i < cnt{

                // 按照约定,尝试制造助手类

                let classType = NSClassFromString(names[i] + "." + lotus + "C") as? NSObject.Type

                if let type = classType {

                    // 实例化,助手类

                    let assist = type.init()

                    if let maid = assist as? Maid{

                         // 拿到 module B 的服务类的名称

                        let classType = NSClassFromString(maid.name) as? NSObject.Type

                        if let type = classType {

                            // 将 module B 的服务类,实例化

                            let lotusoot = type.init()

                            register(lotusoot: lotusoot, lotusName: lotus)

                        }

                        // 默认是,一个 module 一个服务类,

                        // 排除掉,使用过的用户类

                        LotusootCoordinator.sharedInstance.moduleNames.remove(at: i)

                        break

                    }

                }

                i+=1

            }

            if let val = sharedInstance.lotusootMap[lotus]{

                return val

            }

            else{

                fatalError("name Module of" + lotus)

            }

        }

    }

GitHub repo https://github.com/BoxDengJZ/ModuleUnImport


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://blog.csdn.net/dengjiangszhan/article/details/125796150
相关文章
  • Flutter Widgets之标签类控件Chip介绍

    Flutter Widgets之标签类控件Chip介绍
    Flutter 标签类控件大全ChipFlutter内置了多个标签类控件,但本质上它们都是同一个控件,只不过是属性参数不同而已,在学习的过程中可以将
  • iOS Lotusoot模块化工具应用的动态思路
    下文,写的是 Swift 依赖 OC 库,没有命名空间 组件化的要点-约定 个人觉得 例如,URL 路由的注册,就是把约定的信息,传过去。作为服务。
  • iOS浮点类型精度问题的原因与解决办法
    前言 相信不少人(其实我觉得应该是每个人)都遇到过一个问题,那就是当服务端返回的JSON数据中出现了小数时,客户端用CGFloat去解析时
  • iOS开发实现计算器功能的代码

    iOS开发实现计算器功能的代码
    效果图 Masonry 使用数组来自动约束 NSArray *buttonArrayOne = @[_buttonAC, _buttonLeftBracket, _buttonRightBracket, _buttonDivide]; //withFixedSpacing: 每个view中间的间
  • iOS自定义雷达扫描扩散动画的代码

    iOS自定义雷达扫描扩散动画的代码
    自己自定义了 一个雷达扫描/扩散效果的View。 扫描View 效果如下: 扩散View 效果如下: 自定义的代码如下: 1. RadarView.h #import UIKit/UIKit.h t
  • iOS实现雷达扫描效果

    iOS实现雷达扫描效果
    具体内容如下 #import UIKit/UIKit.h @interface LTIndicatiorView : UIView@property(nonatomic,strong)UIColor *color;@property(nonatomic,assign)float repeatCount;@property(nonatom
  • IOS NSTimeInterval使用案例介绍
    一 ios 获取时间间隔 想在程序开始或者进入某个界面 ,到结束程序或退出某个界面,获取到这个持续时间. 获取到这个时间还需要转化一个
  • IOS WebRTC的实现原理

    IOS WebRTC的实现原理
    它在2011年5月开放了工程的源代码,在行业内得到了广泛的支持和应用,成为下一代视频通话的标准。 WebRTC的音视频通信是基于P2P,那么什
  • 关于ios配置微信config出现验签失败的问题解决
    在开发中,出现了一个关于微信配置的问题。 使用的开发工具以及开发框架为 uniapp , JSSDK为 jweixin 使用uniapp进行公众号开发,需要在进入
  • iOS实现轮盘动态效果的代码
    一个常用的绘图,主要用来打分之类的动画,效果如下。 主要是iOS的绘图和动画,本来想用系统自带动画实现呢,发现实现不了,用了其他
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计