如何区分PKAddPassesViewController中Cancel与AddAll按钮的点击事件?
区分PKAddPassesViewController的Cancel和AddAll按钮点击
我之前也遇到过这个头疼的问题!苹果确实没有给PKAddPassesViewController的代理方法addPassesViewControllerDidFinish提供直接区分Cancel和AddAll操作的属性,但有几个可行的方案,我给你梳理下:
方案1:对比钱包中Pass的数量变化(推荐,官方API无风险)
这个方法的核心逻辑是:点击AddAll会向钱包中添加新的Pass(如果用户没有的话),而Cancel操作不会改变钱包内容。我们可以在present控制器前后分别获取钱包中的Pass数量,通过对比来判断用户点击了哪个按钮。
步骤:
- 提前获取当前钱包的Pass数量并保存
- 在代理方法中再次获取数量,对比变化
import PassKit // 保存初始Pass数量的变量 private var initialWalletPassCount = 0 // 获取当前钱包中的Pass总数 private func getCurrentWalletPassCount() -> Int { let passLibrary = PKPassLibrary() return passLibrary.passes.count } // 准备present PKAddPassesViewController时 func presentAddPassVC(with passes: [PKPass]) { initialWalletPassCount = getCurrentWalletPassCount() let addPassVC = PKAddPassesViewController(passes: passes) addPassVC.delegate = self present(addPassVC, animated: true) } // 实现代理方法 func addPassesViewControllerDidFinish(_ controller: PKAddPassesViewController) { dismiss(animated: true) let currentCount = getCurrentWalletPassCount() if currentCount > initialWalletPassCount { // 用户点击了AddAll,执行你的验证操作 print("用户选择了添加所有Pass") } else { // 用户点击了Cancel print("用户取消了操作") } }
注意:如果用户已经拥有要添加的所有Pass,点击AddAll后数量不会变化,这时候这个方法无法区分操作。这种场景下可以结合下面的通知监听方案。
方案2:监听PKPassLibrary变化通知
通过监听PKPassLibraryDidChange通知,可以准确捕获到Pass被添加到钱包的事件,即使初始数量无变化(比如用户重复添加已有的Pass,但系统实际执行了添加逻辑的情况)。
private var didAddPasses = false func presentAddPassVC(with passes: [PKPass]) { // 添加通知监听 NotificationCenter.default.addObserver( self, selector: #selector(passLibraryDidChange), name: .PKPassLibraryDidChange, object: nil ) let addPassVC = PKAddPassesViewController(passes: passes) addPassVC.delegate = self present(addPassVC, animated: true) } @objc private func passLibraryDidChange(notification: Notification) { // 标记有Pass被添加/修改 didAddPasses = true } // 代理方法中判断 func addPassesViewControllerDidFinish(_ controller: PKAddPassesViewController) { dismiss(animated: true) if didAddPasses { print("用户点击了AddAll") didAddPasses = false // 重置标记 } else { print("用户点击了Cancel") } // 移除通知监听 NotificationCenter.default.removeObserver(self, name: .PKPassLibraryDidChange, object: nil) }
注意:如果用户点击AddAll但系统提示“已在钱包中”,这个通知不会触发,此时还是无法区分操作。
方案3:使用私有属性(不推荐,有审核风险)
苹果的PKAddPassesViewController内部有一个私有布尔属性_passesAdded,可以通过KVO监听它的变化来判断是否执行了添加操作。但这个方法依赖私有API,可能在iOS版本更新后失效,且App Store审核可能被拒,仅适合内部测试场景。
func presentAddPassVC(with passes: [PKPass]) { let addPassVC = PKAddPassesViewController(passes: passes) addPassVC.delegate = self // 添加KVO监听私有属性 addPassVC.addObserver( self, forKeyPath: "_passesAdded", options: .new, context: nil ) present(addPassVC, animated: true) } // 实现KVO监听方法 override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { guard keyPath == "_passesAdded", let passesAdded = change?[.newKey] as? Bool else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) return } if passesAdded { print("用户点击了AddAll") } else { print("用户点击了Cancel") } // 移除监听 (object as? PKAddPassesViewController)?.removeObserver(self, forKeyPath: "_passesAdded") }
总结
优先选择方案1+方案2的组合,覆盖绝大多数正常场景;如果必须处理所有极端情况(包括重复添加已有的Pass),可以考虑方案3,但要承担审核和版本兼容的风险。
内容的提问来源于stack exchange,提问作者Mohit Singhal




