Giới thiệu về delegate trong swift 3
Delegate thực sự là một chủ đề khó , trong phạm vi bài viết này mình sẽ đưa cho các bạn một cái nhìn tổng quan về delegate trong swift , nó là gì và hoạt động như thế nào.
Delegate, em là ai giữa cuộc đời này?
Delegate trong các docs viết rất dài dòng và vĩ mô, vì delegate trong Delegation Pattern là cả một Pattern mà
Nhưng trước mắt, bạn đừng để ý đến nó, vì cái mình nói dưới đây, là cái cơ bản nhất khi vận dụng delegate vào trong application iOS của các bạn rồi, thế nên các cái vĩ mô kia, các bạn tìm hiểu sau nhé.
Delegate trong Objective-C là một pattern để đối tượng A ủy nhiệm đối tượng B làm hộ việc gì thông qua protocol mà đối tượng B phải tuân thủ (adopt protocol).
Looking for a web developer ?
Mình đưa ra trường hợp giả sử là , có một chủ của một cửa hàng điện thoại và ổng cần có một developer để xây dựng một cái Web để bán hàng cho ổng
Vì vậy ổng quyết định tìm một web developer. Mà để là Web Developer thì phải có khả năng làm web chứ đúng không?
Đầu tiên mình tạo ra kỹ năng làm web trước:
// Khả năng làm website
protocol WebDeveloper{
func makeWebsite\(\)
}
Kế đến mình phác hoạ người có khả năng làm web:
//Một kỹ sư có khả năng làm web
struct Engineer : WebDeveloper {
func makeWebsite(){
print(“making your website”)
}
}
// Ông chủ
struct Boss {
var delegate: WebDeveloper?
func haveDeveloperBuildMyWebsite(){
delegate?.makeWebsite()
}
}
Mình đã tạo ra đối tượng ông chủ , và yêu cầu của ổng là cần 1 thằng dev để làm cái web vì vậy mình tạo 1 cái delegate , bạn tưởng tượng nó giống như một thằng dev mà ổng đang cần vậy.
Ở đây biến delegate có kiểu là WebDeveloper có nghĩa là bất kì thằng nào có thể lập trình web ( type WebDeveloper ) thì đều có thể làm delegate cho ổng
Còn hàm haveDeveloperBuildMyWebsite tượng trưng cho yêu cầu của ổng là muốn làm cái web
Tạo xong 2 mô hình ông chủ và thằng dev rồi thì bây giờ ta tạo ra 2 thằng đó bằng xương bằng thịt như sau :
var engineer = Engineer()
var boss = Boss()
boss.delegate = engineer
boss.haveDeveloperBuildMyWebsite() // making your website
Dòng boss.delegate = engineer
có nghĩa là gán biến engineer vào delegate. Bạn tưởng tượng ông chủ đó cần thằng WebDeveloper mà thằng engineer này cũng là WebDeveloper thì gán vào giống như thuê thằng đó làm cho ổng
Sau khi có được thằng đó rồi thì ổng có thể thực hiện yêu cầu làm web của ổng :
“boss.haveDeveloperBuildMyWebsite()
“
Để dễ nhớ các bạn xem delegate giống như 1 Người Đại Diện vậy, trong bài này delegate là người đại diện mà có khả năng làm web, khi mình cần một người biết làm web mình tạo ra delegate với khả năng làm web, đối tượng nào có thể làm web mình sẽ gán nó vào delegate này để nó thực hiện yêu cầu của mình
Trong Delegate Pattern sẽ có 3 cái key chính mà mình muốn các bạn lưu ý :
Protocol : trong đây sẽ định nghĩa những gì mà Worker có thể làm
Boss Class : trong class này sẽ có 1 biến delegate , sử dụng để cho Worker Class biết phải làm những gì
Worker Class : sẽ dùng những khả năng mà protocol đã định nghĩa để thực hiện những yêu cầu của Boss Class
In Real Life
Vậy delegate được ứng dụng trong quá trình làm app như thế nào? Mình sẽ đưa ra một ví dụ nhỏ về sử dụng delegate.
Delegate thường được sử dụng trong lập trình ứng dụng để giải bài toán truyền dữ liệu giữa các màn hình với nhau (ngoài ra ta có thể dùng NSUserDefault, Signleton classes, Notification ..)
Tôi lấy ví dụ :
Mình sẽ có 2 màn hình , firstView và secondView , màn hình 1 sẽ có 1 label và 1 button, màn hình 2 sẽ có 1 textField và 1 button
Nhiệm vụ là nhập text vào textField sau đó nhấn button , sẽ chuyển sang màn hình 1 và label đó sẽ hiện đoạn text đã nhập bên khung textField của màn hình 2
//Code của màn hình 2
import UIKit
// protocol used for sending data back
protocol DataEnteredDelegate: class {
func userDidEnterInformation(info: String)
}
class SecondViewController: UIViewController {
// making this a weak variable so that it won't create a strong reference cycle
weak var delegate: DataEnteredDelegate? = nil
@IBOutlet weak var textField: UITextField!
@IBAction func sendTextBackButton(sender: AnyObject) {
// call this method on whichever class implements our delegate protocol
delegate?.userDidEnterInformation(info: textField.text!)
// go back to the previous view controller
self.navigationController?.popViewController(animated: true)
}
}
Mình sẽ đi giải thích từ trên xuống , như mình đã nói “Protocol sẽ định nghĩa những gì Worker có thể làm “ thì theo đoạn code trên protocol này có công dụng là lấy text đã nhập từ textField vào.
Màn hình 2 sẽ là Boss class theo như mình nói, vì vậy bên trong nó sẽ có 1 biến delegate
delegate: DataEnteredDelegate? = nil
và 1 hàm để thực hiện điều mà Boss class muốn Worker class làm :
func sendTextBackButton()
Dòng self.navigationController?.popViewController(animated: true)
thì chỉ để back lại màn hình trứoc thôi
//Code của màn hình 1
import UIKit
class FirstViewController: UIViewController, DataEnteredDelegate {
@IBOutlet weak var label: UILabel!
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showSecondViewController" {
let secondViewController = segue.destination as! SecondViewController
secondViewController.delegate = self
}
}
func userDidEnterInformation(info: String) {
label.text = info
}
}
Màn hình này được xem là Worker class như cách mình nói ở trên, nó sẽ làm nhiệm vụ hiển thị text đã nhập lên label
Cac bạn lưu ý là worker class này phải implement thêm thằng protocol (DataEnteredDelegate )và phải sử dụng lại hàm bên trong Protocol để thực hiện yêu cầu của Boss Class
func userDidEnterInformation(info: String) {
label.text = info
}
secondViewController.delegate = self
dòng này có nghĩa là gọi delegate bên màn 2 và gán cho nó cái đích để nó biết nó sẽ gửi cái delegate đến thằng nào. self tức là màn hình 1 đấy.
OK, ngẫm lại nhé: View 2 click nút –> bắt sự kiện này và gửi đến view 1. Tại sao lại gửi được? Là nhờ Delegate. Gửi bằng cách nào: View 2 send cho delegate, delegate send cho view 1.
Tóm tắt lại đi nói dài dòng quá rồi :))))
Okay , tóm lại là sau cái bài chia sẻ này, hi vọng các bạn nắm được ý chính sau:
- Protocol: trong iOS, nó có hàm để gửi thông điệp giữa 2 ViewController với nhau, hoặc 2 class với nhau.
- Cách hoạt động: view B cần thông báo cho view A rằng mình vừa thực hiện một hành động nào đó : viewB gửi message qua delegate (nhờ các hàm trong protocol, nên nhớ là hàm thì có parameters, nên bạn truyền dữ liệu chính là truyền qua các parameters này). Delegate nhận message rồi gửi lại cho view A. View A thực hiện logic của mình.
- Cách implement: View nào cần gửi thông báo thì view đó cần 1 biến thể hiện delegate (ở ví dụ là view B- hình 1). Trong hàm thực hiện hành động của viewB, nhờ delegate gửi message bằng cách thực hiện method khai báo ở protocol của delegate. View A implement protocol, thực thi lại method mà view B vừa gửi.
Author : Nguyen Khanh Hung