Passing Data Between View Controllers với Swift 5 và UIKit

Có nhiều cách để truyền dữ liệu giữa các View Controllers trong ứng dụng iOS. Dưới đây là một số cách phổ biến, được sắp xếp theo thứ tự từ cơ bản đến phức tạp, cùng với ví dụ minh họa:

1. Sử dụng prepare(for:sender:) (Cơ bản)

Cách này phù hợp khi bạn muốn truyền dữ liệu từ một ViewController (ViewController A) sang một ViewController khác (ViewController B) khi người dùng tương tác với một phần tử UI (ví dụ như nhấn một nút).

Ví dụ:

// ViewController A
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let destinationVC = segue.destination as? ViewControllerB {
        destinationVC.data = "Dữ liệu từ ViewController A"
    }
}

// ViewController B
var data: String?

Giải thích:

  • Trong ViewController A, phương thức prepare(for:sender:) được gọi tự động khi segue được kích hoạt.
  • Kiểm tra xem ViewController đích có phải là ViewControllerB hay không.
  • Truyền dữ liệu vào thuộc tính data của ViewControllerB.

2. Sử dụng Properties (Đơn giản)

Cách này phù hợp khi bạn muốn truyền dữ liệu một chiều từ ViewController A sang ViewController B.

Ví dụ:

// ViewController A
let dataToPass = "Dữ liệu từ ViewController A"

// ViewController B
var receivedData: String?

override func viewDidLoad() {
    super.viewDidLoad()
    receivedData = dataToPass // Truy cập dữ liệu từ ViewController A
}

Giải thích:

  • ViewController A khai báo một thuộc tính dataToPass chứa dữ liệu cần truyền.
  • ViewController B khai báo một thuộc tính receivedData để nhận dữ liệu.
  • Trong viewDidLoad của ViewController B, truy cập dữ liệu từ dataToPass của ViewController A.

3. Sử dụng Delegation (Trung bình)

Cách này phù hợp khi bạn muốn ViewController B thông báo lại cho ViewController A sau khi hoàn thành một tác vụ nào đó.

Ví dụ:

// Protocol
protocol DataPassingDelegate: AnyObject {
    func dataPassed(data: String)
}

// ViewController A
weak var delegate: DataPassingDelegate?

// ViewController B
weak var delegate: DataPassingDelegate?

func passData(data: String) {
    delegate?.dataPassed(data: data)
}

// ViewController A (trong hàm gọi ViewController B)
let vcB = ViewControllerB()
vcB.delegate = self
// ...

// ViewController A (thực hiện protocol)
extension ViewControllerA: DataPassingDelegate {
    func dataPassed(data: String) {
        print("Dữ liệu từ ViewController B: \(data)")
    }
}

Giải thích:

  • Định nghĩa một protocol DataPassingDelegate với phương thức dataPassed.
  • ViewController A và ViewController B đều tuân theo protocol này.
  • ViewController A gán chính nó làm delegate cho ViewController B.
  • ViewController B gọi phương thức dataPassed của delegate khi có dữ liệu cần truyền.

4. Sử dụng Notification Center (Trung bình)

Cách này phù hợp khi bạn muốn truyền dữ liệu giữa nhiều ViewController mà không cần mối quan hệ trực tiếp.

Ví dụ:

// ViewController A
NotificationCenter.default.post(name: .dataChanged, object: nil, userInfo: ["data": "Dữ liệu từ ViewController A"])

// ViewController B
NotificationCenter.default.addObserver(self, selector: #selector(handleDataChanged), name: .dataChanged, object: nil)

@objc func handleDataChanged(notification: Notification) {
    if let data = notification.userInfo?["data"] as? String {
        print("Dữ liệu nhận được: \(data)")
    }
}

Giải thích:

  • ViewController A đăng ký thông báo với tên dataChanged và dữ liệu cần truyền.
  • ViewController B đăng ký lắng nghe thông báo dataChanged.
  • Khi nhận được thông báo, ViewController B xử lý dữ liệu từ thông báo.

5. Sử dụng UserDefaults (Trung bình)

Cách này phù hợp khi bạn muốn lưu trữ dữ liệu cục bộ và truy cập từ nhiều ViewController.

Ví dụ:

// ViewController A
UserDefaults.standard.set("Dữ liệu từ ViewController A", forKey: "myData")

// ViewController B
if let data = UserDefaults.standard.string(forKey: "myData") {
    print("Dữ liệu nhận được: \(data)")
}

Giải thích:

  • ViewController A lưu trữ dữ liệu vào UserDefaults với key "myData".
  • ViewController B truy cập dữ liệu từ UserDefaults với key "myData".

6. Sử dụng Core Data (Nâng cao)

Cách này phù hợp khi bạn muốn lưu trữ và quản lý dữ liệu phức tạp trong ứng dụng.

Ví dụ:

Lưu ý:

  • Chọn cách phù hợp nhất với nhu cầu của ứng dụng.
  • Luôn đảm bảo dữ liệu được truyền một cách an toàn và hiệu quả.