Lời nói đầu
Lúc mới bắt đầu học lập trình iOS, tôi đã học theo những tutorial trên Youtube. Để tạo một đối tượng UI, tôi gõ y nguyên theo những dòng code sau:
let makeBox: UIView = {
let view = UIView()
return view
}()
Ở vị trí của một người đang đi học, thì tôi chỉ copy và sử dụng chúng. Tuy nhiên, một ngày có người hỏi tôi rằng, "Tại sao lại phải thêm hai dấu ngoặc {} và tại sao lại có () ở cuối, đó có phải là một computed property không?. Tôi không thể trả lời. Do vậy, tôi viết bài này để giảng lại cho chính tôi ngày trước.
Để nắm được toàn bộ bài viết này, các bạn cần phải nắm và hiểu rõ những khái niệm sau:
- Closures
- Object Oriented Programming
Tạo UI Components
Trước khi tôi giải thích về phương pháp mới, hãy cùng nhau nhìn vào phương pháp phổ biến mà chúng ta thường dùng. Để tạo một button trong Swift, thường thì chúng ta sẽ làm như sau:
// Determine Size
let buttonSize = CGRect(x: 0, y: 0, width: 100, height: 100)
// Create Instance
let bobButton = UIButton(frame: buttonSize)
bobButton.backgroundColor = .black
bobButton.titleLabel?.text = "Bob"
bobButton.titleLabel?.textColor = .white
Giả dụ bạn cần phải tạo 3 button nữa, bạn sẽ phải copy đoạn code trên và thay đổi tên của chúng.
// New Button
let bobbyButton = UIButton(frame: buttonSize)
bobbyButton.backgroundColor = .black
bobbyButton.titleLabel?.text = "Bob"
bobbyButton.titleLabel?.textColor = .white
Để tiện hơn thì bạn có thể làm như sau với tổ hợp phím Cmd + Ctrl + E
Hoặc bạn cũng có thể tạo một function để đỡ lặp đi lặp lại một công việc
func createButton(enterTitle: String) -> UIButton {
let button = UIButton(frame: buttonSize)
button.backgroundColor = .black
button.titleLabel?.text = enterTitle
return button
}
createButton(enterTitle: "Yoyo") // 👍
Tuy nhiên, trong lập trình iOs, hiếm có trường hợp nào mà các button trông giống hệt nhau. Chính vì thế, function cần phải có thêm nhiều parameter khác như background color, title, border radius, shadow..:
func createButton(title: String, borderWidth: Double, backgrounColor, ...) -> Button
Việc thêm nhiều parameter vào function sẽ khiến nó trở nên khó đọc và khó hiểu hơn. Chúng ta đều muốn một function càng gọn gàng càng tốt.
Init đối tượng với closure
Trước khi đi vào phương pháp mới, chúng ta hãy trả lời câu hỏi ở đầu bài viết, dấu {} nghĩa là gì, và nó có phải là một Computer Property không? Không !, đó chỉ đơn giản là một closure block.
Đầu tiên chúng ta hãy khởi tạo một struct có tên là Human
struct Human {
init() {
print("Born 1996")
}
}
Sau đó chúng ta tạo một đối tượng bằng closure
let createBob = { () -> Human in
let human = Human()
return human
}
let babyBob = createBob() // "Born 1996"
createBob là một closure với kiểu trả về là () -> Human. Sau đó chúng ta gọi clousre createBob() để tạo một instance của Human
Tuy nhiên, bạn phải tạo 2 constants: createBob và babyBob. Và nếu bạn muốn làm mọi thứ trong một câu lệnh thì sao?
let bobby = { () -> Human in
let human = Human()
return human
}()
Bây giờ closure block sẽ thực thi bằng cách thêm () vào và bobby bây giờ đã là một đối tượng Human.Tiếp theo hãy cùng áp dụng vào việc tạo một UI object:
let bobView = { () -> UIView in
let view = UIView()
view.backgroundColor = .black
return view
}()
Tuyệt, chúng ta đã làm nó trở nên ngắn gọn hơn. Thực tế, chúng ta không cần phải chỉ ra rõ kiểu của closure block. Thay vào đó, chúng ta chỉ cần chỉ rõ kiểu của instance:
let bobbyView: UIView = {
let view = UIView()
view.backgroundColor = .black
return view
}()
Lợi ích của việc init bằng closure
Dễ dàng sao chép
Tôi không thích sử dụng Storyboard, tôi thích việc copy và paset những UI object. Thực tế, tôi có một thư viện code ở trong máy tính của mình. Giả dụ có một button như sau:
let myButton: UIButton = {
let button = UIButton(frame: buttonSize)
button.backgroundColor = .black
button.titleLabel?.text = "Button"
button.titleLabel?.textColor = .white
button.layer.cornerRadius = 1
button.layer.masksToBounds = true
return button
}()
Tất cả nhưng gì tôi cần làm là copy những dòng code trên, và thay tên từ myButton thành newButton để sử dụng. Nếu tôi không dùng cách này, tôi sẽ phải thay đổi tên button 7,8 lần.
Nhìn code gọn gàng hơn
Nhóm các đối tượng lại với nhau sẽ khiến code trở nên gọn gàng hơn:
// Init with Closure
let leftCornerButton: UIButton = {
let button = UIButton(frame: buttonSize)
button.backgroundColor = .black
button.titleLabel?.text = "Button"
button.titleLabel?.textColor = .white
button.layer.cornerRadius = 1
button.layer.masksToBounds = true
return button
}()
let rightCornerButton: UIButton = {
let button = UIButton(frame: buttonSize)
button.backgroundColor = .black
button.titleLabel?.text = "Button"
button.titleLabel?.textColor = .white
button.layer.cornerRadius = 1
button.layer.masksToBounds = true
return button
}()
vs
// Init With Fingers
let leftCornerButton = UIButton(frame: buttonSize)
leftCornerButton.backgroundColor = .black
leftCornerButton.titleLabel?.text = "Button"
leftCornerButton.titleLabel?.textColor = .white
leftCornerButton.layer.cornerRadius = 1
leftCornerButton.layer.masksToBounds = true
let rightCornerButton = UIButton(frame: buttonSize)
rightCornerButton.backgroundColor = .black
rightCornerButton.titleLabel?.text = "Button"
rightCornerButton.titleLabel?.textColor = .white
rightCornerButton.layer.cornerRadius = 1
rightCornerButton.layer.masksToBounds = true
Mặc dù tạo một object với closure sẽ thêm một vài dòng code nữa, nhưng nhìn chung code sẽ dễ quản lý hơn khi chúng ta chỉ phải thêm các attributes vào button, thay vì rightCornerButotn hay leftCornerButton.
Khóa học lập trình di động tại Techmaster:
Để cài đặt MacOSX lên phần cứng không phải Apple liên hệ chuyên gia cài Hackintosh:
- Nguyễn Minh Sơn: 01287065634
- Huỳnh Minh Sơn: 0936225565
- Website: caidatmacos.com
Bình luận