SnapKit is a tool allowing iOS developers to manipulate auto-layout constraints easily. By using SnapKit, you can create, update, remove and manage layout constraints of the UI views.
snp.makeConstraint
method is used to add constraints, including: margin, width, height, left and right distance. SnapKit also supports deletion constraints, update constraints, and relative position (inset, offset) and multiple correction (multipleBy and divideBy).
SnapKit supports the following properties:
ViewAttribute | Layout Attribute |
---|---|
view.snp.left | NSLayoutAttribute.Left |
view.snp.right | NSLayoutAttribute.Right |
view.snp.top | NSLayoutAttribute.Top |
view.snp.bottom | NSLayoutAttribute.Bottom |
view.snp.leading | NSLayoutAttribute.Leading |
view.snp.trailing | NSLayoutAttribute.Trailing |
view.snp.width | NSLayoutAttribute.Width |
view.snp.height | NSLayoutAttribute.Height |
view.snp.centerX | NSLayoutAttribute.CenterX |
view.snp.centerY | NSLayoutAttribute.CenterY |
view.snp.baseline | NSLayoutAttribute.Baseline |
Without SnapKit, the code would look similar to the following:
child.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ child.leadingAnchor.constraint(equalTo: parent.leadingAnchor), child.topAnchor.constraint(equalTo: parent.topAnchor), child.trailingAnchor.constraint(equalTo: parent.trailingAnchor), child.bottomAnchor.constraint(equalTo: parent.bottomAnchor), ])
SnapKit represents those constraints like this:
child.snp.makeConstraints { make in make.leading.equalToSuperview() make.top.equalToSuperview() make.trailing.equalToSuperview() make.bottom.equalToSuperview() }
First of all, you need to install SnapKit via CocoaPods. Add this to your Podfile:
pod 'SnapKit'
Let’s display a UIView
pinned to the four edges of its superview.
import UIKit import SnapKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let child = UIView() child.backgroundColor = .red let child1 = UIView() child1.backgroundColor = .green self.view.addSubview(child) self.view.addSubview(child1) child.snp.makeConstraints { (make) in make.edges.equalTo(self.view) } child1.snp.makeConstraints { (make) in make.size.equalTo(CGSize(width: 300, height: 300)) make.top.equalTo(self.view.snp.top).offset(100) make.centerX.equalTo(self.view) } } }
Let’s try sme other things in SnapKit:
child.snp.makeConstraints { (make) in make.size.equalTo(CGSize(width: 300, height: 300)) make.top.equalTo(self.view.snp.top).offset(100) make.centerX.equalTo(self.view) } child2.snp.makeConstraints { (make) in make.size.equalTo(child) make.top.equalTo(child.snp.bottom).offset(50) make.centerX.equalTo(self.view) } child3.snp.makeConstraints { (make) -> Void in make.top.left.right.equalTo(0) make.height.equalTo(self.view.snp_height).multipliedBy(0.5) } child4.snp.makeConstraints { (make) -> Void in make.center.equalTo(topView.center) make.width.equalTo(100) make.height.equalTo(110) } child5.snp.makeConstraints { make in make.edges.equalToSuperview().inset(16) //make.edges.equalTo(child2).inset(UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)) } child6.snp.makeConstraints { make in make.leading.trailing.equalTo(view.safeAreaLayoutGuide) } child7.snp.makeConstraints { make in make.leading.trailing.equalTo(child6) make.top.equalTo(child6.snp.bottom).offset(16) make.height.equalTo(80) }
Aspect ratio
view.snp.makeConstraints { make in make.width.equalTo(view.snp.height).multipliedBy(1.0 / 1.0) }
UITableView example
import UIKit import SnapKit class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { lazy var tbl: UITableView = { let v = UITableView() v.rowHeight = 100 v.separatorStyle = .none return v }() var items: [String] = [] override func viewDidLoad() { super.viewDidLoad() items.append(contentsOf: (1...20).map { index in "Item \(index)"}) setupUI() } func setupUI() { tbl.delegate = self tbl.dataSource = self tbl.register(CustomCell.self, forCellReuseIdentifier: CustomCell.cellId) self.view.addSubview(tbl) tbl.snp.makeConstraints { (make) in make.edges.equalTo(self.view.safeAreaLayoutGuide) } } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return items.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: CustomCell.cellId, for: indexPath) as! CustomCell cell.lblTitle.text = items[indexPath.row] return cell } } class CustomCell: UITableViewCell { static var cellId = "cell" let lblTitle: UILabel = { let v = UILabel() v.backgroundColor = .systemGreen v.textColor = .white v.textAlignment = .center v.layer.cornerRadius = 5 v.layer.masksToBounds = true return v }() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) setupUI() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func setupUI() { self.addSubview(lblTitle) lblTitle.snp.makeConstraints { (make) in make.top.left.equalTo(20) make.right.bottom.equalTo(-20) } } }