本机重点探讨扩展的写法
需求:给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<Base>{
let base:Base
init(_ base:Base) {
self.base = base
}
}
- 第二步 定义一个协议
protocol Compatible{
associatedtype CompatableType
var os: CompatableType { get }
}
提示:
CompatableType 自定义变量 具体在实现时写
os 这个一般写自己的名字或者组织的名字
- 第三步 实现这个协议
extension Compatible{
var os:Auto<Self>{
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