1. 主页 > 好文章

「购物车数据同步遇难题?iOS跨模块通信三种实战方案」


场景痛点:用户点击商品页"加购"按钮后,如何实时更新侧边栏购物车角标?

(某电商App迭代中遇到的真实开发需求)


方案一:NotificationCenter轻量广播(适用于简单数据传递)

swift复制
// 商品详情页发出购买信号
NotificationCenter.default.post(
    name: .didUpdateCart,
    object: ["skuID": "12345", "count": 3]
)

// 侧边栏购物车监听
NotificationCenter.default.addObserver(
    self,
    selector: #selector(updateCartBadge),
    name: .didUpdateCart,
    object: nil
)

@objc func updateCartBadge(_ notification: Notification) {
    guard let info = notification.object as? [String: Any] else { return }
    badgeLabel.text = "\(info["count"] ?? 0)"
}

??适用场景??:跨多层级页面通信、非强关联模块
??避坑指南??:务必在deinit中移除观察者,避免内存泄漏


方案二:Closure回调链(精准控制交互流程)

swift复制
// 定义购物车服务协议
protocol CartServiceable {
    var onCartUpdate: ((Int) -> Void)? { get set }
}

class CartManager: CartServiceable {
    static let shared = CartManager()
    var onCartUpdate: ((Int) -> Void)?
    
    func addToCart(itemID: String) {
        // 网络请求...
        onCartUpdate?(currentCount + 1)
    }
}

// 商品页触发加购
CartManager.shared.addToCart(itemID: "12345")

// 侧边栏绑定更新
CartManager.shared.onCartUpdate = { [weak self] count in
    self?.badgeLabel.text = "\(count)"
}

??适用场景??:1对1精准通信、需要处理异步回调结果
??性能优化??:使用weak避免循环引用,回调中必须切主线程更新UI


方案三:ResponderChain责任链(复杂界面层级穿透)

swift复制
// 自定义购物车事件
class CartEvent: UIEvent {
    var operation: OperationType
    var payload: [String: Any]
    
    override func sendEvent(_ event: UIEvent) {
        UIApplication.shared.sendAction(
            #selector(handleCartEvent(_:)),
            to: nil, // 自动寻找响应者
            from: self,
            for: event
        )
    }
}

// 侧边栏控制器响应
override func canHandle(_ event: UIEvent) -> Bool {
    return event is CartEvent
}

@objc func handleCartEvent(_ event: CartEvent) {
    switch event.operation {
    case .addItem:
        badgeLabel.text = "\(event.payload["count"] ?? 0)"
    // 其他操作处理...
    }
}

??适用场景??:多层嵌套的复杂UI结构、需要事件穿透
??开发技巧??:结合泛型定义统一事件处理接口,配合extension扩展默认实现


方案选型决策树

  1. 是否需要广播到多个接收方 → NotificationCenter
  2. 是否涉及异步操作/网络请求 → Closure回调链
  3. 是否在复杂视图层级中传递 → ResponderChain
  4. 是否需要类型安全 → 改用Combine框架的PassthroughSubject

扩展方案:基于SwiftUI的跨组件通信

(针对适配SwiftUI的混合开发项目)

swift复制
@Observable class CartStore {
    var itemCount = 0
}

struct AddToCartButton: View {
    @Environment(CartStore.self) private var cart
    
    var body: some View {
        Button("加购") {
            cart.itemCount += 1
        }
    }
}

struct CartBadge: View {
    @Environment(CartStore.self) private var cart
    
    var body: some View {
        Text("\(cart.itemCount)")
    }
}

??技术演进建议??:当项目使用Combine或RxSwift时,建议采用PassthroughSubjectPublishSubject实现响应式通信

本文由嘻道妙招独家原创,未经允许,严禁转载