欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

为UILabel创建链式调用写法

程序员文章站 2022-06-08 16:31:55
...

0x00 背景:

开发的时候现在用到的最多的AutoLayout第三方框架就是Masonry(Swift为SnapKit)了,里面有一种非常舒服的调用方法用流行的 话来讲就是链式调用方法,是把一块组合调用方法使用.连接的方式写出来,使得编码方式更直观,更容易理解。下面我们看一下如何在UILabel中使用这种技巧。


0x01 问题

首先,假设我们有一个view,我们需要它在距他的parentView左边15sp,右边30sp,上边20sp,下边20sp,看一下使用SnapKit如何来实现这个布局的

let view = UIView()
        view.backgroundColor = UIColor.red
        self.view.addSubview(view);
        
        view.snp.makeConstraints { (make) in
            make.left.equalTo(20)
            make.right.equalTo(self.view).offset(-20)
            make.top.equalTo(20)
            make.bottom.equalTo(self.view).offset(-20)
        }
其中,描述当前view距parentView的下边距为20sp,就是make.bottom.equealTo(self.view).offset(-20),从字面意思很容易就能看出所表达的内容。

  • 给定一个UILabel,设置字体为系统12号,颜色为Red,背景色为Yellow,text为"One coin has two sides"

通常我们会这么写:

let label = UILabel()
label.font = UIFont.systemFont(ofSize: 12)
label.textColor = UIColor.red
label.backgroundColor = UIColor.yellow
label.text = "One coin has two sides"

那么我们考虑一下,是不是能和SnapKit一样用链式调用来达到同样的效果呢?

let label = UILabel()
label.font(UIFont.systemFont(ofSize: 12)).textColor(UIColor.red).backgroundColor(UIColor.yellow).text("One coin has two sides")

0x02 过程

我们来看一下上述的这句话:

make.bottom.equalTo(self.view).offset(-20)

我们查看一下里面bottom的源码:

    public var bottom: ConstraintMakerExtendable {
        return self.makeExtendableWithAttributes(.bottom)
    }

返回的是 “ConstraintMakerExtendable”对象,我们再点击这个这个查看源码:

public class ConstraintMakerExtendable: ConstraintMakerRelatable {
    
    public var left: ConstraintMakerExtendable {
        self.description.attributes += .left
        return self
    }
    
    public var top: ConstraintMakerExtendable {
        self.description.attributes += .top
        return self
    }
    
    public var bottom: ConstraintMakerExtendable {
        self.description.attributes += .bottom
        return self
    }
...

看出来什么来了吗?它们每个在自身内部计算完之后,最终返回的还是自己,即“ConstraintMakerExtendable”对象,所以“ConstraintMakerExtendable”对象才可以不断的再调用自身其它的属性。

那么基于此,我们也可以为UILabel构造这么一些方法(我们和上述有一点点不同,所以不能以属性的方式来处理,因为需要传入的的值和返回的值并不一致),并返回UILabel自己来达到这样的效果。

0x03 实现

新起一个Swift Playground

新那家一个UILabel的extension,实现我们需要的4个方法,如下:

extension UILabel {
    func sn_font(_ font: UIFont?) -> UILabel {
        self.font = font
        return self
    }
    
    func sn_textColor(_ color: UIColor?) -> UILabel {
        self.textColor = color
        return self
    }
    
    func sn_backgroundColor(_ backgroundColor: UIColor?) -> UILabel {
        self.backgroundColor = backgroundColor
        return self
    }
    
    func sn_text(_ text: String?) -> UILabel {
        self.text = text
        return self
    }
}

我们每次接收传过来的值,并在本身使用之后,再返回自身self,因为返回的还是UILabel对象,所以可以继续调用其他的方法。

下面我们写一段代码测试一下:

let label = UILabel()
label.sn_font(UIFont.systemFont(ofSize: 12)).sn_textColor(.red).sn_backgroundColor(.yellow).sn_text("One coin has two sides")
label.sizeToFit()
let view = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
view.addSubview(label)
PlaygroundPage.current.liveView = view

效果如图:

为UILabel创建链式调用写法

0x04 总结

通过类似的写法,我们还可以把layer用到的一些方法比如说cornerRadius,borderWdith, borderColor等写成上述extension里面的方法,以一种更直观的方式来描述你想达到的界面效果。