前言
由于新工作只做IOS开发,所以技术的中心开始像Swift方向转变。顺便也把以前封装的老库在拿过来改改弄弄。我开发风格一直追求的是极简风,所以减少代码量一直是我这几年干的事情。最近把我减少代码的一些东西分享下。
今天分享的是Snapkit,IOS上dsl风格的优雅的实现约束布局,用了好几个形容词。
SnapKit
首先看它的官方介绍如下:
image.png
本身的框架就是为了实现布局代码的减少,号称用代码可以很轻松的完成 布局的构建。当然事实上也是这样的。
然后DSL风格是最近框架的流行风,实现得益于闭包语法糖的强大。
//创建约束
view.snp.makeConstraints{
$0.top.equalToSuperview().offset(100)
$0.left.equalToSuperview()
$0.right.equalToSuperview()
$0.height.equalTo(300)
}
//修改
view.snp.removeConstraints{
$0.top.equalToSuperview().offset(100)
.....
}
//更新
view.snp.updateConstraints{
$0.top.equalToSuperview().offset(100)
.....
}
用法是非常简单,基本上用一次都会。
那么无论从优雅度 还是 简单度都是非常不错,那为什么还要封装它?
因为代码行数太多了, 一个控件的行数 = 约束(3-6行) + view的构建和设置 (3-5行) + DSL的大括号(2行) + addSubView (1行) = 一个控件要花掉至少10行的代码。
如果有10个控件 单单布局就要花掉100代码,好恐怖。
简化
如何简化,就是找代码的共同点 然后去掉。
当然语法糖的无法无天,让我们的简化思想变得胆大包天。和以前封装一样,我首先问自己想要实现什么方式?
下面是我无法无天的思想
//方法一 运算符 + 类目分离 (放弃 代码嫌多)
10 <<< view.h >> (otherView,10)
(otherView,15) <<< view.v >> (otherView,10)
view.widht = 10
10 <<< view.h >> (otherView,10)
(otherView,15) <<< view.v >> (otherView,10)
view.widht = 10
//方法二 运算符 + 链式调用 (放弃 运算符多记不住 且没有联想功能 组合的优先级设置有难度 )
self.view ++ leftTestView.make <<< -10 >>> 10 ^~ (centerView,10)
self.view ++ topTestView.make ~^ -10 >>< (centerView,10)
self.view ++ midTestView.make ~- 0 <<> (centerView,10)
//方法三 纯链式
self ++ centerView.make.width(100).height(60).centerParent()
self ++ leftTestView.make.left(10).right(10).topToBottom(20,centerView)
self ++ topTestView.make.bottomToTop(-10).rightToLeft(10, centerView)
其实封装看方法名字 就能知道意思,下面讲一些改进的地方,然后贴出源码
增加等边 横竖父空间边距 方便父控件包裹内容
view.equilateral(50).horizontalToParent(10,13)
view.equilateralToParent(0.5,0.4).verticalToParent(10,13)
对同一个控件约束缓存
//如果都是对centerView约束 那么前面可以不指定
self ++ leftTestView.make.left(10).right(10).topToBottom(20,centerView)
安全!!! 这样更新不会报错 <Snp的updateConstraints的时候 如果没有设置这个约束 会报错>
// 这样更新不会报错
leftTestView.makeCache.left(10).right(10).topToBottom(20,centerView).update()
支持多下标更换 约束 note: 索引不会越界 随心所欲
//如果我想改其中某个约束 不需要重新remake
leftCons[2,4,6] = {
$0.topToBottom(20,centerView)
$0.right(12,centerView)
}
拒绝内存泄露
好处
代码少多少? 原来的10行代码 = 现在只要1行,你觉得少多少呢?
配合后面即将分享的 实现Flexbox 支持流线布局 + 极简的控件初始化会让代码量上一个层次。
举个例子<实现如下如的布局>:
image.png
//不需要指定父容器尺寸 自适应
self ++ nameView.leftToParent(16).centerYToParent()
self ++ rightArrowView.rightToParent(-16).centerYToParent()
self ++ faceView.verticalToParent(10,-10).rightToLeft(10,rightArrowView)
源码
import Foundation
import SnapKit
//##############################################################
//# 对齐方式 左<< 右>> 水平基线 | 上^ 下~ 垂直基线 -
//# 目标 !
//# 左约束 << <| <>
//# 右约束 >< >| >>
//# 上约束 ^^ ^- ^_
//# 下约束 _^ _- __
//# 水平约束 |= |< |>
//# 垂直约束 -- -^ -~
//# #居中 >><<
//# 边距相同 <<>>
//# 宽高度等于 |== -==
//##############################################################
infix operator ++ : ViewSetupPrecedence
//左边约束
infix operator <<< : LeftPrecedence
infix operator <<| : LeftPrecedence
infix operator <<> : LeftPrecedence
//右边约束
infix operator >>< : LeftPrecedence
infix operator >>| : LeftPrecedence
infix operator >>> : LeftPrecedence
//顶部约束
infix operator ^^ : LeftPrecedence
infix operator ^- : LeftPrecedence
infix operator ^~ : LeftPrecedence
//底部约束
infix operator ~^ : LeftPrecedence
infix operator ~- : LeftPrecedence
infix operator ~~ : LeftPrecedence
//水平约束
infix operator |= : LeftPrecedence
infix operator |< : LeftPrecedence
infix operator |> : LeftPrecedence
//垂直约束
infix operator -- : LeftPrecedence
infix operator -^ : LeftPrecedence
infix operator -~ : LeftPrecedence
//居中
infix operator >><< : LeftPrecedence
infix operator <<>> : LeftPrecedence
prefix operator =>
precedencegroup ViewSetupPrecedence {
associativity: left
higherThan: AssignmentPrecedence
lowerThan: BitwiseShiftPrecedence
}
precedencegroup LeftPrecedence {
associativity: left
higherThan: ViewSetupPrecedence
lowerThan: BitwiseShiftPrecedence
}
enum SimplifyAlignment {
case begin
case middle
case end
}
extension UIView {
var make : WrapConstraintMaker { return WrapConstraintMaker(self) }
var makeCache : WrapConstraintMaker { return WrapConstraintMaker(self,true) }
@discardableResult
static func ++ (left: UIView, right: WrapConstraintMaker) -> WrapConstraintMaker{
guard let sView = right.mineView else { return right }
left.addSubview(sView)
sView.snp.makeConstraints { constraint in
right.buildMakes(constraint)
}
return right
}
}
extension UIViewController {
@discardableResult
static func ++ (left: UIViewController, right: WrapConstraintMaker) -> WrapConstraintMaker {
return left.view ++ right
}
}
class WrapConstraintMaker {
//不在使用 weak 防止变量提前释放 改为手动释放 fileprivate
var mineView : UIView? = nil
//当缓存的时候
weak var cacheView : UIView? = nil
var isCache : Bool = false
private var allMakers = [( (ConstraintMaker)-> Void )]()
//暂存的约束 用于
private var stashMakers:[( (ConstraintMaker)-> Void )]? = nil
private var lastMakers = [( (ConstraintMaker,UIView)-> Void )]()
init(_ view:UIView,_ isCache : Bool = false){
self.mineView = view
self.isCache = isCache
if isCache { self.cacheView = view }
}
private func hRelateTarget(_ host:UIView, _ alig : SimplifyAlignment) -> ConstraintRelatableTarget {
var target:ConstraintRelatableTarget?
switch alig {
case .end:
target = host.snp.right
case .middle:
target = host.snp.centerX
default:
target = host.snp.left
}
return target!
}
private func vRelateTarget(_ host:UIView, _ alig : SimplifyAlignment) -> ConstraintRelatableTarget {
var target:ConstraintRelatableTarget?
switch alig {
case .end:
target = host.snp.bottom
case .middle:
target = host.snp.centerY
default:
target = host.snp.top
}
return target!
}
private func lastProcess(_ curView:UIView ){
lastMakers.forEach{ process in
allMakers.append{ m in
process(m,curView)
}
}
lastMakers.removeAll()
}
private func addMakeProcess(_ ardView:UIView?, _ process : @escaping (ConstraintMaker,UIView)-> Void ) -> WrapConstraintMaker{
if let view = ardView {
lastProcess(view)
if let _ = stashMakers {
stashMakers?.append{ process($0,view) }
} else {
allMakers.append{ process($0,view) }
}
} else {
lastMakers.append(process)
}
return self
}
fileprivate func buildMakes(_ cons: ConstraintMaker){
allMakers.forEach{ $0(cons) }
if !isCache { allMakers.removeAll() }
mineView = nil
}
private func addMakeProcessImmediately(_ process : @escaping (ConstraintMaker)-> Void ) -> WrapConstraintMaker{
if let _ = stashMakers {
stashMakers?.append(process)
} else {
allMakers.append(process)
}
return self
}
//MARK: ------------- 左约束 ------------------
@discardableResult
private func leftConstraint( _ ardView:UIView?,_ offset: CGFloat,_ alignment: SimplifyAlignment ) -> WrapConstraintMaker{
return addMakeProcess(ardView){ m,v in m.left.equalTo( self.hRelateTarget(v,alignment) ).offset(offset) }
}
@discardableResult
func left( _ offset: CGFloat = 0 ,_ ardView:UIView? = nil ) -> WrapConstraintMaker {
return leftConstraint(ardView,offset,SimplifyAlignment.begin)
}
@discardableResult
func leftToParent( _ offset: CGFloat = 0 ) -> WrapConstraintMaker {
return addMakeProcessImmediately{ $0.left.equalToSuperview().offset(offset) }
}
@discardableResult
static func <<< (left: WrapConstraintMaker, right: (UIView?,CGFloat)) -> WrapConstraintMaker {
return left.leftConstraint( right.0,right.1,SimplifyAlignment.begin )
}
@discardableResult
static func <<< (left: WrapConstraintMaker, right:CGFloat ) -> WrapConstraintMaker { return left <<< (nil ,right) }
@discardableResult
func leftToCenter( _ offset: CGFloat = 0 ,_ ardView:UIView? = nil ) -> WrapConstraintMaker {
return leftConstraint(ardView,offset,SimplifyAlignment.middle)
}
@discardableResult
static func <<| (left: WrapConstraintMaker, right: (UIView?,CGFloat)) -> WrapConstraintMaker {
return left.leftConstraint( right.0,right.1,SimplifyAlignment.middle )
}
@discardableResult
static func <<| (left: WrapConstraintMaker, right:CGFloat ) -> WrapConstraintMaker { return left <<| (nil ,right) }
@discardableResult
func leftToRight( _ offset: CGFloat = 0 ,_ ardView:UIView? = nil ) -> WrapConstraintMaker {
return leftConstraint(ardView,offset,SimplifyAlignment.end)
}
@discardableResult
static func <<> (left: WrapConstraintMaker, right: (UIView?,CGFloat)) -> WrapConstraintMaker {
return left.leftConstraint( right.0,right.1,SimplifyAlignment.end )
}
@discardableResult
static func <<> (left: WrapConstraintMaker, right:CGFloat ) -> WrapConstraintMaker { return left <<> (nil ,right) }
//MARK: ------------- 右对齐 ------------------
@discardableResult
private func rightConstraint ( _ ardView:UIView?,_ offset: CGFloat,_ alignment: SimplifyAlignment ) -> WrapConstraintMaker{
return addMakeProcess(ardView){ m,v in m.right.equalTo( self.hRelateTarget(v,alignment) ).offset(offset) }
}
@discardableResult
func rightToLeft( _ offset: CGFloat = 0 ,_ ardView:UIView? = nil ) -> WrapConstraintMaker {
return rightConstraint(ardView,offset,SimplifyAlignment.begin)
}
@discardableResult
static func >>< (left: WrapConstraintMaker, right: (UIView?,CGFloat)) -> WrapConstraintMaker {
return left.rightConstraint( right.0,right.1,SimplifyAlignment.begin )
}
@discardableResult
static func >>< (left: WrapConstraintMaker, right:CGFloat ) -> WrapConstraintMaker { return left >>< (nil ,right) }
@discardableResult
func rightToCenter( _ offset: CGFloat = 0 ,_ ardView:UIView? = nil ) -> WrapConstraintMaker {
return rightConstraint(ardView,offset,SimplifyAlignment.middle)
}
@discardableResult
static func >>| (left: WrapConstraintMaker, right: (UIView?,CGFloat)) -> WrapConstraintMaker {
return left.rightConstraint( right.0,right.1,SimplifyAlignment.middle )
}
@discardableResult
static func >>| (left: WrapConstraintMaker, right:CGFloat ) -> WrapConstraintMaker { return left >>| (nil ,right) }
@discardableResult
func right( _ offset: CGFloat = 0 ,_ ardView:UIView? = nil ) -> WrapConstraintMaker {
return rightConstraint(ardView,offset,SimplifyAlignment.end)
}
@discardableResult
func rightToParent( _ offset: CGFloat = 0 ) -> WrapConstraintMaker {
return addMakeProcessImmediately{ $0.right.equalToSuperview().offset(offset) }
}
@discardableResult
static func >>> (left: WrapConstraintMaker, right: (UIView?,CGFloat)) -> WrapConstraintMaker {
return left.rightConstraint( right.0,right.1,SimplifyAlignment.end )
}
@discardableResult
static func >>> (left: WrapConstraintMaker, right:CGFloat ) -> WrapConstraintMaker { return left >>> (nil ,right) }
//MARK: ------------- 顶部约束 ------------------
@discardableResult
private func topConstraint ( _ ardView:UIView?,_ offset: CGFloat,_ alignment: SimplifyAlignment ) -> WrapConstraintMaker{
return addMakeProcess(ardView){ m,v in m.top.equalTo( self.vRelateTarget(v,alignment) ).offset(offset) }
}
@discardableResult
func top( _ offset: CGFloat = 0 ,_ ardView:UIView? = nil ) -> WrapConstraintMaker {
return topConstraint(ardView,offset,SimplifyAlignment.begin)
}
@discardableResult
func topToParent( _ offset: CGFloat = 0 ) -> WrapConstraintMaker {
return addMakeProcessImmediately{ $0.top.equalToSuperview().offset(offset) }
}
@discardableResult
static func ^^ (left: WrapConstraintMaker, right: (UIView?,CGFloat)) -> WrapConstraintMaker {
return left.topConstraint( right.0,right.1,SimplifyAlignment.begin )
}
@discardableResult
static func ^^ (left: WrapConstraintMaker, right:CGFloat ) -> WrapConstraintMaker { return left ^^ (nil ,right) }
@discardableResult
func topToCenter( _ offset: CGFloat = 0 ,_ ardView:UIView? = nil ) -> WrapConstraintMaker {
return topConstraint(ardView,offset,SimplifyAlignment.middle)
}
@discardableResult
static func ^- (left: WrapConstraintMaker, right: (UIView?,CGFloat)) -> WrapConstraintMaker {
return left.topConstraint( right.0,right.1,SimplifyAlignment.middle )
}
@discardableResult
static func ^- (left: WrapConstraintMaker, right:CGFloat ) -> WrapConstraintMaker { return left ^- (nil ,right) }
@discardableResult
func topToBottom( _ offset: CGFloat = 0 ,_ ardView:UIView? = nil ) -> WrapConstraintMaker {
return topConstraint(ardView,offset,SimplifyAlignment.end)
}
@discardableResult
static func ^~ (left: WrapConstraintMaker, right: (UIView?,CGFloat)) -> WrapConstraintMaker {
return left.topConstraint( right.0,right.1,SimplifyAlignment.end )
}
@discardableResult
static func ^~ (left: WrapConstraintMaker, right:CGFloat ) -> WrapConstraintMaker { return left ^~ (nil ,right) }
//MARK: ------------- 底部约束 ------------------
@discardableResult
private func bottomConstraint ( _ ardView:UIView?,_ offset: CGFloat,_ alignment: SimplifyAlignment ) -> WrapConstraintMaker{
return addMakeProcess(ardView){ m,v in m.bottom.equalTo( self.vRelateTarget(v,alignment) ).offset(offset) }
}
@discardableResult
func bottomToTop( _ offset: CGFloat = 0 ,_ ardView:UIView? = nil ) -> WrapConstraintMaker {
return bottomConstraint(ardView,offset,SimplifyAlignment.begin)
}
@discardableResult
static func ~^ (left: WrapConstraintMaker, right: (UIView?,CGFloat)) -> WrapConstraintMaker {
return left.bottomConstraint( right.0,right.1,SimplifyAlignment.begin )
}
@discardableResult
static func ~^ (left: WrapConstraintMaker, right:CGFloat ) -> WrapConstraintMaker { return left ~^ (nil ,right) }
@discardableResult
func bottomToCenter( _ offset: CGFloat = 0 ,_ ardView:UIView? = nil ) -> WrapConstraintMaker {
return bottomConstraint(ardView,offset,SimplifyAlignment.middle)
}
@discardableResult
static func ~- (left: WrapConstraintMaker, right: (UIView?,CGFloat)) -> WrapConstraintMaker {
return left.bottomConstraint( right.0,right.1,SimplifyAlignment.middle )
}
@discardableResult
static func ~- (left: WrapConstraintMaker, right:CGFloat ) -> WrapConstraintMaker { return left ~- (nil ,right) }
@discardableResult
func bottom( _ offset: CGFloat = 0 ,_ ardView:UIView? = nil ) -> WrapConstraintMaker {
return bottomConstraint(ardView,offset,SimplifyAlignment.end)
}
@discardableResult
func bottomToParent( _ offset: CGFloat = 0 ) -> WrapConstraintMaker {
return addMakeProcessImmediately{ $0.bottom.equalToSuperview().offset(offset) }
}
@discardableResult
static func ~~ (left: WrapConstraintMaker, right: (UIView?,CGFloat)) -> WrapConstraintMaker {
return left.bottomConstraint( right.0,right.1,SimplifyAlignment.end )
}
@discardableResult
static func ~~ (left: WrapConstraintMaker, right:CGFloat ) -> WrapConstraintMaker { return left ~~ (nil ,right) }
//MARK: ------------- 水平对齐 ------------------
@discardableResult
private func centerXConstraint ( _ ardView:UIView?,_ offset: CGFloat,_ alignment: SimplifyAlignment ) -> WrapConstraintMaker {
return addMakeProcess(ardView){ m,v in m.centerX.equalTo( self.hRelateTarget(v,alignment) ).offset(offset) }
}
@discardableResult
func centerX( _ offset: CGFloat = 0 ,_ ardView:UIView? = nil ) -> WrapConstraintMaker {
return centerXConstraint(ardView,offset,SimplifyAlignment.middle)
}
@discardableResult
func centerXToParent( _ offset: CGFloat = 0) -> WrapConstraintMaker {
return addMakeProcessImmediately{ $0.centerX.equalToSuperview().offset(offset) }
}
@discardableResult
static func |= (left: WrapConstraintMaker, right: (UIView?,CGFloat)) -> WrapConstraintMaker {
return left.centerXConstraint( right.0 , right.1 , SimplifyAlignment.middle )
}
@discardableResult
static func |= (left: WrapConstraintMaker, right:CGFloat ) -> WrapConstraintMaker { return left |= (nil ,right) }
@discardableResult
func centerXToLeft( _ offset: CGFloat = 0 ,_ ardView:UIView? = nil ) -> WrapConstraintMaker {
return centerXConstraint(ardView,offset,SimplifyAlignment.begin)
}
@discardableResult
static func |< (left: WrapConstraintMaker, right: (UIView?,CGFloat)) -> WrapConstraintMaker {
return left.centerXConstraint( right.0 , right.1 , SimplifyAlignment.begin )
}
@discardableResult
static func |< (left: WrapConstraintMaker, right:CGFloat ) -> WrapConstraintMaker { return left |< (nil ,right) }
@discardableResult
func centerXToRight( _ offset: CGFloat = 0 ,_ ardView:UIView? = nil ) -> WrapConstraintMaker {
return centerXConstraint(ardView,offset,SimplifyAlignment.end)
}
@discardableResult
static func |> (left: WrapConstraintMaker, right: (UIView?,CGFloat)) -> WrapConstraintMaker {
return left.centerXConstraint( right.0 , right.1 , SimplifyAlignment.end )
}
@discardableResult
static func |> (left: WrapConstraintMaker, right:CGFloat ) -> WrapConstraintMaker { return left |> (nil ,right) }
//MARK: ------------- 垂直对齐 ------------------
@discardableResult
private func centerYConstraint ( _ ardView:UIView?,_ offset: CGFloat,_ alignment: SimplifyAlignment ) -> WrapConstraintMaker {
return addMakeProcess(ardView){ m,v in m.centerY.equalTo( self.vRelateTarget(v,alignment) ).offset(offset) }
}
@discardableResult
func centerY( _ offset: CGFloat = 0 ,_ ardView:UIView? = nil ) -> WrapConstraintMaker {
return centerYConstraint(ardView,offset,SimplifyAlignment.middle)
}
@discardableResult
func centerYToParent( _ offset: CGFloat = 0) -> WrapConstraintMaker {
return addMakeProcessImmediately{ $0.centerY.equalToSuperview().offset(offset) }
}
@discardableResult
static func -- (left: WrapConstraintMaker, right: (UIView?,CGFloat)) -> WrapConstraintMaker {
return left.centerYConstraint( right.0,right.1,SimplifyAlignment.middle )
}
@discardableResult
static func -- (left: WrapConstraintMaker, right:CGFloat ) -> WrapConstraintMaker { return left -- (nil ,right) }
@discardableResult
func centerYToTop( _ offset: CGFloat = 0 ,_ ardView:UIView? = nil ) -> WrapConstraintMaker {
return centerYConstraint(ardView,offset,SimplifyAlignment.begin)
}
@discardableResult
static func -^ (left: WrapConstraintMaker, right: (UIView?,CGFloat)) -> WrapConstraintMaker {
return left.centerYConstraint( right.0,right.1,SimplifyAlignment.middle )
}
@discardableResult
static func -^ (left: WrapConstraintMaker, right:CGFloat ) -> WrapConstraintMaker { return left -^ (nil ,right) }
@discardableResult
func centerYToBottom( _ offset: CGFloat = 0 ,_ ardView:UIView? = nil ) -> WrapConstraintMaker {
return centerYConstraint(ardView,offset,SimplifyAlignment.end)
}
@discardableResult
static func -~ (left: WrapConstraintMaker, right: (UIView?,CGFloat)) -> WrapConstraintMaker {
return left.centerYConstraint( right.0,right.1,SimplifyAlignment.end )
}
@discardableResult
static func -~ (left: WrapConstraintMaker, right:CGFloat ) -> WrapConstraintMaker { return left -~ (nil ,right) }
//MARK: ------------- 居中 ------------------
@discardableResult
func center( _ ardView: UIView? = nil ) -> WrapConstraintMaker {
return addMakeProcess(ardView){ m,v in m.center.equalTo( v.snp.center ) }
}
func centerParent() -> WrapConstraintMaker {
return addMakeProcessImmediately{ $0.center.equalToSuperview() }
}
@discardableResult
static func >><< (left: WrapConstraintMaker, right: UIView? ) -> WrapConstraintMaker {
return left.center(right)
}
@discardableResult
func edges(_ inset:(CGFloat,CGFloat,CGFloat,CGFloat)? = nil, _ ardView: UIView? = nil ) -> WrapConstraintMaker {
return addMakeProcess(ardView){ $0.edges.equalTo( $1.snp.edges ).inset(UIEdgeInsetsMake(inset?.1 ?? 0, inset?.0 ?? 0, inset?.3 ?? 0, inset?.2 ?? 0)) }
}
@discardableResult
func edgesParents(_ left:CGFloat = 0,_ top:CGFloat = 0,_ right:CGFloat = 0,_ bottom:CGFloat = 0) -> WrapConstraintMaker {
return addMakeProcessImmediately{ $0.edges.equalToSuperview().inset(UIEdgeInsetsMake(top, left, bottom, right )) }
}
@discardableResult
static func <<>> (left: WrapConstraintMaker, right: (CGFloat,CGFloat,CGFloat,CGFloat)? ) -> WrapConstraintMaker {
return left.edges(right)
}
//MARK: ------------- 尺寸 ------------------
private func width( _ rate:CGFloat = 1 , _ ardView: UIView? = nil , _ isRate:Bool = false , _ isParent:Bool = false ) -> WrapConstraintMaker {
return addMakeProcess(ardView){ m,v in
let maker = isParent ? m.width.equalToSuperview() : m.width.equalTo( v.snp.width )
let _ = isRate ? maker.multipliedBy(rate) : maker.offset(rate)
}
}
@discardableResult
func widthByRate( _ rate:CGFloat = 1 , _ ardView: UIView? = nil ) -> WrapConstraintMaker {
return width(rate,ardView,true,false)
}
@discardableResult
func widthByOffset( _ rate:CGFloat = 1 , _ ardView: UIView? = nil ) -> WrapConstraintMaker {
return width(rate,ardView,false,false)
}
@discardableResult
func width( _ size:CGFloat) -> WrapConstraintMaker {
allMakers.append{
$0.width.equalTo(size)
}
return self
}
@discardableResult
func widthToParentByRate( _ rate:CGFloat = 1) -> WrapConstraintMaker {
return width(rate,nil,true,true)
}
@discardableResult
func widthToParent( _ rate:CGFloat = 1) -> WrapConstraintMaker {
return addMakeProcessImmediately {
$0.width.equalToSuperview().multipliedBy(rate)
}
}
private func height( _ rate:CGFloat = 1 , _ ardView: UIView? = nil , _ isRate:Bool = false , _ isParent:Bool = false ) -> WrapConstraintMaker {
return addMakeProcess(ardView){ m,v in
let maker = isParent ? m.height.equalToSuperview() : m.height.equalTo( v.snp.height )
let _ = isRate ? maker.multipliedBy(rate) : maker.offset(rate)
}
}
@discardableResult
func heightByRate( _ rate:CGFloat = 1 , _ ardView: UIView? = nil ) -> WrapConstraintMaker {
return height(rate,ardView,true,false)
}
@discardableResult
func heightByOffset( _ rate:CGFloat = 0 , _ ardView: UIView? = nil ) -> WrapConstraintMaker {
return height(rate,ardView,false,false)
}
@discardableResult
func height( _ size:CGFloat) -> WrapConstraintMaker {
allMakers.append{
$0.height.equalTo(size)
}
return self
}
@discardableResult
func heightToParent( _ rate:CGFloat = 0) -> WrapConstraintMaker {
return addMakeProcessImmediately {
$0.height.equalToSuperview().multipliedBy(rate)
}
}
//MARK: ------------- 等边 ------------------
@discardableResult
func equilateral(_ size:CGFloat) -> WrapConstraintMaker {
return addMakeProcessImmediately {
$0.width.equalTo(size)
$0.height.equalTo(size)
}
}
@discardableResult
func equilateralToParent(_ hRate:CGFloat = 1 ,_ vRate:CGFloat = 1) -> WrapConstraintMaker {
return addMakeProcessImmediately {
$0.width.equalToSuperview().multipliedBy(hRate)
$0.height.equalToSuperview().multipliedBy(vRate)
}
}
func horizontalToParent(_ leftMargin:CGFloat = 0 ,_ rightMargin:CGFloat = 0) -> WrapConstraintMaker {
return addMakeProcessImmediately {
$0.left.equalToSuperview().offset(leftMargin)
$0.right.equalToSuperview().offset(rightMargin)
}
}
func verticalToParent(_ topMargin:CGFloat = 0 ,_ bottomMargin:CGFloat = 0) -> WrapConstraintMaker {
return addMakeProcessImmediately {
$0.top.equalToSuperview().offset(topMargin)
$0.bottom.equalToSuperview().offset(bottomMargin)
}
}
//MARK: ------------- 自定义 ------------------
@discardableResult
func custom(_ maker:@escaping (ConstraintMaker)-> Void) -> WrapConstraintMaker {
allMakers.append(maker)
return self
}
//MARK: ------------- 从新设置 ------------------
func reSet(){
( mineView ?? self.cacheView )?.snp.remakeConstraints{ buildMakes($0) }
}
func update(){
( mineView ?? self.cacheView )?.snp.updateConstraints{ buildMakes($0) }
}
//支持多个下标修改 不支持 忽略 (因为view没有缓存 防止内存泄露)
subscript(_ indexs: Int... ) -> (WrapConstraintMaker)-> Void {
get{ return {_ in } }
set{
stashMakers = [( (ConstraintMaker)-> Void )]()
newValue(self)
let allMakeRange = Range(0..<allMakers.count)
indexs.forEach{ index in
if stashMakers!.count > 0 && allMakeRange.contains(index) {
allMakers[index] = stashMakers!.remove(at: 0)
}
}
stashMakers?.removeAll()
stashMakers = nil
reSet()
}
}
}
网友评论