iOS Swift Protocol的多种应用场景

2020-02-03  本文已影响0人  落夏简叶

Swift 是面向协议编程 (Protocol Oriented Programming,以下简称 POP) 的。使用非常灵活,扩展性非常强。

项目中用到的Protocol很多,将应用的场景总结一下。(开始时不知其滋味,细细品味后欲罢不能,夸,总之是很好用就是了)
优点:

Protocol 作为类型

  1. 数组中可以包含多种类型的数据
private protocol DBAvailableType {}
extension Bool: DBAvailableType {}
extension String: DBAvailableType {}
extension Int: DBAvailableType {}
extension Int16: DBAvailableType {}
extension Double: DBAvailableType {}
extension NSNull: DBAvailableType {}
var arguments: [DBAvailableType] = []
  1. 相似但不同的数据模型,给同一UI赋值(数据是协议类型:有时可能用ABtest两种方式获取的数据,为了兼容和复用)。
protocol MapRoute {
    var length: UInt { get }
    var duration: TimeInterval { get }
}

extension NMARoute: MapRoute {
    var length: UInt {
        return route.length
    }
    
    var duration: TimeInterval {
        return route.duration
    }
}

extension TPPRoute: MapRoute {
    var length: UInt {
        return route.length
    }
    
    var duration: TimeInterval {
        return route.duration
    }
}

埋点

虽然有些埋点可以通过hook的方式无侵入地添加,但是有些业务埋点代码被塞进逻辑中无可避免。开始时是直接写在控制器中调用,但是这样会让控制器变得臃肿。后来想到可以用Protocol,总结一下好处:

protocol TPPSubscriptionPromoAnalyticProtocal {
    func logCompaignOctPageViewEvent(source: TPPCompaignOctPageViewEvent.Source) //定义方法
}


extension TPPSubscriptionPromoAnalyticProtocal {
//利用extension给出默认实现。
    func logCompaignOctPageViewEvent(source: TPPCompaignOctPageViewEvent.Source) {
        let event = TPPCompaignOctPageViewEvent(source: source)
        AnalyticsManager.log(event: event)
    }
}

// 使用时,遵守协议。在需要的地方调用方法即可
class TPPSubscriptionPromoVC: TPPSubscriptionPromoAnalyticProtocal {
}

Protocol 扩展方法和属性

  1. 为UIButton 或者特定的UIView的类添加放大效果
protocol TPPBigEffectProtocol: class {
    func biggerEffect()
}

//为UIButton添加方法效果方法。
extension UIButton: TPPBigEffectProtocol {
    func biggerEffect() {
        UIView.animate(withDuration: 0.25, animations: {
            self.transform = CGAffineTransform.init(scaleX: 1.5, y: 1.5)
        }) { (_) in
            self.transform = CGAffineTransform.identity
        }
    }
}
  1. 获取不同设备横竖屏状态下的有效内容高度(只要遵守了TPPDisplayViewProtocol的类对象都可以直接通过getViewWidth方法获取)
protocol TPPDisplayViewProtocol: AnyObject {
    func getViewWidth() -> CGFloat
}

extension TPPDisplayViewProtocol {
    func getViewWidth() -> CGFloat {
        let orientation = UIApplication.shared.statusBarOrientation
        if orientation == .portrait || orientation == .portraitUpsideDown {
            return UIScreen.main.bounds.width
        } else {
            if iPhoneXSeries {
                return (UIScreen.main.bounds.width - 88)
            } else {
                return UIScreen.main.bounds.width
            }
        }
    }
}
  1. 为一个tableViewCell设置一个唯一标志符,通常让cell 遵循一个协议,在协议里面定义一个uniqueIdentifier。用自己的类名作为唯一标识符。
// 1. 定义一个协议
protocol CellProtocol: class {
    static var uniqueIdentifier: String {get}
}

// 2. 协议扩展来实现属性
extension CellProtocol {
    static var uniqueIdentifier: String {
        return String(describing: type(of: self)).components(separatedBy: ".").first!
    }
}

// 3.调用
// 先遵守协议
class TPPReviewCell: UITableViewCell, CellProtocol {
}
// 在用到这个cell的cellForRow里面
let cell = tableView.dequeueReusableCell(withIdentifier: TPPReviewCell.uniqueIdentifier) as! TPPReviewCell

Protocol 和Delegate的配合使用

  1. 定义协议方法
protocol DropDownMenuDelegate: NSObjectProtocol {
    func menuView(_ menuView: DropdownMenuView, didSelectColumnAt index: Int)
}
  1. 设置delegate属性,调用
DropdownMenuView.swift

weak open var delegate: DropDownMenuDelegate?

if let delegate = delegate {
    delegate.menuView(self, didSelectColumnAt: index)
}
  1. 遵守协议,实现协议方法
TPPTruckDealerDetailController.swift
lazy private var dropMenuView = DropdownMenuView()

dropMenuView.delegate = self

extension TPPTruckDealerDetailController: DropDownMenuDelegate {
    func menuView(_ menuView: DropdownMenuView, didSelectColumnAt index: Int) {
        eventRecord(outcome: "Sort")
    }
}
上一篇 下一篇

猜你喜欢

热点阅读