web-dev-qa-db-ja.com

iOSアプリ内購入サブスクリプションは、SKProductから無料の試用期間を取得します

サブスクリプションでのアプリ内購入に取り組んでいます。 Swiftでは、次のようにSKProductから価格と価格ロケールを取得できます。

weeklyProduct.price.doubleValue  
weeklyProduct.priceLocale.currencySymbol

ここで、weeklyProductはSKProductです。

無料試用期間を取得することは可能ですか?たとえば、製品の2週間の無料試用を指定しました。これをSKProductから取得できますか?

12
mjpablo23

入手できますが、前述のとおり、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 ""
    }
}
7
Eslam Shaker

初めて回答を投稿しました。穏やかな...

インスピレーションとして Eslam's answer を使用して、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)"
    }
}

使用するには:

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

これにより、適切にフォーマットされた文字列が作成されます(1日、1週間、2か月、2年など)。

4
Scott Wood

素敵な@scott Wood。関数ではなく、SKProduct.PeriodUnitのプロパティにします。これにより、列挙型との動作の一貫性が維持されます。

@available(iOS 11.2, *)
extension SKProduct.PeriodUnit {

    var description: String {
        switch self {
        case .day: return "day"
        case .week: return "week"
        case .month: return "month"
        case .year: return "year"
        // support for future values
        default:
            return "N/A"
        }
    }

    func pluralisedDescription(length: Int) -> String {
        let lengthAndDescription = length.description + " " + self.description
        let plural = length > 1 ?  lengthAndDescription + "s" : lengthAndDescription
        return plural
    }
}

そして、descriptionプロパティに基づいて、複数形を返す関数。

そして、はい、他の誰かが指摘したように、アプリが他の言語で利用できる場合は複数形をローカライズする必要があります。

0
kakubei

試用期間はSKProduct情報に含まれていません。アプリにハードコードするか、サーバーに保存する必要があります。このタイプの情報を(現在のところ)導出するために利用できる唯一のオプションは、レシート自体からです。

0
Garrett Cox

IOS 11.2から、introductoryPriceの-​​ SKProduct プロパティを使用して、トライアルに関する情報を取得できます。

SKProductDiscount クラスのインスタンスが含まれ、無料トライアルを含むすべての割引期間が記述されています。

0
DanSkeel

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)
    }
}

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
    }
}

そして、次のようにSubscriptionPeriodから呼び出すことができます。

import StoreKit

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

SKProductDiscountから同様に呼び出すことができます。現時点では、他のPaymentModeは実装していません。

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
        }
    }
}
0