如何从BookDetailViewController更新TableView单元格页码?能否用Notification Center?
问题解答:用Notification Center实现书籍阅读进度更新
完全可以通过Notification Center实现这个需求,下面是具体的实现步骤和代码修改方案:
1. 定义全局通知名称
先定义一个全局的通知标识符,方便两端统一引用:
extension Notification.Name { static let updateBookProgress = Notification.Name("UpdateBookProgress") }
2. 在HomeViewController中注册并处理通知
在viewDidLoad中添加通知监听,同时在控制器销毁时移除监听避免内存泄漏,新增处理通知的方法来更新数据源和表格:
class HomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, SendingBookDataProtocol { @IBOutlet weak var addBookButton: UIButton! @IBOutlet var tableView: UITableView! var items = [BookItem]() override func viewDidLoad() { super.viewDidLoad() tableView?.delegate = self tableView?.dataSource = self let nib = UINib(nibName: "BookCell", bundle: nil) tableView?.register(nib, forCellReuseIdentifier: "BookCell") // 注册进度更新通知 NotificationCenter.default.addObserver(self, selector: #selector(updateBookProgress(_:)), name: .updateBookProgress, object: nil) } deinit { // 移除通知监听 NotificationCenter.default.removeObserver(self) } // 处理进度更新通知 @objc private func updateBookProgress(_ notification: Notification) { guard let userInfo = notification.userInfo, let index = userInfo["index"] as? Int, let newCurrentPage = userInfo["currentPage"] as? String, index < items.count else { return } // 更新数据源中的页码 items[index].currentPage = newCurrentPage // 仅刷新对应单元格,比全局reload更高效 tableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .automatic) } // 原有代码保持不变... // 修改didSelectRowAt,传递书籍在数据源中的索引 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let bookDetailVc = self.storyboard?.instantiateViewController(withIdentifier: "BookDetailView") as? BookDetailViewController let item = items[indexPath.row] bookDetailVc?.bookItem = item bookDetailVc?.bookIndex = indexPath.row // 新增:传递索引 self.navigationController?.pushViewController(bookDetailVc!, animated: true) } // 原有代码保持不变... }
3. 修改BookDetailViewController实现
注意:BookDetailViewController无需继承HomeViewController,直接继承UIViewController即可,避免不必要的属性继承。新增属性接收书籍数据和索引,添加按钮点击事件发送通知:
class BookDetailViewController: UIViewController{ // 修改继承类为UIViewController @IBOutlet weak var bookTitle: UILabel! @IBOutlet weak var currentPageDetail: UILabel! @IBOutlet weak var totalPagesDetail: UILabel! @IBOutlet weak var updatePageButton: UIButton! // 假设你有一个更新页码的按钮 var bookItem: BookItem? // 直接接收书籍对象 var bookIndex: Int = 0 // 接收书籍在数据源中的索引 override func viewDidLoad() { super.viewDidLoad() // 用bookItem初始化页面UI bookTitle.text = bookItem?.title currentPageDetail.text = bookItem?.currentPage totalPagesDetail.text = bookItem?.totalPages } // 更新页码按钮点击事件 @IBAction func updatePageTapped(_ sender: UIButton) { // 示例:这里替换为你获取新页码的逻辑(比如输入框、步进器的值) let newCurrentPage = "100" // 更新当前页面显示 currentPageDetail.text = newCurrentPage // 发送通知给HomeViewController更新表格 NotificationCenter.default.post( name: .updateBookProgress, object: nil, userInfo: [ "index": bookIndex, "currentPage": newCurrentPage ] ) } }
额外优化建议
- 相比Notification Center,**闭包(Closure)或代理(Delegate)**类型更安全,能避免通知名称拼写错误、用户信息类型不匹配的问题,是更推荐的组件间通信方式。
- 避免不必要的继承关系,BookDetailViewController只需要负责书籍详情展示和进度修改,无需继承HomeViewController。
内容的提问来源于stack exchange,提问作者alias.marv
相关产品推荐
相关产品推荐

