+3

Hướng dẫn sử dụng IBDesignable và IBInspectable với Swift 3

1. Bài toán Khi lập trình một ứng dụng, có thể có lúc bạn gặp phải bài toán như sau: Bạn có một UIView chứa rất nhiều các subView, mỗi subView có thể là UIView, UIButton, UILabel, ... Yêu cầu đặt ra là mỗi subView đều được bo tròn góc. Như trong hình vẽ, yêu cầu bài toán là bo tròn 5 hình chữ nhật (mình tạm lấy ví dụ là 5 UIView)

2. Giải quyết vấn đề Để giải quyết bài toán trên thì có rất nhiều cách khác nhau.

Đơn giản nhất để bo tròn 5 UIView này, đó là bạn đặt ra 5 IBOutlet, sau đó bạn thực hiện bo tròn bằng CALayer.cornerRadius

@IBOutlet weak var view1: UIView!
@IBOutlet weak var view2: UIView!
@IBOutlet weak var view3: UIView!
@IBOutlet weak var view4: UIView!
@IBOutlet weak var view5: UIView!

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        view1.layer.cornerRadius = 5.0
        view2.layer.cornerRadius = 5.0
        view3.layer.cornerRadius = 5.0
        view4.layer.cornerRadius = 5.0
        view5.layer.cornerRadius = 5.0
}

Khi đó, các bạn sẽ được kết quả như sau

Nếu các bạn có 20 UIView cần bo tròn như vậy thì sao ???

Lúc này các bạn sẽ nghĩ ngay tới sử dụng IBCollectionView

@IBOutlet var views: [UIView]!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
        
    for v in views {
        v.layer.cornerRadius = 5.0
    }
}

Source code của chúng ta đã ngắn gọn hơn rất nhiều và vẫn đem lại kết quả mong muốn. Nhưng, chuyện gì sẽ xảy ra nếu 5 UIView này không cùng bo góc 5.0 pixels.

Và có thể bạn sẽ suy nghĩ là chuyển về dùng cách 1

Có thể mọi chuyện sẽ diễn ra như vậy đến trước thời điểm mà Xcode 6 ra đời. Với Xcode 6 (or newer), bạn có thể dễ dàng giải quyết vấn đề bằng IBDesignable và IBInspectable

Đầu tiên, để sử dụng IBDesignable và IBInspectable, bạn cần subclass lại UIView

import UIKit

@IBDesignable
class CustomView: UIView {
    private var _cornerRadius: CGFloat = 0.0
    
    var cornerRadius: CGFloat {
        set (newValue) {
            _cornerRadius = newValue
            layer.cornerRadius = _cornerRadius
        } get {
            return _cornerRadius
        }
    }
}

Sau khi viết đoạn code CustomView như trên, các bạn đổi lại custom class trong xcode và xoá đoạn code set cornerRadius ở cách bên trên đi, các bạn sẽ được kết quả như sau

Như hình vẽ trên, mình đang sử dụng User Defined Runtime Attributes để set cornerRadius cho mỗi UIView. Và với từ khoá @IBDesignable ở đầu class CustomView, Xcode đã render màn hình design của bạn trực tiếp với runtime attributes, các bạn có thể thấy kết quả bo tròn góc trên Interface Builder Như vậy, với yêu cầu bài toán là 20 UIView với các góc bo tròn khác nhau thì đã không còn là vấn đề gây khó dễ nữa.

Bây giờ, vấn đề tiếp theo đó là, các bạn đóng gói module để sử dụng nhiều nơi, và các bạn đã quên mất Runtime Attributes tên là gì. Xcode đã đưa vào @IBInspectable để giải quyết vấn đề.

import UIKit

@IBDesignable
class CustomView: UIView {
       private var _cornerRadius: CGFloat = 0.0
    
       @IBInspectable
       var cornerRadius: CGFloat {
           set (newValue) {
               _cornerRadius = newValue
               layer.cornerRadius = _cornerRadius
            } get {
                return _cornerRadius
            }
       }
}

Khi đó màn hình Interface Builder sẽ có thêm thuộc tính để bạn nhập giá trị corner radius

3. Kết luận Như vậy, với @IBDesignable@IBInspectable, các bạn có thể giải quyết được rất nhiều bài toán về UI mà không phải tốn nhiều thời gian code mà vẫn đạt được kết quả mong muốn. @IBDesignable@IBInspectable không phải là điều mới với nhiều người, nhưng hy vọng bài viết này sẽ giúp ích được cho các bạn mới bước vào nghề lập trình iOS. Happy coding !


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí