Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS in-app purchase subscription get free trial period length from SKProduct

Tags:

I am working on in-app purchases with subscriptions. In swift, you can get price and price locale from the SKProduct like so:

weeklyProduct.price.doubleValue   weeklyProduct.priceLocale.currencySymbol 

where weeklyProduct is a SKProduct.

Is it possible to get the free trial length? For example, I specified a two week free trial for the product. can I get this from the SKProduct?

like image 235
mjpablo23 Avatar asked Aug 22 '17 19:08

mjpablo23


People also ask

How do I get a free trial on iOS app?

App > Manage In App Purchases > Subscription Basic > 1 Month > Offer a free trial? Before one month if the user cancels the subscription will that app will available to the user.

Do apps automatically charge you after free trial?

Here are three things to know about free trial offers: 1. If you don't cancel on time, you'll be charged. Usually, you have to give your credit card number for a “free trial.” That way, the company can charge you if you don't cancel before the trial period ends.

How do free trials work on Apple?

When users sign up for a subscription with a free trial, their subscription begins immediately but they won't be billed until the free trial period is over. You can select one of the following durations for a free trial: 3 days, 1 week, 2 weeks, 1 month, 2 months, 3 months, 6 months, or 1 year."

What is SKProduct?

An object containing the subscription period duration information. enum SKProduct.PeriodUnit. Values representing the duration of an interval, from a day up to a year.


2 Answers

I've solved it using DateComponentsFormatter, that saves you a lot of time localizing in different languages and handling plurals and whatnot. This might seem like a lot of code, but I hope it will save me time in the future.

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

It requires to convert the SKProduct period unit into a 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     } } 

And you can call it from a SubscriptionPeriod like this:

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

Which you can in turn call from a SKProductDiscount like so. Please note I didn't implement the other PaymentModes for now.

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         }     } } 
like image 150
Roel van der Kraan Avatar answered Sep 18 '22 13:09

Roel van der Kraan


You can get it, but as mentioned above it works only starting from iOS 11.2, for other versions you'll have to get it from your server via API.

Here is an example code that I've used:

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 ""     } } 
like image 22
Binshakerr Avatar answered Sep 21 '22 13:09

Binshakerr