Swift3.0 - 设计技巧_扩展深入

本机重点探讨扩展的写法

需求:给UIView 扩展一个获取width 和height 的 属性

extension UIView{
    var width:CGFloat{
        return self.frame.size.width
    }
    var height:CGFloat{
        return self.frame.size.height
    }
}

调用方式

  self.view.width
  self.view.height

分析:

调用方式非常简单,但是但是,如果别人也写了个一样的扩展,或者系统框架以后也增加了一个这样的属性,你写的这个就会报冲突的错误

有人说好办,加个前缀,我们继续改进一下

extension UIView{
    var os_width:CGFloat{
        return self.frame.size.width
    }
    var os_height:CGFloat{
        return self.frame.size.height
    }
}

调用:

    self.view.os_width
    self.view.os_height

这个是oc 延展过来的写法,当然Swift 有自己更优雅的写法,过程有点复杂,我按照步骤写

  • 第一步 创建一个泛型结构体,里面定义一个属性,接受传进来的值
 struct Auto{
    let base:Base
    init(_ base:Base) {
        self.base = base
    }
  }
  • 第二步 定义一个协议
protocol Compatible{
    associatedtype CompatableType 
    var os: CompatableType { get } 
}

提示:

CompatableType 自定义变量 具体在实现时写
os 这个一般写自己的名字或者组织的名字

  • 第三步 实现这个协议
extension Compatible{
    var os:Auto{
        return Auto(self)
    }
}

提示:

Auto 是一个泛型的结构体,Self 代表谁实现了协议Compatible 这个Self 就是谁

  • 第四步 写扩展协议
extension Auto where Base: UIView{
    /// 扩展方法写到这个
    var width:CGFloat{
        return self.base.frame.size.width
    }
    var height:CGFloat{
        return self.base.frame.size.height
    }
}

注意:

这个时候,你如果调用扩展的方法是掉不出来的,因为UIView 下载是没有实现协议Compatible 所以不能调用os这个属性, 刚才说Auto 是泛型,where 后面的意思就是Base 如果是UIView的类型,这个扩展才有效,即给base 为UIView 类型的对象扩展属性,这个时候系统会自动推断Base 为UIView 类型,所以能调出frame的属性

  • 第五步 让UIView 实现协议
extension UIView:Compatible{ 
}

完成上面的五步,就完成了我们的扩展,看一下如何调用

 print(self.view.os.width)
 print(self.view.os.height)

运行结果:

375.0
667.0

你可能感兴趣的:(Swift3.0 - 设计技巧_扩展深入)