首页 > 解决方案 > SKDownload 的 contentURL 不是 nil 但不存在

问题描述

我正在使用 StoreKit 构建我的应用程序的 In App Purchases 部分,并且在购买和下载 Apple 托管的内容时遇到了奇怪的行为。

简而言之,这是代码:

SKPaymentQueue.default().add(delegate)
...
SKPaymentQueue.default().add(payment)

代表

func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
    transactions.forEach { transaction in
        switch transaction.transactionState {
        case .purchased, .restored:
            if transaction.downloads.isEmpty {
                SKPaymentQueue.default().finishTransaction(transaction)
                didPurchaseProduct(nil)
            } else {
                SKPaymentQueue.default().start(transaction.downloads)
            }

        case .failed:
            SKPaymentQueue.default().finishTransaction(transaction)
            didFailWithError(transaction.error)

        case .deferred: break
        case .purchasing: break
        @unknown default:
            fatalError("Unhandled case \(transaction.transactionState)")
        }
    }
}

func paymentQueue(_ queue: SKPaymentQueue, updatedDownloads downloads: [SKDownload]) {
    downloads.forEach { download in
        switch download.state {
        case .waiting: break
        case .active: break
        case .paused: break
        case .finished:
            didPurchaseProduct(download)
        case .failed: didFailWithError(nil)
        case .cancelled: didFailWithError(nil)
        }
    }
}

下载处理

do {
    guard let url = download.contentURL else {
        promise(.failure(.noContentURL))
        return
    }

    print("download.contentURL =", url.absoluteString)
    print("download.contentURL exists:", FileManager.default.fileExists(atPath: url.path))

    let path = url.appendingPathComponent("Contents").appendingPathComponent("Content.json")
    let data = try Data(contentsOf: path, options: .mappedIfSafe)
    let package = try JSONDecoder().decode(CardPackage.self, from: data)

    promise(.success(.didProcessDownload(package)))

    SKPaymentQueue.default().finishTransaction(download.transaction)
} catch {
    print(error.localizedDescription)

    promise(.failure(.decodeErrorDidOccur))

    SKPaymentQueue.default().finishTransaction(download.transaction)
}

我面临的问题如下。附加到事务的 SKDownload 有一个 contentURL,它不是 nil,而是对应于一个不存在的文件夹。这些是打印的日志

download.contentURL = file:///private/var/mobile/Containers/Data/Application/EE97399D-974F-417A-AA50-969E3C238693/Library/Caches/StoreKit/13484324297981572924/
download.contentURL exists: false

The file “Content.json” couldn’t be opened because there is no such file.

有谁知道为什么会发生这种情况以及如何解决?

标签: iosswiftstorekit

解决方案


我遇到了同样的问题,我怀疑问题是在我开发 StoreKit 集成的某个时刻,我删除了已安装的应用程序。重新安装应用程序时,它会收到一个新容器,因此会收到一个新的 Caches 目录,但之前未完成的事务下载仍然包含指向旧安装容器的 url,该容器当然不再存在。

无法为未完成的事务创建新的下载。

解决方案是通过完成交易来丢弃不可访问的下载

SKPaymentQueue.default().finishTransaction(download.transaction)

然后通过实现恢复购买来完成 StoreKit 集成。

当您恢复购买时,您将获得新的交易和新的下载。

大概这是在生产环境中永远不应该发生的事情,但如果发生了,我猜唯一合适的行动是告诉用户出了点问题并指示他们恢复购买。


推荐阅读