Ver Fonte

Adds localized subscription duration

Added localizedSubscriptionPeriod as an extension of SKProduct (fixes #474). Also makes SKProductDiscount improvements available for Catalyst apps. Added some watchOS availability markers.
Sam Spencer há 5 anos atrás
pai
commit
152dd68c6d

+ 8 - 0
SwiftyStoreKit.xcodeproj/project.pbxproj

@@ -71,6 +71,9 @@
 		65F7DF9A1DCD536700835D30 /* SwiftyStoreKit-iOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 65F7DF971DCD536100835D30 /* SwiftyStoreKit-iOS.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		65F7DF9B1DCD537800835D30 /* SwiftyStoreKit-macOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 65F7DF981DCD536100835D30 /* SwiftyStoreKit-macOS.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		65F7DF9C1DCD537F00835D30 /* SwiftyStoreKit-tvOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 65F7DF991DCD536100835D30 /* SwiftyStoreKit-tvOS.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		A61BF4BE2481F0560017D9BC /* SKProductDiscount+LocalizedPrice.swift in Sources */ = {isa = PBXBuildFile; fileRef = A61BF4BD2481F0560017D9BC /* SKProductDiscount+LocalizedPrice.swift */; };
+		A61BF4BF2481F0560017D9BC /* SKProductDiscount+LocalizedPrice.swift in Sources */ = {isa = PBXBuildFile; fileRef = A61BF4BD2481F0560017D9BC /* SKProductDiscount+LocalizedPrice.swift */; };
+		A61BF4C02481F0560017D9BC /* SKProductDiscount+LocalizedPrice.swift in Sources */ = {isa = PBXBuildFile; fileRef = A61BF4BD2481F0560017D9BC /* SKProductDiscount+LocalizedPrice.swift */; };
 		C3099C071E2FCDAA00392A54 /* PaymentsControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3099C061E2FCDAA00392A54 /* PaymentsControllerTests.swift */; };
 		C3099C091E2FCE3A00392A54 /* TestProduct.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3099C081E2FCE3A00392A54 /* TestProduct.swift */; };
 		C3099C0B1E2FD13200392A54 /* TestPaymentTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3099C0A1E2FD13200392A54 /* TestPaymentTransaction.swift */; };
@@ -207,6 +210,7 @@
 		65F7DF971DCD536100835D30 /* SwiftyStoreKit-iOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SwiftyStoreKit-iOS.h"; sourceTree = "<group>"; };
 		65F7DF981DCD536100835D30 /* SwiftyStoreKit-macOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SwiftyStoreKit-macOS.h"; sourceTree = "<group>"; };
 		65F7DF991DCD536100835D30 /* SwiftyStoreKit-tvOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SwiftyStoreKit-tvOS.h"; sourceTree = "<group>"; };
+		A61BF4BD2481F0560017D9BC /* SKProductDiscount+LocalizedPrice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SKProductDiscount+LocalizedPrice.swift"; sourceTree = "<group>"; };
 		C3099C061E2FCDAA00392A54 /* PaymentsControllerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaymentsControllerTests.swift; sourceTree = "<group>"; };
 		C3099C081E2FCE3A00392A54 /* TestProduct.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestProduct.swift; sourceTree = "<group>"; };
 		C3099C0A1E2FD13200392A54 /* TestPaymentTransaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestPaymentTransaction.swift; sourceTree = "<group>"; };
@@ -317,6 +321,7 @@
 				65E9E0781ECADF5E005CF7B4 /* InAppReceiptVerificator.swift */,
 				1592CD4F1E27756500D321E6 /* AppleReceiptValidator.swift */,
 				653722801DB8282600C8F944 /* SKProduct+LocalizedPrice.swift */,
+				A61BF4BD2481F0560017D9BC /* SKProductDiscount+LocalizedPrice.swift */,
 				C40C680F1C29414C00B60B7E /* OS.swift */,
 				65F7DF931DCD536100835D30 /* Platforms */,
 			);
@@ -728,6 +733,7 @@
 				650307FA1E317BCF001332A4 /* CompleteTransactionsController.swift in Sources */,
 				65BB6CEA1DDB018900218A0B /* SwiftyStoreKit+Types.swift in Sources */,
 				54B069941CF742D600BAFE38 /* InAppProductQueryRequest.swift in Sources */,
+				A61BF4C02481F0560017D9BC /* SKProductDiscount+LocalizedPrice.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -759,6 +765,7 @@
 				650307F81E317BCF001332A4 /* CompleteTransactionsController.swift in Sources */,
 				65BB6CE81DDB018900218A0B /* SwiftyStoreKit+Types.swift in Sources */,
 				6502F63C1B985CA4004E342D /* SwiftyStoreKit.swift in Sources */,
+				A61BF4BE2481F0560017D9BC /* SKProductDiscount+LocalizedPrice.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -808,6 +815,7 @@
 				650307F91E317BCF001332A4 /* CompleteTransactionsController.swift in Sources */,
 				65BB6CE91DDB018900218A0B /* SwiftyStoreKit+Types.swift in Sources */,
 				C4D74BC51C24CEDC0071AD3E /* SwiftyStoreKit.swift in Sources */,
+				A61BF4BF2481F0560017D9BC /* SKProductDiscount+LocalizedPrice.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 1 - 1
SwiftyStoreKit/PaymentsController.swift

@@ -51,7 +51,7 @@ struct Payment: Hashable {
 public struct PaymentDiscount {
     let discount: AnyObject?
     
-    @available(iOS 12.2, tvOS 12.2, OSX 10.14.4, *)
+    @available(iOS 12.2, tvOS 12.2, OSX 10.14.4, watchOS 6.2, macCatalyst 13.0, *)
     public init(discount: SKPaymentDiscount) {
         self.discount = discount
     }

+ 20 - 0
SwiftyStoreKit/SKProduct+LocalizedPrice.swift

@@ -38,4 +38,24 @@ public extension SKProduct {
         return formatter
     }
     
+    @available(iOSApplicationExtension 11.2, OSX 10.13.2, tvOS 11.2, watchOS 6.2, macCatalyst 13.0, *)
+    var localizedSubscriptionPeriod: String {
+        guard let subscriptionPeriod = self.subscriptionPeriod else { return "" }
+        
+        let dateComponents: DateComponents
+        
+        switch subscriptionPeriod.unit {
+        case .day: dateComponents = DateComponents(day: subscriptionPeriod.numberOfUnits)
+        case .week: dateComponents = DateComponents(weekOfMonth: subscriptionPeriod.numberOfUnits)
+        case .month: dateComponents = DateComponents(month: subscriptionPeriod.numberOfUnits)
+        case .year: dateComponents = DateComponents(year: subscriptionPeriod.numberOfUnits)
+        @unknown default: 
+            print("WARNING: SwiftyStoreKit localizedSubscriptionPeriod does not handle all SKProduct.PeriodUnit cases.")
+            // Default to month units in the unlikely event a different unit type is added to a future OS version
+            dateComponents = DateComponents(month: subscriptionPeriod.numberOfUnits) 
+        }
+
+        return DateComponentsFormatter.localizedString(from: dateComponents, unitsStyle: .short) ?? ""
+    }
+    
 }

+ 63 - 0
SwiftyStoreKit/SKProductDiscount+LocalizedPrice.swift

@@ -0,0 +1,63 @@
+//
+//  SKProductDiscount+LocalizedPrice.swift
+//  SwiftyStoreKit
+//
+//  Created by Sam Spencer on 5/29/20.
+//  Copyright © 2020 Sam Spencer. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import StoreKit
+
+@available(iOSApplicationExtension 11.2, OSX 10.13.2, tvOS 11.2, watchOS 4.2, macCatalyst 13.0, *)
+public extension SKProductDiscount {
+    
+    /// The formatted discount price of the product using the local currency.
+    var localizedPrice: String? {
+        return priceFormatter(locale: priceLocale).string(from: price)
+    }
+    
+    private func priceFormatter(locale: Locale) -> NumberFormatter {
+        let formatter = NumberFormatter()
+        formatter.locale = locale
+        formatter.numberStyle = .currency
+        return formatter
+    }
+    
+    /// The formatted, localized period / date for the product discount.
+    /// - note: The subscription period for the discount is independent of the product's regular subscription period, and does not have to match in units or duration.
+    var localizedSubscriptionPeriod: String {
+        let dateComponents: DateComponents
+        
+        switch subscriptionPeriod.unit {
+        case .day: dateComponents = DateComponents(day: subscriptionPeriod.numberOfUnits)
+        case .week: dateComponents = DateComponents(weekOfMonth: subscriptionPeriod.numberOfUnits)
+        case .month: dateComponents = DateComponents(month: subscriptionPeriod.numberOfUnits)
+        case .year: dateComponents = DateComponents(year: subscriptionPeriod.numberOfUnits)
+        @unknown default: 
+            print("WARNING: SwiftyStoreKit localizedSubscriptionPeriod does not handle all SKProduct.PeriodUnit cases.")
+            // Default to month units in the unlikely event a different unit type is added to a future OS version
+            dateComponents = DateComponents(month: subscriptionPeriod.numberOfUnits) 
+        }
+        
+        return DateComponentsFormatter.localizedString(from: dateComponents, unitsStyle: .full) ?? ""
+    }
+    
+}
+