delegation là gì

Chào mừng chúng ta tiếp tục trở về với seri Lập trình iOS mang đến người xem.

Bài ghi chép này tiếp tục thưa cho tới 1 chủ thể khá tầm cỡ và dùng nhiều nhập iOS. Đó là Delegation Pattern , hoặc gọi theo đuổi thương hiệu dân gian lận là Delegate & DataSource. Trước tiên thì bạn phải bắt được những bài bác cơ phiên bản sau:

Bạn đang xem: delegation là gì

  • Basic Swift nhập 10 phút
  • Protocol nhập 10 phút

Vì thực chất của Delegate thì là một trong những Protocol, nên chúng ta nên thành thục Protocol trước tiếp tục. Cách tiếp theo sau là vận dụng quy mô Delegation nhập vào xây dựng iOS.

Bắt đầu thôi!

Chuẩn bị

  • MacOS 10.14.4
  • Xcode 11.0
  • Swift 5.1

1. Vấn đề

1.1. Vấn đề 1

Đây là 1 yếu tố khá là làm cho đầu đau nhập xây dựng.

  • Tại View A, sở hữu 2 chức năng
    • Mở View B
    • Đóng View B
  • Tại View B, sở hữu 2 chức năng
    • Mở View A
    • Đóng View A

Giải quyết mang đến yếu tố này thì phải

  • Tạo con cái trỏ B nhập A
  • Tạo con cái trỏ A nhập B

Khi cơ thì bên trên từng View tiếp tục điều kiển được View cơ và ngược lại. Nhưng vấn này lại đột biến Khi close hoặc huỷ đối tượng người sử dụng con cái trỏ cơ. Dẫn cho tới deadlock

1.2. Vấn đề 2

Vấn đề này là mối liên hệ cha-con trong những đối tượng:

  • Tại View A, việc tạo nên đối tượng người sử dụng con cái (sub-view A) và truyền độ quý hiếm mang đến tính chất của chính nó (data) thì cực kỳ giản dị.
    • Sub-view A đưa đến và View A xét độ quý hiếm mang đến property của Sub-View A bên trên đó
  • Tại Sub-View A, việc trả độ quý hiếm về View A thì ko giản dị như vậy
    • Vì thời điểm này việc thực ganh đua đang được ở bên trên function của Sub-View A và không tồn tại con cái trỏ của View A (con trỏ cha)

Giải quyết yếu tố này thì rất có thể vận dụng cách thức bên trên nhằm xử lý. Tạo con cái trỏ phụ vương nhập đối tượng người sử dụng con cái. Và nó cũng bắt gặp nên trở ngại như bên trên.

Bây giờ tao nên tìm hiểu cơ hội xử lý tối ưu rộng lớn.

2. Delegation Pattern

Đầu tiên, delegate là 1 design pattern dùng làm truyền tài liệu trong những class hoặc struct. Từ “delegate” ở trên đây tức là ủy quyền, uỷ thác, và nhằm dễ nắm bắt hơn nữa thì tiếp tục dùng những kể từ ngữ tương tự động.

Ta nên xử lý được 2 điểm:

  1. Truyền tài liệu trong những đối tượng
  2. Tránh việc deadlock Khi những đối tượng người sử dụng release

2.1. Giải thích

  • Khai báo 1 Protocol P
    • Khai báo những function của P
  • Tại View A thì implement P.. Khi đó:
    • A tiếp tục thừa kế thêm thắt P
    • Có thể hiểu A sở hữu thêm một loại tài liệu nữa là P
    • A khái niệm lại những function tuy nhiên và đã được khai báo bên trên P
  • Tại Sub-View A, bên trên đó:
    • Khai báo 1 property là p (có thể thương hiệu bịa đặt delegate) với loại là P
  • Tạo đối tượng người sử dụng Sub-View A
    • Thực ganh đua bên trên View A
    • Các tính chất Sub-View A sẽ tiến hành View A gán độ quý hiếm cho
    • Trong cơ, gán p = View A (hay là self) được đồng ý vì thế View A tiếp tục implement Protocol P.. và coi như View A sở hữu loại tài liệu là P
    • Đây đó là chiều truyền tài liệu thứ nhất: Từ phụ vương lịch sự con
  • Return Data
    • Thực ganh đua bên trên Sub-View A
    • Sử dụng tính chất p (đang là tính chất nhập class Sub-View A) nhằm gọi những function của chính nó (đã khai báo bên trên Protocol P)
    • Dữ liệu tiếp tục truyền nhập những tham số của những function được khai báo bên trên Protocol P
    • Đây đó là chiều truyền dữ kiệu thứ hai: Từ con cái lịch sự cha
  • p đó là View A, nên
    • p gọi function của chính nó với những đối số là tài liệu kể từ Sub-View A
    • cũng đó là View A gọi những function tuy nhiên tiếp tục implement Protocol P.., với những đối số là tài liệu kể từ Sub-View A

Về thực chất p cũng đó là con cái trỏ View A nên tiếp tục thực ganh đua được những function ước muốn và tài liệu được truyền rằng dựa trên việc gán những đối số cho những function ước muốn cơ.

2.2. Sử dụng

  • Đâu tiên dùng Protocol nhằm khai báo những Delegate.
  • Bước 1: Khai báo Delegate
protocol SubViewADelegate {
    func passData(data: String)
}
  • Bước 2: tạo nên những class View A và Sub-View A
//MARK: Class View A
class ViewA {
    init() { }
}

//MARK: Class Sub-View A
class SubViewA {
    init() { }
}
  • Bước 3: khai báo delegate mang đến Sub-View A
    • Delegte nên được khai báo là optional
//MARK: Class Sub-View A
class SubViewA {
    var delegate: SubViewADelegate?
    
    init() { }
}
  • Bước 4: Implement Protocol mang đến View A
    • Định nghĩa lại những function của Delegate
class ViewA: SubViewADelegate {
    init() { }
    
    //MARK: SubviewA Delegate
    func passData(data: String) {
        print("Data: \(data)")
    }
}
  • Bước 5: thực ganh đua truyền tài liệu kể từ Sub-View A lịch sự View A
//MARK: Do something
var viewA = ViewA()

var subViewA = SubViewA()
subViewA.delegate = viewA
//pass data
subViewA.delegate?.passData(data: "do something")
  • Kết quả

Làm đẹp nhất một chút ít mang đến nó nhìn có trách nhiệm rộng lớn.

//MARK: Define delegate
protocol SubViewADelegate {
    func passData(data: String)
}

//MARK: Class View A
class ViewA {
    init() { }
}
//SubviewA Delegate
extension ViewA: SubViewADelegate {
    func passData(data: String) {
        print("Data: \(data)")
    }
}

//MARK: Class Sub-View A
class SubViewA {
    var delegate: SubViewADelegate?
    
    init() { }
    
    // action
    func doSomething(data: String) {
        if let delegate = delegate {
            delegate.passData(data: data)
        }
    }
}

//MARK: Do something
var viewA = ViewA()

var subViewA = SubViewA()
subViewA.delegate = viewA

//do something
subViewA.doSomething(data: "OK, let's bủ go")

Trong đó:

  • Viết extension mang đến View A nhằm implement delegate
  • Viết function xử lý và truyền tài liệu bên trên Sub-View A & đánh giá delegate

3. Delegation nhập View

DelegateDatasource xuất hiện tại ở từng ngóc ngóc nhập hệ sinh thái xanh iOS, và phần rộng lớn những developer giản dị là chỉ copy & paste bọn chúng nhằm người sử dụng tuy nhiên ko hiểu rõ thực chất hoạt động và sinh hoạt là đi ra sao. Sau trên đây, bản thân tiếp tục thưa về phong thái dùng nó nhập code iOS.

3.1. UI Control cơ bản

Hầu không còn toàn bộ UI Control cơ phiên bản đều sở hữu delegatedatasource của riêng biệt nó. Tại sao vậy?

Delegate của UI Control nhằm mục đích thông tin cho những View hoặc Controller biết sự thay cho thay đổi về trạng thái của chủ yếu phiên bản đằm thắm nó.

Ví dụ:

Khi sử dụng tay tác dụng nhằm kéo 1 scrollview và thả đi ra. Thì scrollview vẫn nối tiếp chạy 1 tí, tuy vậy người tiêu dùng còn tác dụng nữa. Đó đó là sự thay cho thay đổi tình trạng của scrollview. Tính đến khi scrollview ngừng và người tiêu dùng mong muốn bắt được sự khiếu nại cơ thì scroll view nên gởi chuồn 1 sự khiếu nại vị delegate của chính nó. Nếu View hoặc Controller implement và lắng tai sự khiếu nại kể từ delegate của scrollview thì tiếp tục sẽ có được .

Làm thế này nhằm tìm hiểu đi ra tụi nó?

Ví dụ với UITableViewDelegate > nhấn command + kích con chuột.

Nhảy thẳng cho tới tệp tin define những function của Delegate cơ.

Copy đi ra và người sử dụng bên trên class tuy nhiên implement Delegate cơ.

Đây cũng đó là cơ hội bắt sự khiếu nại tiếp theo sau (ngoài IBAction, cảm biến Event và cảm ứng) nhập xây dựng iOS.

Xem thêm: diện tích xung quanh của hình trụ

 

3.2. Custom View

Phần này tiếp tục chỉ dẫn chủ yếu về dùng delegate nhập custom view. Mục đích:

    • Truyền tài liệu kể từ custom view về View Controller
    • Không rất cần được nên tạo nên những property nhằm quản lý và vận hành những custom view như là một trong những đổi mới toàn viên của class ViewController
    • Sử dụng được với tương đối nhiều đối tượng người sử dụng custom tạo nên ra

Tiến hành tạo nên 1 custom view với cách thức LoadNibName . Nếu chúng ta chưa chắc chắn thì rất có thể hiểu bài bác custom view:

    • Basic iOS tutorial : Custom View

Trong đó:

  • UserView
    • Là 1 sub-class của UIView
    • Có 1 UIImageView và 1 UILabel

Khai báo thêm 1 Protocol mang đến UserView:

  • Đặt thương hiệu là UserViewDelegate
  • Khai báo 1 function với mục tiêu trả về trật tự của view Khi người tiêu dùng đụng chạm nhập.
protocol UserViewDelegate: class {
    func userView(userView: UserView, didSelectedWith index: Int)
}

Triển khai dùng bên trên custom view

class UserView: UIView {
    
    weak var delegate: UserViewDelegate?
    var index: Int = 0
    
    @IBOutlet weak var avatarImageView: UIImageView!
    @IBOutlet weak var nameLabel: UILabel!
    
    @IBAction func tap(_ sender: Any) {
        if let delegate = delegate {
            delegate.userView(userView: self, didSelectedWith: index)
        }
    }
    
}

Trong đó:

  • Khai báo property delegate với kể từ khoá weak và loại optional
  • Điều này tách leak bộ nhớ lưu trữ Khi đối tượng người sử dụng custom view bị giải phỏng thì delegate cũng trở thành giải tỏa theo
  • Khi dùng delegate nhằm đáp ứng mang đến lịch trình không biến thành crash thì mặt mày đánh giá sự tồn bên trên của bọn chúng.

Tại tệp tin ViewController, tạo nên custom view và  addSubview

import UIKit

class HomeViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let userView = Bundle.main.loadNibNamed("UserView", owner: self, options: nil)?.first as! UserView
        userView.frame = CGRect(x: 50, y: 50, width: 100, height: 125)
        userView.index = 10
        view.addSubview(userView)
    }
}

Viết extension của ViewController mang đến việc implement Delegate. Tại trên đây, khái niệm lại những function của delegate.

extension HomeViewController: UserViewDelegate {
    func userView(userView: UserView, didSelectedWith index: Int) {
        print("Did select UserView with index \(index)")
    }
}

Tiếp theo đuổi, xét độ quý hiếm delegate của custom view đó là ViewController

userView.delegate = self

Kết quả:

Bạn nhằm ý thì tiếp tục thấy:

  • Biến userView được đưa đến và addSubview nhập view của ViewController thì kết thúc đẩy hàm viewDidLoad nó có khả năng sẽ bị giải phỏng ngoài cỗ nhớ
  • Tuy nhiên, delegate của chính nó tiếp tục trỏ cho tới ViewController nên tất cả chúng ta vẫn rất có thể quản lý và vận hành và nhận tài liệu kể từ Custom View

Ngoài việc dùng với Custom View thì delegate được dùng ở đa số những class/struct/enum. Như vậy nhăm ngày càng tăng sức khỏe của class của chúng ta.

4. DataSource

Theo những phần bên trên thì tất cả chúng ta mới nhất chuồn được một chiều là:

Truyền tài liệu kể từ đối tượng người sử dụng con cái lịch sự đối tượng người sử dụng phụ vương.

Vậy Khi đối tượng người sử dụng con cái mong muốn lấy độ quý hiếm kể từ đối tượng người sử dụng phụ vương thì tiếp tục như vậy nào?

Có một định nghĩa được thể hiện là datasource với chân thành và ý nghĩa hòn đảo ngược lại quy trình delegate.

Phần tích một chút ít về delagate:

  • function được thực ganh đua và tài liệu được gán nhập những thông số của function
  • các function thông thường tiếp tục return về là Void

Đảo ngược lại quy trình delegate thì tiếp tục như vậy nào? Tham khảo đoạn code sau:

protocol UserViewDataSource: class {
    func userView(nameOf userView: UserView) -> String
    func userView(indexOf userView: UserView) -> Int
}

Trong đó:

  • Function return về loại tài liệu không giống Void
  • Cách khai báo DataSource vẫn tương tự Delegate
  • Các function chỉ khai báo

Sử dụng nhập custom view

  • Khai báo property dataSource
weak var dataSource: UserViewDataSource?
  • Sử dụng dataSource bên trên Custom View, cũng tương tự động như delegate.
func configView() {
        if let dataSource = dataSource {
            //set index
            index = dataSource.userView(indexOf: self)
            
            //set name
            nameLabel.text = dataSource.userView(nameOf: self)
        }
    }

Tại tệp tin ViewController:

  • implement UserViewDataSource bằng phương pháp tạo nên 1 extension mang đến ViewController.
extension HomeViewController: UserViewDataSource {
    func userView(nameOf userView: UserView) -> String {
        return "Fx Studio"
    }
    
    func userView(indexOf userView: UserView) -> Int {
        return 999
    }
}
  • Xét độ quý hiếm mang đến property dataSource của Custom View là ViewController
userView.dataSource = self
  • Gọi hàm configView() của Custom View để thay thế thay đổi tài liệu của Custom View.

Xem lại toàn cỗ code của ViewController và chạy lịch trình nhằm kiểm tra:

import UIKit

class HomeViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let userView = Bundle.main.loadNibNamed("UserView", owner: self, options: nil)?.first as! UserView
        userView.frame = CGRect(x: 50, y: 150, width: 100, height: 125)
        userView.index = 10
        userView.delegate = self
        userView.dataSource = self
        view.addSubview(userView)
        
        userView.configView()
    }
}


extension HomeViewController: UserViewDelegate {
    func userView(userView: UserView, didSelectedWith index: Int) {
        print("Did select UserView with index \(index)")
    }
}

extension HomeViewController: UserViewDataSource {
    func userView(nameOf userView: UserView) -> String {
        return "Fx Studio"
    }
    
    func userView(indexOf userView: UserView) -> Int {
        return 999
    }
}

Kết quả:

  • Ban đầu Custom View được tạo nên và addSubview nhập View của ViewController với index = 10
  • Gọi hàm configView() thì độ quý hiếm của indexname đã được thay cho đổi
  • Khi click nhập Custom View thì delegate tiếp tục truyền tài liệu index về ViewController và in ra
  • Bây giờ độ quý hiếm của index = 999

Xem thêm: đại học sân khấu điện ảnh hcm

 

Qua ví dụ bên trên thì tao thấy delegatedatasource thực ra đều là Protocol. Nhưng tuỳ nhập cơ hội dùng là truyền hoặc lấy tài liệu thì tất cả chúng ta tiếp tục mang tên gọi riêng biệt mang đến nó.

  • Truyền tài liệu : Delegate
  • Lấy dữ liệu: DataSource

Tạm kết

  • Nắm được những yếu tố trong những công việc truyền dữ liệu
  • Hiểu được quy mô Delegation
  • Khai báo và dùng những Delagate & DataSource Protocol
  • Nắm được sự không giống nhau cơ phiên bản của Delegate và DataSource