为了账号安全,请及时绑定邮箱和手机立即绑定

MG--Swift面向协议开发

标签:
iOS Swift

得益于面向对象语言的特性 (封装、继承、多态) 在我们熟悉的设计模式中渐渐形成统一的软件开发思想,但是由于OC的局限性, 使得iOS开发组件化编程变得十分繁琐,需要将一些功能拆分为类,在抽取某些功能作为基类的不断运用中,代码的可移植性逐渐减弱。就如同一棵树,从主干到各个分支,每个分支再长成细枝末叶。代码的耦合性也相应增加。随着苹果 swift 语言的推出,对于传统OC 语言取其精华,弃其糟粕。 加上开源社区众大神的齐力维护。逐渐成为一门非常优秀的高级语言。其中Swift中的面向协议编程思想就是其中很有代表性的一项优秀组成部分。

Swift的 POP 是使用了继承的思想,它模拟了多继承关系,实现了代码的跨父类复用,同时也不存在 is-a 关系。swift中主类和 extension扩展类 的协同工作,保留了 在主类中定义方法 在所继承的类中进行实现的特性,又新增了在 extension拓展类 中定义并实现的方法在任何继承自此协议的类中可以任意调用,从而实现组件化编程。

自定义协议

  • 于是我们可以使用协议做一些优化,精简开发中所写代码,👇请看代码
//
//  MGProtocol+extesnsion.swift
//  MGSDK
//
//  Created by Nicky Y M LIU_SP on 2021/1/11.
//  Copyright © 2021 Nicky Y M LIU_SP. All rights reserved.
//

import UIKit

public protocol MGReusableViewAble: class {}
extension MGReusableViewAble where Self: UIView {
    public static var reuseIdentifier: String {
        return String("\(self)")
    }
}

public protocol MGNibLoadAbleViewAble: class { }
extension MGNibLoadAbleViewAble where Self: UIView {
    public static func loadViewWithNib() -> Self {
        return Bundle.main.loadNibNamed("\(self)", owner: nil, options: nil)?.last! as! Self
    }
    
    public static var nibName: String {
        return String("\(self)")
    }
}


// MARK: - extension
extension UITableView {
    // Register
    public func registerCellFromNib<T: UITableViewCell>(_: T.Type) where T: MGReusableViewAble, T: MGNibLoadAbleViewAble {
        let Nib = UINib(nibName: T.nibName, bundle: nil)
        register(Nib, forCellReuseIdentifier: T.reuseIdentifier)
    }
    
    public func registerCell<T: UITableViewCell>(_: T.Type) where T: MGReusableViewAble {
        register(T.self, forCellReuseIdentifier: T.reuseIdentifier)
    }
    
    public func registerHeaderFooterFromNib<T: UITableViewHeaderFooterView>(_: T.Type) where T: MGReusableViewAble, T: MGNibLoadAbleViewAble {

        let Nib = UINib(nibName: T.nibName, bundle: nil)
        register(Nib, forHeaderFooterViewReuseIdentifier: T.reuseIdentifier)
    }
    
    public func registerHeaderFooter<T: UITableViewHeaderFooterView>(_: T.Type) where T: MGReusableViewAble {
        register(T.self, forHeaderFooterViewReuseIdentifier: T.reuseIdentifier)
    }
    
    public func dequeueReusableCell<T: UITableViewCell>(forIndexPath indexPath: IndexPath) -> T where T: MGReusableViewAble {
        guard let cell = dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath) as? T else {
          fatalError("Could not dequeue cell with identifier: \(T.reuseIdentifier)")
      }
      return cell
    }
}

extension UICollectionView {
    // Register
    public func registerCellFromNib<T: UICollectionViewCell>(_: T.Type) where T: MGReusableViewAble, T: MGNibLoadAbleViewAble {
        let Nib = UINib(nibName: T.nibName, bundle: nil)
        register(Nib, forCellWithReuseIdentifier: T.reuseIdentifier)
    }
    
    public func registerCell<T: UICollectionViewCell>(_: T.Type) where T: MGReusableViewAble {
        register(T.self, forCellWithReuseIdentifier: T.reuseIdentifier)
    }
    
    
    // elementKindSectionHeader  elementKindSectionFooter
    public func registerHeaderFooter<T: UICollectionReusableView>(_: T.Type, elementKind: String) where T: MGReusableViewAble, T: MGNibLoadAbleViewAble {
        let Nib = UINib(nibName: T.nibName, bundle: nil)
        register(Nib, forSupplementaryViewOfKind: elementKind, withReuseIdentifier:  T.reuseIdentifier)
    }
    
    public func registerHeaderFooter<T: UICollectionReusableView>(_: T.Type, elementKind: String) where T: MGReusableViewAble {
        register(T.self, forSupplementaryViewOfKind: elementKind, withReuseIdentifier:  T.reuseIdentifier)
    }
    
    // dequeueReusable
    public func dequeueReusableCell<T: UICollectionViewCell>(forIndexPath indexPath: IndexPath) -> T where T: MGReusableViewAble {
        guard let cell = dequeueReusableCell(withReuseIdentifier: T.reuseIdentifier, for: indexPath) as? T else {
          fatalError("Could not dequeue cell with identifier: \(T.reuseIdentifier)")
      }
      return cell
    }
}

使用

  • 我们如何使用呢,只需要创建的class或者struct 遵守协议,便拥有了此方法,
  • 举个例子来说,.xib 加载 UIView,只要在xib加载的类中继承此协议MGNibLoadAbleViewAble\color{#FF0000}{MGNibLoadAbleViewAble}MGNibLoadAbleViewAbleclass MGRedView: UIView, MGNibLoadAbleViewAble {},就可以在需要初始化此对象时直接调用let view = MGRedView.loadViewWithNib(),也可以查看下面的代码

下面我们来精简UITableView的注册和循环利用方法

  • MGTableViewCell遵守MGReusableViewAble\color{#0000FF}{MGReusableViewAble}MGReusableViewAble协议
import UIKit
import MGSDK

class MGTableViewCell: UITableViewCell, MGReusableViewAble  {

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }
}
  • 主要看registerCell\color{#0000FF}{registerCell}registerCelldequeueReusableCell\color{#0000FF}{dequeueReusableCell}dequeueReusableCell方法

import UIKit
import MGSDK

class MGTabViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = .white

        self.view.addSubview(self.tableView)
        tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor,constant: 0).isActive = true
        tableView.topAnchor.constraint(equalTo: self.view.topAnchor,constant: 0).isActive = true
        tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor,constant: 0).isActive = true
        tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor,constant: 0).isActive = true
    }
    
    private lazy var tableView: UITableView = {
        let tableView = UITableView(frame: self.view.frame, style: UITableView.Style.plain)
        tableView.delegate = self
        tableView.dataSource = self
        tableView.tableFooterView = UIView()
        tableView.registerCell(MGTableViewCell.self)
        return tableView
    }()
}

extension MGTabViewController :UITableViewDelegate,UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        10
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(forIndexPath: indexPath) as MGTableViewCell
        return cell
    }
}

图片描述

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消