You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何区分PKAddPassesViewController中Cancel与AddAll按钮的点击事件?

区分PKAddPassesViewController的Cancel和AddAll按钮点击

我之前也遇到过这个头疼的问题!苹果确实没有给PKAddPassesViewController的代理方法addPassesViewControllerDidFinish提供直接区分Cancel和AddAll操作的属性,但有几个可行的方案,我给你梳理下:

方案1:对比钱包中Pass的数量变化(推荐,官方API无风险)

这个方法的核心逻辑是:点击AddAll会向钱包中添加新的Pass(如果用户没有的话),而Cancel操作不会改变钱包内容。我们可以在present控制器前后分别获取钱包中的Pass数量,通过对比来判断用户点击了哪个按钮。

步骤:

  1. 提前获取当前钱包的Pass数量并保存
  2. 在代理方法中再次获取数量,对比变化
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

火山引擎 最新活动