#25–5 期末< 5>好味小姐罐頭訂購APP-Notification資料傳到下一頁

Ethan
彼得潘的 Swift iOS / Flutter App 開發教室
9 min readJul 10, 2024

最近都在忙其他事就沒有持續更新☕☕

上次提到使用IBSegueAction傳資料到MenuDetailTableViewCell裡,
這次要做的是把選擇的資料傳到其他的ViewController(如果以這次的專案來看就是要傳到OrderViewController)。如下圖紅色箭頭:

如果要看藍色箭頭資料要怎麼傳送可以看上一篇期末< 4>的文章~

關於Notification

我們可以分成以下4個步驟:

  1. 發送通知:

➡使用 NotificationCenter.default.post 發送通知,將相關數據打包在 userInfo 字典中並附加到通知中。

NotificationCenter.default.post(name: Notification.Name("OrderAdded"), object: nil, userInfo: userInfo)

2. 添加通知觀察者:

➡在 viewWillAppear 方法中,使用 NotificationCenter.default.addObserver 註冊觀察者,指定接收通知的名稱和處理函數。

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(handleOrderAddedNotification(_:)), name: Notification.Name("OrderAdded"), object: nil)
}

3. 處理通知:

➡實現一個方法(如 handleOrderAddedNotification),該方法在接收到通知時被調用,並處理通知的數據。

// 記得要加@objc

@objc func handleOrderAddedNotification(_ notification: Notification) {
// 處理通知的數據
}

4. 移除通知觀察者:

➡在 viewWillDisappear 方法中,使用NotificationCenter.default.removeObserver 移除觀察者,避免不必要的通知接收。

override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: Notification.Name("OrderAdded"), object: nil)
}

➡在 deinit 方法中,也移除觀察者,確保在對象釋放時不再接收通知,防止洩漏問題產生。

deinit {
NotificationCenter.default.removeObserver(self)
}

所以notification的順序:
發送通知→ 添加通知觀察者→處理通知→移除通知觀察者

專案開始:

先附上完成的gif~

YouTube shorts link:

Code:

發送通知:

建立userInfo字典並使用NotificationCenter.default.post…..

    @IBAction func addOrderButtonTapped(_ sender: UIButton) {

let orderQty = orderQty.text ?? ""
let name = nameLabel.text ?? ""
let title = titleLabel.text ?? ""
let price = priceLabel.text ?? ""
let detailPrice = pricedetailLabel.text ?? ""
let titleImageUrlString = productInfo.titleImage?.absoluteString ?? ""
let imageUrlString = productInfo.image?.absoluteString ?? ""
let titleImageUrl = URL(string: titleImageUrlString)
let imageUrl = URL(string: imageUrlString)
let newDetailOrder = DetailOrderData(name: name, detailPrice: detailPrice, price: price, orderQty: orderQty, imageUrl: imageUrl)
// 檢查是否存在相同 title 的 TitleOrderData
if let index = SharedData.shared.titleOrders.firstIndex(where: { $0.title == title }) {
// 如果存在,添加新的 DetailOrderData
SharedData.shared.titleOrders[index].detailOrderData.append(newDetailOrder)
} else {
// 如果不存在,創建新的 TitleOrderData 並添加到 titleOrders
let newTitleOrder = TitleOrderData(title: title, titleImageUrl: titleImageUrl,detailOrderData: [newDetailOrder])
SharedData.shared.titleOrders.append(newTitleOrder)
}

let userInfo: [String: Any] = [
"orderQty": orderQty,
"name": name,
"title": title,
"price": price,
"detailPrice": detailPrice,
"titleImageUrl": titleImageUrlString,
"imageUrl": imageUrlString
]

NotificationCenter.default.post(name: Notification.Name("OrderAdded"), object: nil, userInfo: userInfo)

print("成功使用 userInfo 發送通知,内容:\(userInfo)")
dismiss(animated: true)

}

添加通知觀察者:

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(handleOrderAddedNotification(_:)), name: Notification.Name("OrderAdded"), object: nil)
}

處理通知:

 @objc private func handleOrderAddedNotification(_ notification: Notification) {
if let userInfo = notification.userInfo {
let title = userInfo["title"] as? String
let orderQty = userInfo["orderQty"] as? String
let name = userInfo["name"] as? String
let price = userInfo["price"] as? String
let detailPrice = userInfo["detailPrice"] as? String
let titleImageUrlString = userInfo["titleImageUrl"] as? String
let imageUrlString = userInfo["imageUrl"] as? String
let titleImageUrl = titleImageUrlString != nil ? URL(string: titleImageUrlString!) : nil
let imageUrl = imageUrlString != nil ? URL(string: imageUrlString!) : nil
let newDetailOrder = DetailOrderData(name: name, detailPrice: detailPrice, price: price, orderQty: orderQty, imageUrl: imageUrl)

if let title = title, let index = SharedData.shared.titleOrders.firstIndex(where: { $0.title == title }) {
SharedData.shared.titleOrders[index].detailOrderData.append(newDetailOrder)
} else {
if let title = title {
let newTitleOrder = TitleOrderData(title: title, titleImageUrl: titleImageUrl, detailOrderData: [newDetailOrder])
SharedData.shared.titleOrders.append(newTitleOrder)
}
}
DispatchQueue.main.async {
self.mainTableView.reloadData()
}
}
}

移除通知觀察者:

override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: Notification.Name("OrderAdded"), object: nil)
}

deinit {
NotificationCenter.default.removeObserver(self)
}

--

--