iOS应用内购买订阅从SKProduct获得免费试用期

mjp*_*o23 10 storekit in-app-purchase ios skproduct in-app-subscription

我正在通过订阅进行应用内购买.在swift中,您可以从SKProduct获得价格和价格区域设置,如下所示:

weeklyProduct.price.doubleValue  
weeklyProduct.priceLocale.currencySymbol
Run Code Online (Sandbox Code Playgroud)

其中weeklyProduct是SKProduct.

是否有可能获得免费试用期?例如,我为该产品指定了为期两周的免费试用版.我可以从SKProduct获得这个吗?

Roe*_*aan 22

我已经使用 DateComponentsFormatter 解决了这个问题,这为您节省了大量时间以不同语言进行本地化以及处理复数等等。这可能看起来像很多代码,但我希望它会在未来节省我的时间。

import Foundation

class PeriodFormatter {
    static var componentFormatter: DateComponentsFormatter {
        let formatter = DateComponentsFormatter()
        formatter.maximumUnitCount = 1
        formatter.unitsStyle = .full
        formatter.zeroFormattingBehavior = .dropAll
        return formatter
    }

    static func format(unit: NSCalendar.Unit, numberOfUnits: Int) -> String? {
        var dateComponents = DateComponents()
        dateComponents.calendar = Calendar.current
        componentFormatter.allowedUnits = [unit]
        switch unit {
        case .day:
            dateComponents.setValue(numberOfUnits, for: .day)
        case .weekOfMonth:
            dateComponents.setValue(numberOfUnits, for: .weekOfMonth)
        case .month:
            dateComponents.setValue(numberOfUnits, for: .month)
        case .year:
            dateComponents.setValue(numberOfUnits, for: .year)
        default:
            return nil
        }

        return componentFormatter.string(from: dateComponents)
    }
}
Run Code Online (Sandbox Code Playgroud)

它需要将 SKProduct 周期单位转换为 NSCalendarUnit

import StoreKit

@available(iOS 11.2, *)
extension SKProduct.PeriodUnit {
    func toCalendarUnit() -> NSCalendar.Unit {
        switch self {
        case .day:
            return .day
        case .month:
            return .month
        case .week:
            return .weekOfMonth
        case .year:
            return .year
        @unknown default:
            debugPrint("Unknown period unit")
        }
        return .day
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以像这样从 SubscriptionPeriod 调用它:

import StoreKit

@available(iOS 11.2, *)
extension SKProductSubscriptionPeriod {
    func localizedPeriod() -> String? {
        return PeriodFormatter.format(unit: unit.toCalendarUnit(), numberOfUnits: numberOfUnits)
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以像这样从 SKProductDiscount 调用。请注意,我暂时没有实现其他 PaymentModes。

import StoreKit

@available(iOS 11.2, *)
extension SKProductDiscount {
    func localizedDiscount() -> String? {
        switch paymentMode {
        case PaymentMode.freeTrial:
            return "Free trial for \(subscriptionPeriod.localizedPeriod() ?? "a period")"
        default:
            return nil
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 最优雅的解决方案,因为它适当地考虑了本地化。 (2认同)

小智 12

使用Eslam 的答案作为灵感,我创建了 SKProduct.PeriodUnit 的扩展

extension SKProduct.PeriodUnit {
    func description(capitalizeFirstLetter: Bool = false, numberOfUnits: Int? = nil) -> String {
        let period:String = {
            switch self {
            case .day: return "day"
            case .week: return "week"
            case .month: return "month"
            case .year: return "year"
            }
        }()

        var numUnits = ""
        var plural = ""
        if let numberOfUnits = numberOfUnits {
            numUnits = "\(numberOfUnits) " // Add space for formatting
            plural = numberOfUnits > 1 ? "s" : ""
        }
        return "\(numUnits)\(capitalizeFirstLetter ? period.capitalized : period)\(plural)"
    }
}
Run Code Online (Sandbox Code Playgroud)

使用:

if #available(iOS 11.2, *),
    let period = prod?.introductoryPrice?.subscriptionPeriod
{
    let desc = period.unit.description(capitalizeFirstLetter: true, numberOfUnits: period.numberOfUnits)
} else {
    // Fallback
}
Run Code Online (Sandbox Code Playgroud)

这将创建一个格式良好的字符串(例如 1 天、1 周、2 个月、2 年)

  • 很好的答案。如果要本地化,请使用 stringdicts 而不是 `plural` 变量:https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPInternational/StringsdictFileFormat/StringsdictFileFormat.html (2认同)

小智 8

您可以获取它,但是如上所述,它只能从iOS 11.2开始运行,对于其他版本,则必须通过API从服务器获取它。

这是我使用的示例代码:

if #available(iOS 11.2, *) {
  if let period = prod.introductoryPrice?.subscriptionPeriod {
     print("Start your \(period.numberOfUnits) \(unitName(unitRawValue: period.unit.rawValue)) free trial")
  }
} else {
  // Fallback on earlier versions
  // Get it from your server via API
}

func unitName(unitRawValue:UInt) -> String {
    switch unitRawValue {
    case 0: return "days"
    case 1: return "weeks"
    case 2: return "months"
    case 3: return "years"
    default: return ""
    }
}
Run Code Online (Sandbox Code Playgroud)


Gar*_*Cox 0

试用长度不包含在 SKProduct 信息中,必须硬编码到应用程序中或存储在您的服务器上。(当前)获取此类信息的唯一可用选项是从收据本身。