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

时间:2017-08-22 19:01:07

标签: ios in-app-purchase storekit in-app-subscription skproduct

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

weeklyProduct.price.doubleValue  
weeklyProduct.priceLocale.currencySymbol

其中weeklyProduct是SKProduct。

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

11 个答案:

答案 0 :(得分:4)

你可以得到它,但如上所述它只能从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 ""
    }
}

答案 1 :(得分:4)

我第一次发布答案。保持温柔...

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

从iOS 11.2开始,您可以使用write的{​​{3}}属性获取有关试用的信息。

它包含introductoryPrice类的实例,它描述了所有折扣期,包括免费试用。

答案 4 :(得分:0)

一个不错的@scott Wood。我将其设为 FBSDKShareDialog *dialog = [[FBSDKShareDialog alloc] init]; FBSDKSharePhoto *photo = [[FBSDKSharePhoto alloc] init]; FBSDKSharePhotoContent *content = [[FBSDKSharePhotoContent alloc] init]; for( int i = 0; i < (int)pActiveSession.aShotImages.count; i++ ) { UIImage *image = [UIImage imageWithData:pActiveSession.aShotImages[i]]; [pActiveSession.allShotImages addObject:[self resizeImage:image]]; } content.photos = pActiveSession.allShotImages; photo.userGenerated = YES; dialog.mode = FBSDKShareDialogModeNative; dialog.fromViewController = self; [FBSDKShareDialog showFromViewController:self withContent:content delegate:nil]; 的属性而不是函数。这样可以使行为与枚举更加一致:

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 } } 属性返回复数的函数。

是的,正如其他人指出的那样,如果您的应用程序支持其他语言,则应本地化复数形式。

答案 5 :(得分:0)

我已经使用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
    }
}

您可以像这样从Subscription时段调用它:

import StoreKit

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

您可以依次从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
        }
    }
}

答案 6 :(得分:0)

快捷键5

使用Eslam'sScott's的答案作为启发:

import StoreKit

extension SKProduct {
    func priceString() -> String {
        let period:String = {
            switch self.subscriptionPeriod?.unit {
            case .day: return "day"
            case .week: return "week"
            case .month: return "month"
            case .year: return "year"
            case .none: return ""
            case .some(_): return ""
            }
        }()

        let price = self.localizedPrice!
        let numUnits = self.subscriptionPeriod?.numberOfUnits ?? 0
        let plural = numUnits > 1 ? "s" : ""
        return String(format: "%@ for %d %@%@", arguments: [price, numUnits, period, plural])
    }
}

要使用:

let price = product.priceString()
print(price)

结果:

THB 89.00 for 7 days
THB 149.00 for 1 month

答案 7 :(得分:0)

+ (NSString*)localizedTitleForSKPeriod:(SKProductSubscriptionPeriod*)period{
    NSDateComponents *comps = [NSDateComponents new];
    NSDateComponentsFormatter *fmt = [NSDateComponentsFormatter new];
    switch (period.unit) {
        case SKProductPeriodUnitDay:{
            fmt.allowedUnits = NSCalendarUnitDay;
            comps.day = period.numberOfUnits;
        }break;
        case SKProductPeriodUnitWeek:{
            fmt.allowedUnits = NSCalendarUnitWeekOfMonth;
            comps.weekOfMonth = period.numberOfUnits;
        }break;
        case SKProductPeriodUnitMonth:{
            fmt.allowedUnits = NSCalendarUnitMonth;
            comps.month = period.numberOfUnits;
        }break;
        case SKProductPeriodUnitYear: {
            fmt.allowedUnits = NSCalendarUnitYear;
            comps.year = period.numberOfUnits;
        }break;
    }
    // 1 Day, 1 Week, 2 Weeks, 1 Month, 2 Months, 3 Months, 6 Months, 1 Year
    fmt.unitsStyle = NSDateComponentsFormatterUnitsStyleFull;
    // One Day, One Week, Two Weeks, etc
    //fmt.unitsStyle = NSDateComponentsFormatterUnitsStyleSpellOut;
    NSString *s = [[fmt stringFromDateComponents:comps] capitalizedString];
    return s;
}

答案 8 :(得分:0)

这是更紧凑,使用更短的版本,用于Swift 5,扩展了SKProductSubscriptionPeriod

用法:

print("\(period.localizedDescription) free trial")

//Printed example "1 week free trial"

实施:

extension SKProductSubscriptionPeriod {
    public var localizedDescription: String {
        let period:String = {
            switch self.unit {
            case .day: return "day"
            case .week: return "week"
            case .month: return "month"
            case .year: return "year"
            @unknown default:
                return "unknown period"
            }
        }()
    
        let plural = numberOfUnits > 1 ? "s" : ""
        return "\(numberOfUnits) \(period)\(plural)"
    }
}

答案 9 :(得分:0)

目标C

#import "SKProduct+SKProduct.h"

-(NSString*_Nullable)localizedTrialDuraion{

if (@available(iOS 11.2, *)) {
    
    NSDateComponentsFormatter *formatter = [[NSDateComponentsFormatter alloc] init];
    [formatter setUnitsStyle:NSDateComponentsFormatterUnitsStyleFull]; //e.g 1 month
    formatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorDropAll;
    NSDateComponents * dateComponents = [[NSDateComponents alloc]init];
    [dateComponents setCalendar:[NSCalendar currentCalendar]];
    
    switch (self.introductoryPrice.subscriptionPeriod.unit) {
        case SKProductPeriodUnitDay:{
            formatter.allowedUnits = NSCalendarUnitDay;
            [dateComponents setDay:self.introductoryPrice.subscriptionPeriod.numberOfUnits];
            break;
        }
        case SKProductPeriodUnitWeek:{
            formatter.allowedUnits = NSCalendarUnitWeekOfMonth;
            [dateComponents setWeekOfMonth:self.introductoryPrice.subscriptionPeriod.numberOfUnits];
            break;
        }
        case SKProductPeriodUnitMonth:{
            formatter.allowedUnits = NSCalendarUnitMonth;
            [dateComponents setMonth:self.introductoryPrice.subscriptionPeriod.numberOfUnits];
            break;
        }
        case SKProductPeriodUnitYear:{
            formatter.allowedUnits = NSCalendarUnitYear;
            [dateComponents setYear:self.introductoryPrice.subscriptionPeriod.numberOfUnits];
            break;
        }
        default:{
            return nil;
            break;
        }
            break;
    }
    [dateComponents setValue:self.introductoryPrice.subscriptionPeriod.numberOfUnits forComponent:formatter.allowedUnits];
    return [formatter stringFromDateComponents:dateComponents];
} else {
    // Fallback on earlier versions
}

return nil;

}

答案 10 :(得分:0)

如果您使用 SwiftyStoreKitlocalizedSubscriptionPeriod 是最简单的方法

import SwiftyStoreKit

product.introductoryPrice?.localizedSubscriptionPeriod // "1 week"

这是实现: https://github.com/bizz84/SwiftyStoreKit/blob/master/Sources/SwiftyStoreKit/SKProductDiscount+LocalizedPrice.swift