iOS/Auto Layout – Phần 4: Làm sao để viết constraint dễ dàng hơn? Giới thiệu Snapkit

by DaoNM2
1.6K views

Lời mở đầu

Ở phần 3 chúng ta đã được làm quen với việc tạo constraints bằng code. Vậy nên bài viết này mình sẽ chia sẻ với các bạn về việc làm sao để tạo constraints bằng code dễ dàng hơn, tiết kiệm thời gian hơn. Và làm thế nào để debug UI.



Sử dụng extension

Việc sử dụng extension để mở rộng các class giúp chúng ta có thể tạo constraint dễ dàng và tiết kiệm nhiều thời gian. Việc của các bạn là nghĩ và tạo ra các func có thể hay được sử dụng.

1. UIView

Ví dụ chung ta có thể tạo ra một func trong extension UIView giúp chúng ta tạo các constraints liên kết với SuperView như sau:

extension UIView {

    /// Returns a collection of constraints to anchor the bounds of the current view to the given view.
    ///
    /// - Parameter view: The view to anchor to.
    /// - Returns: The layout constraints needed for this constraint.
    func constraintsForAnchoringTo(boundsOf view: UIView) -> [NSLayoutConstraint] {
        return [
            topAnchor.constraint(equalTo: view.topAnchor),
            leadingAnchor.constraint(equalTo: view.leadingAnchor),
            view.bottomAnchor.constraint(equalTo: bottomAnchor),
            view.trailingAnchor.constraint(equalTo: trailingAnchor)
        ]
    }
}

Từ đây các bạn có thể tha hồ nghĩ thêm các func để giúp cho việc tạo constraints của mình trở nên đơn giản và tiết kiệm thời gian hơn nhiều so với việc hì hục ngồi code.

1.2 Xử lí ưu tiên

Khi bạn phải đặt độ ưu tiên cho các constraints của mình để tránh phá vỡ các constraint khác. Bạn có thể sẽ cần đến extension này:

extension NSLayoutConstraint {
    
    /// Returns the constraint sender with the passed priority.
    ///
    /// - Parameter priority: The priority to be set.
    /// - Returns: The sended constraint adjusted with the new priority.
    func usingPriority(_ priority: UILayoutPriority) -> NSLayoutConstraint {
        self.priority = priority
        return self
    }
    
}

extension UILayoutPriority {
    
    /// Creates a priority which is almost required, but not 100%.
    static var almostRequired: UILayoutPriority {
        return UILayoutPriority(rawValue: 999)
    }
    
    /// Creates a priority which is not required at all.
    static var notRequired: UILayoutPriority {
        return UILayoutPriority(rawValue: 0)
    }
}

Độ ưu tiên của constraint là phần khá là hay ho, nên mình sẽ dành một mục ở bài viết tiếp theo.

1.3 Tạo Auto layout property wrapper

Khi auto layout bằng code, để tránh việc phải viết đi viết lại nhiều lần dòng code dưới đây:
translatesAutoresizingMaskIntoConstraints = false

Chúng ta sẽ tạo ra Property Wrapper như dưới đây:

@propertyWrapper
public struct UsesAutoLayout<T: UIView> {
    public var wrappedValue: T {
        didSet {
            wrappedValue.translatesAutoresizingMaskIntoConstraints = false
        }
    }

    public init(wrappedValue: T) {
        self.wrappedValue = wrappedValue
        wrappedValue.translatesAutoresizingMaskIntoConstraints = false
    }
}

final class MyViewController {
    @UsesAutoLayout
    var label = UILabel()
}

Lưu ý: Nó không sử dụng được cho biến Local

Giới thiệu về Snapkit

Nếu như các bạn lười nghĩ và viết các extension để hỗ trợ cho việc tạo constraint bằng code. Thì chúng ta lại có một giải pháp khác là dùng của thằng khác :D. Của ăn sẵn nhiều khi cũng tốt mà. Tiện đây mình xin giới thiệu với các bạn về thư viện Snapkit một thư việt rất mạnh về Auto layout bằng code. Giúp chúng ta xử lí Autolayout một cách đơn giản, gọn gàng và tiết kiệm khá nhiều thời gian.

Ưu điểm
– Code nhìn gọn gàng, dễ hiểu hơn
– Tiết kiệm thời gian khi code

Nhược điểm
– Sẽ có những thành viên không sử dụng snapkit mà dùng API default của apple dẫn đến thời gian đầu làm việc gặp khó khăn.

Cài đặt

CocoaPods, Carthage hoặc ném nó vào project của bạn.
Tham khảo link này nhé.

Cách sử dụng

1.Tạo constraint

func makeConstraintBySnapkit1() {
        let iView = UIView()
        let oView = UIView()
        iView.backgroundColor = .red
        oView.backgroundColor = .blue

        view.addSubview(oView)
        oView.addSubview(iView)

        oView.snp.makeConstraints { (make) in
            make.width.height.equalTo(200)
            make.center.equalToSuperview()
        }
        iView.snp.makeConstraints { (make) in
            make.top.leading.equalToSuperview().offset(20)
            make.bottom.trailing.equalToSuperview().offset(-20)
        }
    }

Để tạo được constraint có kết quả như hình này bằng code sử dụng API mặc định của apple chúng ta sẽ phải viết khá nhiều dòng code.

2. Giữ reference của constraint và thay đổi nó giá trị của nó khi cần.

var myConstraint: Constraint?
iView.snp.makeConstraints { (make) in
            self.myConstraint = make.top.leading.equalToSuperview().offset(20).constraint
            make.bottom.trailing.equalToSuperview().offset(-20)
        }
myConstraint?.update(offset: 40)

3. Update constraint

Update constraint giúp chúng ta update tùy ý bất kể 1 constraint nào đó của View.
Để update constraint ta chỉ cần viết như sau:

iView.snp.updateConstraints { (edit) in
    edit.top.leading.equalToSuperview().offset(0)
}

Kết quả thu được sẽ là:

4. Remake constraint

Khác với updateContraint, remake constraint sẽ remove toàn bộ constraints cũ đi và bạn sẽ tạo lại constraint từ đầu như hàm makeConstraint.
Câu lênh của nó sẽ như sau:

        iView.snp.remakeConstraints { (remake) in
            remake.top.leading.equalToSuperview().offset(20)
            remake.bottom.trailing.equalToSuperview()
        }

Kết quả thu được

Để có thể thành thạo sử dụng Auto Layout và Snapkit chúng ta chỉ có 1 cách đó là làm nhiều, nhiều nữa và nhiều mãi thế thôi =)) Cố gắng lên anh em :))

Tổng kết

Mình hi vọng bài viết này sẽ giúp các bạn phần nào sử dụng Auto Layout dễ dàng và tiết kiệm thời gian hơn.



Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.