You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从UITableViewCell移除NSNotification Observer及CollectionView更新咨询

用NSNotification实现Section Header触发对应Cell内CollectionView行更新的方案

这个场景我之前做类似的电商分类页面时遇到过,用NSNotification来实现确实是个可行的思路,下面给你一步步拆解具体实现:

1. 定义专属的Notification名称

首先要定义一个唯一的通知名称,避免和系统或其他业务的通知冲突:

import UIKit

// 全局定义通知名称,方便各方引用
extension NSNotification.Name {
    static let updateCollectionViewRows = NSNotification.Name(rawValue: "com.yourApp.updateCollectionViewRows")
}

2. 在Section Header的按钮点击事件中发送通知

当用户点击Section Header的按钮时,我们需要把当前的section索引通过通知的userInfo传出去,这样接收方才能知道要更新哪个section下的Cell:

// 假设你的Section Header是自定义的UITableViewHeaderFooterView子类
class CustomSectionHeader: UITableViewHeaderFooterView {
    var section: Int = 0 // 记录当前header所属的section
    @IBAction func updateButtonTapped(_ sender: UIButton) {
        // 发送通知,携带section信息
        NotificationCenter.default.post(
            name: .updateCollectionViewRows,
            object: nil,
            userInfo: ["targetSection": section]
        )
    }
}

// 在UITableView的viewForHeaderInSection方法中给header赋值section
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: "CustomSectionHeader") as! CustomSectionHeader
    header.section = section
    return header
}

3. 在包含CollectionView的TableViewCell中监听通知并处理更新

每个TableViewCell需要持有自己所属的section索引,这样收到通知时能判断是否是自己需要更新的,然后同步更新CollectionView的数据源并刷新指定行:

class CustomTableViewCell: UITableViewCell {
    @IBOutlet weak var collectionView: UICollectionView!
    var section: Int = 0 // 记录当前cell所属的section
    // 假设collectionView的数据源是cell自己管理的数组
    var collectionData: [String] = []
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // 添加通知监听
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleCollectionUpdate(_:)),
            name: .updateCollectionViewRows,
            object: nil
        )
    }
    
    @objc private func handleCollectionUpdate(_ notification: Notification) {
        guard let targetSection = notification.userInfo?["targetSection"] as? Int else { return }
        // 只处理当前cell所属section的更新请求
        guard targetSection == section else { return }
        
        // 第一步:先更新collectionView的数据源(这里根据你的业务逻辑修改)
        // 示例:更新前3行的数据
        if collectionData.count >= 3 {
            collectionData[0] = "更新后内容1"
            collectionData[1] = "更新后内容2"
            collectionData[2] = "更新后内容3"
        }
        
        // 第二步:刷新collectionView的指定行
        let indexPathsToUpdate = [
            IndexPath(item: 0, section: 0),
            IndexPath(item: 1, section: 0),
            IndexPath(item: 2, section: 0)
        ]
        collectionView.performBatchUpdates({
            self.collectionView.reloadItems(at: indexPathsToUpdate)
        }, completion: nil)
    }
    
    // 记得在销毁时移除监听,避免内存泄漏
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

// 在UITableView的cellForRowAt方法中给cell赋值section
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell", for: indexPath) as! CustomTableViewCell
    cell.section = indexPath.section
    // 初始化cell的collectionData等
    return cell
}

一些需要注意的细节

  • 数据源同步:一定要先更新CollectionView的数据源,再调用刷新方法,否则会出现数据和UI不匹配甚至崩溃的情况。
  • Section索引准确性:确保Header和Cell的section属性都被正确赋值,不然会出现更新错Section的问题。
  • 内存泄漏:必须在Cell的deinit方法中移除通知监听,因为NotificationCenter会持有观察者的强引用,不移除会导致Cell无法被释放。

内容的提问来源于stack exchange,提问作者Anita Nagori

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:44:07