美文网首页
Swift-核心之面向协议开发

Swift-核心之面向协议开发

作者: heedaaaaaa | 来源:发表于2018-03-21 16:19 被阅读0次

    Swift is a Protocol-Oriented Programming Language

    Swift 是一门面向协议 (POP) 开发的语言

    Swift 的核心是面向协议编程

    WWDC 对 OOP 很好的诠释:

    Protocol-Oriented Programming in Swift

    POP 面向协议的编程

    面向协议的编程的核心是抽象(Abstraction)和简化(Simplicity) 

    协议的高级使用是协议的延展 

    协议(protocol) + 结构体(struct) > 类(class)

    面向对象面向协议比较

    面向对象是一个很古老的软件开发模式,通过类来实现

    面向协议是苹果在 swift 中主推的,通过协议和结构体,可以代替类

    Swift 中的很多对象都改成了结构体和协议

    并不是所有的类都可以被协议+结构体替代,但大多数是可以被替换的

    面向协议使代码更加灵活,类似于组件化开发,符合工厂方法模式

    实例比较:给一个类添加额外的方法

    通过继承 

    创建一个继承类的子类,在子类中添加方法,以后使用子类即可获取这个方法 

    通过协议 

    为这个方法定义一个协议,那个类需要实现这个方法,协议即可

    使用继承的缺点:

    通过继承添加的方法,不一定每个子类都会使用,使代码冗余

    拥有太多的子类,使类冗余

    对于父类的方法太过依赖,当父类的方法更改后,影响子类的重载方法

    什么时候使用面向对象的类呢?

    协议的高级使用是协议的延展以及和结构体配合

    为协议添加属性, 属性为可读或可写

    protocol MessageModelProtocol {varname: String {getset}varage:  Int {setget}}

    1

    2

    3

    4

    定义一个接受协议的结构体

    struct MessageModel: MessageModelProtocol {varname: String =""varage: Int =0varisMale: Bool =falseinit(with dict: [String: Any]) {self.name = (dict["name"]as? String) ??""self.age = (dict["age"]as? Int) ??0self.isMale = (dict["isMale"]as? Bool) ??false}}

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    对协议进行延展

    extensionMessageModelProtocol{    mutating func test() {self.name ="Hello iPhone 8"}}

    1

    2

    3

    4

    5

    协议的协议

    protocol DemoMessageModelProtocol: MessageModelProtocol {    vardate:Date{setget}}

    1

    2

    3

    4

    具体实例运用:

    给 UIViewController 添加 一个数据为空视图

    给 UIViewController 添加 一个遮挡提示视图

    给 xib 添加一个快速获取示例方法

    ……(对控制器依赖比较小的视图等)

    数据为空或者网络请求失败提示界面

    import UIKitenum EmptyType {    case emptyData    case networkError}protocol EmptyDataSetProtocol { }extension EmptyDataSetProtocol where Self : UIViewController {    func addEmptyView(type: EmptyType? =.emptyData, iconName: String, tipTitle: String, action: Selector? = nil) {        let emptyView = UIView(frame: view.bounds)        emptyView.backgroundColor= UIColor.whiteemptyView.tag=1024view.addSubview(emptyView)        let icomViewW: CGFloat =100let imageView = UIImageView(image: UIImage(named: iconName))        imageView.frame.size= imageView.image?.size?? CGSize(width: icomViewW, height: icomViewW)        imageView.contentMode=.centerimageView.center= CGPoint(x: emptyView.center.x,y: emptyView.center.y-100)        emptyView.addSubview(imageView)        let tipLabel = UILabel()        let margin: CGFloat =20tipLabel.numberOfLines=0tipLabel.font= UIFont.systemFont(ofSize:14)        tipLabel.textColor= UIColor.lightGrayif tipTitle.contains("\n") {            let style = NSMutableParagraphStyle()            style.lineSpacing=5// 设置行间距            style.alignment=.center// 文字居中            let tipString = NSAttributedString(string: tipTitle, attributes: [NSParagraphStyleAttributeName: style])            tipLabel.attributedText= tipString        } else {            tipLabel.text= tipTitle        }        tipLabel.adjustsFontSizeToFitWidth= true        tipLabel.textAlignment=.centertipLabel.sizeToFit()        tipLabel.frame= CGRect(x: margin,y: imageView.frame.maxY+ margin, width: UIScreen.main.bounds.width- margin*2, height: tipLabel.bounds.height)        emptyView.addSubview(tipLabel)        // 网络请求失败        if type ==.networkError{            let reloadButton = UIButton(type:.system)            reloadButton.frame.size= CGSize(width:100, height:36)            reloadButton.center= CGPoint(x: emptyView.center.x,y: tipLabel.frame.maxY+ margin*2)            reloadButton.backgroundColor= UIColor(red:255/255.0, green:42/255.0, blue:102/255.0, alpha:1.0)            reloadButton.layer.cornerRadius=18reloadButton.layer.masksToBounds= true            reloadButton.setTitle("重新加载", for:.normal)            reloadButton.setTitleColor(UIColor.white, for:.normal)            reloadButton.titleLabel?.font= UIFont.systemFont(ofSize:16)            reloadButton.addTarget(self, action: action!, for:.touchUpInside)            emptyView.addSubview(reloadButton)        }    }    func hideEmptyView() {        view.subviews.filter({ $0.tag ==1024}).first?.removeFromSuperview()    }}

    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

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    具体使用:

    class ViewController: UIViewController, EmptyDataSetProtocol {...}

    1

    /// 显示数据为空视图funcshowEmptyDataView(){addEmptyView(type: .emptyData, iconName:"emptyData", tipTitle:"数据为空")}/// 显示请求失败重新加载视图funcshowNetworkErrorReloadView(){addEmptyView(type: .networkError, iconName:"network_error", tipTitle:"网络出问题了,请检查网络", action: #selector(reloadData))}/// 移除空视图/重新加载视图funcremoveEmptyView(){hideEmptyView()}

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    添加 guide 视图 到 window 上

    import UIKitprotocol GuideViewProtocol { }extension GuideViewProtocol where Self : UIViewController {    func showGuideView(with title: String, imageName: String, buttonName: String, sureAction: Selector, cancelAction: Selector) {        let kScreenW: CGFloat = UIScreen.main.bounds.widthlet kMargine: CGFloat =30let backgroundView = UIView(frame: UIScreen.main.bounds)        backgroundView.backgroundColor= UIColor.black.withAlphaComponent(0.3)        backgroundView.tag=1024UIApplication.shared.keyWindow?.addSubview(backgroundView)        let containerView = UIView()        containerView.frame.size= CGSize(width: kScreenW-kMargine*2, height: (kScreenW-kMargine*2) +20)        containerView.backgroundColor= UIColor.whitecontainerView.center= backgroundView.centercontainerView.layer.cornerRadius=15backgroundView.addSubview(containerView)        let tipLabel = UILabel(frame: CGRect(x: kMargine,y:30, width: containerView.bounds.width-kMargine*2, height: kMargine))        tipLabel.font= UIFont.systemFont(ofSize:20)        tipLabel.textColor= UIColor.redtipLabel.textAlignment=.centertipLabel.text= title        containerView.addSubview(tipLabel)        let sureButton = UIButton(type:.system)        sureButton.frame.size= CGSize(width:200, height:30)        sureButton.setTitle(buttonName, for:.normal)        sureButton.setTitleColor(UIColor.white, for:.normal)        sureButton.backgroundColor= UIColor.redsureButton.titleLabel?.font= UIFont.systemFont(ofSize:18)        sureButton.frame.origin.x= (containerView.bounds.width- sureButton.bounds.width)*0.5sureButton.center.y= containerView.bounds.height-20- sureButton.bounds.heightsureButton.layer.cornerRadius=15sureButton.addTarget(self, action: sureAction, for:.touchUpInside)        containerView.addSubview(sureButton)        let centerImageView = UIImageView(image: UIImage(named: imageName))        centerImageView.contentMode=.scaleAspectFitcenterImageView.frame= CGRect(x:30,y: tipLabel.frame.maxY+20, width: containerView.bounds.width-60, height: sureButton.frame.minY- tipLabel.frame.maxY-40)        containerView.addSubview(centerImageView)        let cancelButton = UIButton(type:.custom)        cancelButton.setBackgroundImage(UIImage(named:"cancelButton"), for:.normal)        cancelButton.frame.size= cancelButton.currentBackgroundImage?.size?? CGSize.zerocancelButton.center.x= UIScreen.main.bounds.width*0.5cancelButton.center.y= containerView.frame.maxY+50cancelButton.addTarget(self, action: cancelAction, for:.touchUpInside)        backgroundView.addSubview(cancelButton)    }    func hideGuideView() {        UIView.animate(withDuration:0.25) {            UIApplication.shared.keyWindow?.subviews.filter({ $0.tag ==1024}).first?.removeFromSuperview()        }    }}

    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

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    具体使用

    class ViewController: UIViewController, GuideViewProtocol {...}

    1

    /// 添加指示视图到当前视图的 window 上funcaddGuideView(){showGuideView(with:"您有VIP礼包待领取", imageName:"vip_image", buttonName:"立即领取", sureAction: #selector(sureAction), cancelAction: #selector(removeGuideView))}/// 提示视图上按钮的点击事件funcsureAction(){show(FirstViewController(), sender: nil)hideGuideView()}/// 移除指示视图funcremoveGuideView(){hideGuideView()}

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    修改导航栏左侧按钮

    protocol LeftBarButtonChangeable { }extension LeftBarButtonChangeable where Self :UIViewController{    func changeLeftBarButton(_ imageName: String, action: Selector ) {        let itemButton =UIButton(type:.custom)        itemButton.setImage(UIImage(named: imageName),for:.normal)        itemButton.sizeToFit()        itemButton.addTarget(self, action: action,for:.touchUpInside)self.navigationItem.leftBarButtonItem=UIBarButtonItem(customView: itemButton)    }}

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    具体使用

    classViewController:UIViewController,LeftBarButtonChangeable{override func viewDidLoad() {super.viewDidLoad()        changeLeftBarButton("back_image",action:#selector(backAction))}    func backAction() {        navigationController?.popViewController(animated:true)    }}

    相关文章

      网友评论

          本文标题:Swift-核心之面向协议开发

          本文链接:https://www.haomeiwen.com/subject/xkigqftx.html