iOS 组件化实践

前言:

一直一来,总是听到组件化这个词,项目也进行了组件化. 现在来写写关于组件化的一些实践吧,理论以及组件化的框架大佬都讲的很好了.

简介:

         组件化顾名思义,就是把app 里的模块相互分离开来,既可以进行业务组件的分离,也可以对一些常用的基础组件如网络请求的封装,图片展示等的封装.  举个支付宝的例子, 支付宝这个app 里,集成了蚂蚁财富,口碑.组件化要做的就是支付宝作为主app,运用组件化方法,可以让蚂蚁财富,口碑很便捷的继承进支付宝,蚂蚁财富,口碑还可以作为单独的app运行. 通过github 或者自己建的代码仓库,让口碑,蚂蚁财富团队开发的项目更新,提交代码,支付宝可以通过cocoapods 继承进支付宝.这样是不是管理起来很方便.

优点: 

    降低耦合度,小模块可以单独开发,单独测,适于多人团队协作开发. 

缺点:  增加项目复杂度,还会有版本同步,以及,项目过大后,实施组件化费时费力等,

所以建议项目快速迭代一个版本以后,即有计划的引入组件化.省掉了后期实施组件化的大麻烦.

组件化我这边是用的cocoapods创建.

1 我们先建立一个工程吧(你可以把这个工程当做你要组件化的项目,毕竟大部分项目一开始是没有进行组件化的,都是做了一段时间之后才着手组件化)

2 假定我们要分离的第一个模块叫做 口碑 我们起名字叫 WordOfMouth

打开终端,进入到我们要放置口碑模块的位置. 终端执行  pod lib create  WordOfMouth如下:

Cloning `https://github.com/CocoaPods/pod-template.git` into `WordOfMouth`.
Configuring WordOfMouth template.
security: SecKeychainSearchCopyNext: The specified item could not be found in the keychain.
What platform do you want to use?? [ iOS / macOS ]
 > iOS

What language do you want to use?? [ Swift / ObjC ]
 > Swift

Would you like to include a demo application with your library? [ Yes / No ]
 > Yes
选择No的话子工程无法单独运行调用代码.

Which testing frameworks will you use? [ Quick / None ]
 > None

Would you like to do view based testing? [ Yes / No ]
 > No

得到的工程如下:

模块代码自动集成到了 Development Pods.

 需要集成的子模块的项目实际是存放在 WordOfMouth/WordOfMouth/Classes  这个文件夹下

 接下来我们随意新建个vc来替代ReplaceMe.swift. 

我新建了一个 WordOfMouthMainViewController 的vc, 放在classess 里然后

在终端进入到 WordOfMouth/Example 文件夹下 来一下我们熟悉的 pod install

有了哈,如图:

我现在WordOfMouth这个项目里调用一下 WordOfMouthMainViewController. 

1 ViewController 里代码如下

import UIKit
import WordOfMouth

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "口碑模块"
        view.addSubview(wordOfMouthBtn)
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    private lazy var wordOfMouthBtn: UIButton = {
     let btn = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 30))
        btn.setTitle("口碑", for: .normal)
        btn.setTitleColor(UIColor.black, for: .normal)
        btn.addTarget(self, action: #selector(goWordOfMouth), for: .touchUpInside)
        return btn
       }()
    
    @objc func goWordOfMouth() {
        print("跳转到口碑页面")
        // 实际组件化的时候,这样调用肯定是不合适的. 方便实践组件化,暂时先这么写.
        let vc = WordOfMouthMainViewController()
        self.navigationController?.pushViewController(vc, animated: true)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

WordOfMouthMainViewController 代码如下

import UIKit

public class WordOfMouthMainViewController: UIViewController {

    override public func viewDidLoad() {
        super.viewDidLoad()
        self.title = "口碑"
        self.view.backgroundColor = UIColor.white
        // Do any additional setup after loading the view.
    }
}

此处需要注意两点

1 模块外调用,需用public修饰切记切记.    不熟悉的朋友可以着重 了解下private,fileprivate,internal,public 和 open.

2 WordOfMouthMainViewController 改变之后pod install  发觉没有改变,需cmd+ shift + k clean 一下,或者Podfile 加如下一句话

install! 'cocoapods', :disable_input_output_paths => true

接下来我们在主工程里引用口碑这个模块.

终端进入到 主工程目录下  pod init  初始化 Podfile 文件.

然后 vim Podfile 文件里引用  WordOfMouth

pod 'WordOfMouth', :path => '../workspace/WordOfMouth'    

Podfile 文件如下

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
install! 'cocoapods', :disable_input_output_paths => true

target 'ComponentDemo' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for ComponentDemo

  pod 'WordOfMouth', :path => '../workspace/WordOfMouth'


  target 'ComponentDemoTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'ComponentDemoUITests' do
    inherit! :search_paths
    # Pods for testing
  end

end

接下来我们在 新建一个组件名字叫做蚂蚁财富 用于代码放在git上然后用cocopods调用.

蚂蚁财富的模块 创建跟上面一样.

然后将创建好的模块上传到github. 或者公司自己的gitlab. 等等,这里我用一个国内的git 码云.

在账号里新建一个仓库.

在这里我把这个仓库设置为公开,方便大家调用.

然后 可以git clone git@gitee.com:godlovexq/AntWealth.git

把原来创建的工程AntWealth下的文件放到git 的AntWealth目录下.

然后cd AntWealth

git add .

git commit -m "code add"

git push 

好了码云上已经有代码了

然后 主工程 的Podfie 引用

pod 'AntWealth', :git => 'git@gitee.com:godlovexq/AntWealth.git'

或者引用某个tag

pod 'AntWealth', :git => 'git@gitee.com:godlovexq/AntWealth.git', :tag => '0.1.0' 

指定版本需 有对应的tags  

git tag 'v0.1.0’  -m ‘ 0.1.0备份'    

git push --tags

如上引用 只需要关注

AntWealth.podspec 里的s.version版本号就好,下面那一堆暂时不用管,

或者直接如引用三方库那样. 

pod 'AntWealth', '~> 0.1.0' (这个方式我这边暂时没弄通,用的上面的办法)

这时候需要加如下两句话,告诉pod 从这两个地址搜索

source 'https://gitee.com/godlovexq/AntWealth.git'
source 'https://github.com/CocoaPods/Specs.git'

比较麻烦,不建议.

 另外,资讯了一些大佬,通俗的做法都是把代码直接上传到公司服务器,需要的时候,本地引用省去了代码版本控制的麻烦.(通过公司git 控制版本) 也是一个不错的选择.以上,完.

建议此大佬出的组件化方案

https://casatwy.com/iOS-Modulization.html

具体实践:

1 在组件里写好中间件. 代码如下

AntWealth+CTExt.swift:

//
//  AntWealth+CTExt.swift
//  AntWealth_Example
//
//  Created by qiangfei dong on 2020/6/11.
//  Copyright © 2020 CocoaPods. All rights reserved.
//

import CTMediator
public extension CTMediator {
    @objc func AntWealth_AntWealthController(callback:@escaping (String) -> Void,name:String) -> UIViewController? {
        let params = [
            "callback":callback,
            kCTMediatorParamsKeySwiftTargetModuleName:"AntWealth",
            "name": name
            ] as [AnyHashable : Any]
        print(name)
        if let viewController = self.performTarget("AntWealth", action: "AntWealthViewController", params: params, shouldCacheTarget: false) as? UIViewController {
            return viewController
        }
        return nil
    }
}

Target_AntWealth.swift:

import UIKit
   
@objc class Target_AntWealth: NSObject {
    @objc func Action_AntWealthViewController(_ params: [AnyHashable: Any]) ->
            UIViewController {
            if let callback = params["callback"] as? (String) -> Void {
                callback("success")
            }
            print("这里可以穿参数")
            print(params)
            let vc = AntWealthViewController()
            if let name = params["name"] {
                vc.name = name as! String
            }
            return vc
    }
}

Podfile 引用 pod 'CTMediator'

AntWealth.podspec 里 依赖   s.dependency 'CTMediator'

主工程里声明 调用:

import UIKit
import AntWealth
import CTMediator

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "蚂蚁财富模块"
        
        
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        //let vc = AntWealthViewController()
        //self.navigationController?.pushViewController(vc, animated: true)
        
        let vc = CTMediator.sharedInstance().AntWealth_AntWealthController(callback: { (str) in
            print(str)
        }, name: "传参")
        if let tempVC = vc {
            self.navigationController?.pushViewController(tempVC, animated: true)
        }
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值