diff --git a/FBSDKCoreKit/FBSDKCoreKit/AppEvents/FBSDKAppEvents.m b/FBSDKCoreKit/FBSDKCoreKit/AppEvents/FBSDKAppEvents.m index d3a27834fe..1d9a61573c 100644 --- a/FBSDKCoreKit/FBSDKCoreKit/AppEvents/FBSDKAppEvents.m +++ b/FBSDKCoreKit/FBSDKCoreKit/AppEvents/FBSDKAppEvents.m @@ -974,19 +974,17 @@ - (void)fetchServerConfiguration:(FBSDKCodeBlock)callback [self.onDeviceMLModelManager enable]; } }]; - if (@available(iOS 11.3, *)) { - if ([self.settings isSKAdNetworkReportEnabled]) { - [self.featureChecker checkFeature:FBSDKFeatureSKAdNetwork completionBlock:^(BOOL SKAdNetworkEnabled) { - if (SKAdNetworkEnabled) { - [SKAdNetwork registerAppForAdNetworkAttribution]; - [self.featureChecker checkFeature:FBSDKFeatureSKAdNetworkConversionValue completionBlock:^(BOOL SKAdNetworkConversionValueEnabled) { - if (SKAdNetworkConversionValueEnabled) { - [self.skAdNetworkReporter enable]; - } - }]; - } - }]; - } + if ([self.settings isSKAdNetworkReportEnabled]) { + [self.featureChecker checkFeature:FBSDKFeatureSKAdNetwork completionBlock:^(BOOL SKAdNetworkEnabled) { + if (SKAdNetworkEnabled) { + [SKAdNetwork registerAppForAdNetworkAttribution]; + [self.featureChecker checkFeature:FBSDKFeatureSKAdNetworkConversionValue completionBlock:^(BOOL SKAdNetworkConversionValueEnabled) { + if (SKAdNetworkConversionValueEnabled) { + [self.skAdNetworkReporter enable]; + } + }]; + } + }]; } if (@available(iOS 14.0, *)) { [self.featureChecker checkFeature:FBSDKFeatureAEM completionBlock:^(BOOL AEMEnabled) { diff --git a/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKAppEventsConfigurationManager.m b/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKAppEventsConfigurationManager.m index d59fcfaac6..3674c658e9 100644 --- a/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKAppEventsConfigurationManager.m +++ b/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKAppEventsConfigurationManager.m @@ -64,16 +64,9 @@ - (void) configureWithStore:(id)store self.graphRequestConnectionFactory = graphRequestConnectionFactory; id data = [self.store fb_objectForKey:FBSDKAppEventsConfigurationKey]; - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdeprecated-declarations" if ([data isKindOfClass:NSData.class]) { - if (@available(iOS 11.0, tvOS 11.0, *)) { - self.configuration = [NSKeyedUnarchiver unarchivedObjectOfClass:FBSDKAppEventsConfiguration.class fromData:data error:nil]; - } else { - self.configuration = [NSKeyedUnarchiver unarchiveObjectWithData:data]; - } + self.configuration = [NSKeyedUnarchiver unarchivedObjectOfClass:FBSDKAppEventsConfiguration.class fromData:data error:nil]; } - #pragma clang diagnostic pop if (!self.configuration) { self.configuration = FBSDKAppEventsConfiguration.defaultConfiguration; diff --git a/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKPaymentProductRequestor.m b/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKPaymentProductRequestor.m index 52f6160fb3..50db7622d0 100644 --- a/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKPaymentProductRequestor.m +++ b/FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/FBSDKPaymentProductRequestor.m @@ -137,11 +137,10 @@ - (void)logTransactionEvent:(SKProduct *)product - (BOOL)isSubscription:(SKProduct *)product { #if !TARGET_OS_TV - if (@available(iOS 11.2, *)) { - return (product.subscriptionPeriod != nil) && ((unsigned long)product.subscriptionPeriod.numberOfUnits > 0); - } -#endif + return (product.subscriptionPeriod != nil) && ((unsigned long)product.subscriptionPeriod.numberOfUnits > 0); +#else return NO; +#endif } - (NSMutableDictionary *)getEventParametersOfProduct:(SKProduct *)product @@ -184,26 +183,24 @@ - (BOOL)isSubscription:(SKProduct *)product } #if !TARGET_OS_TV - if (@available(iOS 11.2, *)) { - if ([self isSubscription:product]) { - // subs inapp - [FBSDKTypeUtility dictionary:eventParameters setObject:[self durationOfSubscriptionPeriod:product.subscriptionPeriod] forKey:FBSDKAppEventParameterNameSubscriptionPeriod]; - [FBSDKTypeUtility dictionary:eventParameters setObject:@"subs" forKey:FBSDKAppEventParameterNameInAppPurchaseType]; - [FBSDKTypeUtility dictionary:eventParameters setObject:[self isStartTrial:transaction ofProduct:product] ? @"1" : @"0" forKey:FBSDKAppEventParameterNameIsStartTrial]; - // trial information for subs - SKProductDiscount *discount = product.introductoryPrice; - if (discount) { - if (discount.paymentMode == SKProductDiscountPaymentModeFreeTrial) { - [FBSDKTypeUtility dictionary:eventParameters setObject:@"1" forKey:FBSDKAppEventParameterNameHasFreeTrial]; - } else { - [FBSDKTypeUtility dictionary:eventParameters setObject:@"0" forKey:FBSDKAppEventParameterNameHasFreeTrial]; - } - [FBSDKTypeUtility dictionary:eventParameters setObject:[self durationOfSubscriptionPeriod:discount.subscriptionPeriod] forKey:FBSDKAppEventParameterNameTrialPeriod]; - [FBSDKTypeUtility dictionary:eventParameters setObject:discount.price forKey:FBSDKAppEventParameterNameTrialPrice]; + if ([self isSubscription:product]) { + // subs inapp + [FBSDKTypeUtility dictionary:eventParameters setObject:[self durationOfSubscriptionPeriod:product.subscriptionPeriod] forKey:FBSDKAppEventParameterNameSubscriptionPeriod]; + [FBSDKTypeUtility dictionary:eventParameters setObject:@"subs" forKey:FBSDKAppEventParameterNameInAppPurchaseType]; + [FBSDKTypeUtility dictionary:eventParameters setObject:[self isStartTrial:transaction ofProduct:product] ? @"1" : @"0" forKey:FBSDKAppEventParameterNameIsStartTrial]; + // trial information for subs + SKProductDiscount *discount = product.introductoryPrice; + if (discount) { + if (discount.paymentMode == SKProductDiscountPaymentModeFreeTrial) { + [FBSDKTypeUtility dictionary:eventParameters setObject:@"1" forKey:FBSDKAppEventParameterNameHasFreeTrial]; + } else { + [FBSDKTypeUtility dictionary:eventParameters setObject:@"0" forKey:FBSDKAppEventParameterNameHasFreeTrial]; } - } else { - [FBSDKTypeUtility dictionary:eventParameters setObject:@"inapp" forKey:FBSDKAppEventParameterNameInAppPurchaseType]; + [FBSDKTypeUtility dictionary:eventParameters setObject:[self durationOfSubscriptionPeriod:discount.subscriptionPeriod] forKey:FBSDKAppEventParameterNameTrialPeriod]; + [FBSDKTypeUtility dictionary:eventParameters setObject:discount.price forKey:FBSDKAppEventParameterNameTrialPrice]; } + } else { + [FBSDKTypeUtility dictionary:eventParameters setObject:@"inapp" forKey:FBSDKAppEventParameterNameInAppPurchaseType]; } #endif return eventParameters; @@ -246,15 +243,13 @@ - (BOOL)isStartTrial:(SKPaymentTransaction *)transaction } } } - // introductory offer starting from iOS 11.2 - if (@available(iOS 11.2, *)) { - if (product.introductoryPrice - && product.introductoryPrice.paymentMode == SKProductDiscountPaymentModeFreeTrial) { - NSString *originalTransactionID = transaction.originalTransaction.transactionIdentifier; - // only consider the very first trial transaction as start trial - if (!originalTransactionID) { - return YES; - } + + if (product.introductoryPrice + && product.introductoryPrice.paymentMode == SKProductDiscountPaymentModeFreeTrial) { + NSString *originalTransactionID = transaction.originalTransaction.transactionIdentifier; + // only consider the very first trial transaction as start trial + if (!originalTransactionID) { + return YES; } } #endif @@ -264,18 +259,16 @@ - (BOOL)isStartTrial:(SKPaymentTransaction *)transaction - (nullable NSString *)durationOfSubscriptionPeriod:(id)subcriptionPeriod { #if !TARGET_OS_TV - if (@available(iOS 11.2, *)) { - if (subcriptionPeriod && [subcriptionPeriod isKindOfClass:SKProductSubscriptionPeriod.class]) { - SKProductSubscriptionPeriod *period = (SKProductSubscriptionPeriod *)subcriptionPeriod; - NSString *unit = nil; - switch (period.unit) { - case SKProductPeriodUnitDay: unit = @"D"; break; - case SKProductPeriodUnitWeek: unit = @"W"; break; - case SKProductPeriodUnitMonth: unit = @"M"; break; - case SKProductPeriodUnitYear: unit = @"Y"; break; - } - return [NSString stringWithFormat:@"P%lu%@", (unsigned long)period.numberOfUnits, unit]; + if (subcriptionPeriod && [subcriptionPeriod isKindOfClass:SKProductSubscriptionPeriod.class]) { + SKProductSubscriptionPeriod *period = (SKProductSubscriptionPeriod *)subcriptionPeriod; + NSString *unit = nil; + switch (period.unit) { + case SKProductPeriodUnitDay: unit = @"D"; break; + case SKProductPeriodUnitWeek: unit = @"W"; break; + case SKProductPeriodUnitMonth: unit = @"M"; break; + case SKProductPeriodUnitYear: unit = @"Y"; break; } + return [NSString stringWithFormat:@"P%lu%@", (unsigned long)period.numberOfUnits, unit]; } #endif return nil; diff --git a/FBSDKCoreKit/FBSDKCoreKit/FBSDKBridgeAPI.m b/FBSDKCoreKit/FBSDKCoreKit/FBSDKBridgeAPI.m index b9141d921b..4b67ae1ac9 100644 --- a/FBSDKCoreKit/FBSDKCoreKit/FBSDKBridgeAPI.m +++ b/FBSDKCoreKit/FBSDKCoreKit/FBSDKBridgeAPI.m @@ -27,7 +27,7 @@ #import "FBSDKLogger+Internal.h" #import "FBSDKURLScheme.h" -/// Specifies state of FBSDKAuthenticationSession (SFAuthenticationSession (iOS 11) and ASWebAuthenticationSession (iOS 12+)) +/// Specifies state of FBSDKAuthenticationSession typedef NS_ENUM(NSUInteger, FBSDKAuthenticationSession) { /// There is no active authentication session FBSDKAuthenticationSessionNone, @@ -62,8 +62,8 @@ @interface FBSDKBridgeAPI () *pendingRequest; @property (nonatomic) FBSDKBridgeAPIResponseBlock pendingRequestCompletionBlock; @property (nonatomic) id pendingURLOpen; -@property (nonatomic) id authenticationSession NS_AVAILABLE_IOS(11_0); -@property (nonatomic) FBSDKAuthenticationCompletionHandler authenticationSessionCompletionHandler NS_AVAILABLE_IOS(11_0); +@property (nonatomic) id authenticationSession; +@property (nonatomic) FBSDKAuthenticationCompletionHandler authenticationSessionCompletionHandler; @property (nonatomic) FBSDKAuthenticationSession authenticationSessionState; @property (nonatomic) BOOL expectingBackground; @property (nullable, nonatomic) SFSafariViewController *safariViewController; @@ -125,13 +125,7 @@ - (void)applicationDidBecomeActive:(UIApplication *)application } else if (_authenticationSession && _authenticationSessionState == FBSDKAuthenticationSessionCanceledBySystem) { [_authenticationSession cancel]; _authenticationSession = nil; - NSString *errorDomain; - if (@available(iOS 12.0, *)) { - errorDomain = @"com.apple.AuthenticationServices.WebAuthenticationSession"; - } else { - errorDomain = @"com.apple.SafariServices.Authentication"; - } - + NSString *errorDomain = @"com.apple.AuthenticationServices.WebAuthenticationSession"; NSError *error = [self.errorFactory errorWithDomain:errorDomain code:1 userInfo:nil diff --git a/FBSDKCoreKit/FBSDKCoreKit/Internal/Configuration/CoreKitComponents.swift b/FBSDKCoreKit/FBSDKCoreKit/Internal/Configuration/CoreKitComponents.swift index 5edcf4ae2e..cfad8b1732 100644 --- a/FBSDKCoreKit/FBSDKCoreKit/Internal/Configuration/CoreKitComponents.swift +++ b/FBSDKCoreKit/FBSDKCoreKit/Internal/Configuration/CoreKitComponents.swift @@ -494,13 +494,11 @@ final class CoreKitComponents { } var skAdNetworkReporter: (_AppEventsReporter & SKAdNetworkReporting)? - if #available(iOS 11.3, *) { - skAdNetworkReporter = _SKAdNetworkReporter( - graphRequestFactory: graphRequestFactory, - dataStore: UserDefaults.standard, - conversionValueUpdater: SKAdNetwork.self - ) - } + skAdNetworkReporter = _SKAdNetworkReporter( + graphRequestFactory: graphRequestFactory, + dataStore: UserDefaults.standard, + conversionValueUpdater: SKAdNetwork.self + ) let metaIndexer: _MetadataIndexing = _MetadataIndexer(userDataStore: userDataStore, swizzler: _Swizzler.self) let suggestedEventsIndexer: _SuggestedEventsIndexerProtocol = _SuggestedEventsIndexer( diff --git a/FBSDKCoreKit/FBSDKCoreKit/Internal/ServerConfiguration/FBSDKGateKeeperManager.m b/FBSDKCoreKit/FBSDKCoreKit/Internal/ServerConfiguration/FBSDKGateKeeperManager.m index dafc444a54..049780d3e7 100644 --- a/FBSDKCoreKit/FBSDKCoreKit/Internal/ServerConfiguration/FBSDKGateKeeperManager.m +++ b/FBSDKCoreKit/FBSDKCoreKit/Internal/ServerConfiguration/FBSDKGateKeeperManager.m @@ -187,11 +187,7 @@ + (void)processLoadRequestResponse:(id)result error:(NSError *)error NSString *defaultKey = [NSString stringWithFormat:FBSDK_GATEKEEPERS_USER_DEFAULTS_KEY, _settings.appID]; - #if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_11_0 NSData *data = [NSKeyedArchiver archivedDataWithRootObject:gateKeeper requiringSecureCoding:NO error:NULL]; - #else - NSData *data = [NSKeyedArchiver archivedDataWithRootObject:gateKeeper]; - #endif [self.store fb_setObject:data forKey:defaultKey]; } diff --git a/FBSDKCoreKit/FBSDKCoreKitTests/DefaultCoreKitComponentsTests.swift b/FBSDKCoreKit/FBSDKCoreKitTests/DefaultCoreKitComponentsTests.swift index f6cd1701a7..1748965ff9 100644 --- a/FBSDKCoreKit/FBSDKCoreKitTests/DefaultCoreKitComponentsTests.swift +++ b/FBSDKCoreKit/FBSDKCoreKitTests/DefaultCoreKitComponentsTests.swift @@ -625,7 +625,6 @@ final class DefaultCoreKitComponentsTests: XCTestCase { ) } - @available(iOS 11.3, *) func testSKAdNetworkReporter() throws { let reporter = try XCTUnwrap( components.skAdNetworkReporter as? _SKAdNetworkReporter, diff --git a/FBSDKCoreKit/FBSDKCoreKitTests/DynamicFrameworkLoaderTests.swift b/FBSDKCoreKit/FBSDKCoreKitTests/DynamicFrameworkLoaderTests.swift index 923bef9203..d1ec11e8f0 100644 --- a/FBSDKCoreKit/FBSDKCoreKitTests/DynamicFrameworkLoaderTests.swift +++ b/FBSDKCoreKit/FBSDKCoreKitTests/DynamicFrameworkLoaderTests.swift @@ -15,7 +15,6 @@ import Security import Social import XCTest -@available(iOS 12.0, *) final class DynamicFrameworkLoaderTests: XCTestCase { #if BUCK diff --git a/FBSDKCoreKit/FBSDKCoreKitTests/Interfaces/FBSDKBridgeAPI+Testing.h b/FBSDKCoreKit/FBSDKCoreKitTests/Interfaces/FBSDKBridgeAPI+Testing.h index 97b657e9ff..094898a618 100644 --- a/FBSDKCoreKit/FBSDKCoreKitTests/Interfaces/FBSDKBridgeAPI+Testing.h +++ b/FBSDKCoreKit/FBSDKCoreKitTests/Interfaces/FBSDKBridgeAPI+Testing.h @@ -31,7 +31,7 @@ NS_SWIFT_NAME(AuthenticationSessionHandling) @end -/// Specifies state of FBSDKAuthenticationSession (SFAuthenticationSession (iOS 11) and ASWebAuthenticationSession (iOS 12+)) +/// Specifies state of FBSDKAuthenticationSession typedef NS_ENUM(NSUInteger, FBSDKAuthenticationSession) { /// There is no active authentication session FBSDKAuthenticationSessionNone, diff --git a/FBSDKCoreKit/FBSDKCoreKitTests/Internal/AppEvents/AppEventsTests.swift b/FBSDKCoreKit/FBSDKCoreKitTests/Internal/AppEvents/AppEventsTests.swift index 8044c34d60..2e26888745 100644 --- a/FBSDKCoreKit/FBSDKCoreKitTests/Internal/AppEvents/AppEventsTests.swift +++ b/FBSDKCoreKit/FBSDKCoreKitTests/Internal/AppEvents/AppEventsTests.swift @@ -1194,19 +1194,17 @@ final class AppEventsTests: XCTestCase { } func testLogEventWillRecordAndUpdateWithSKAdNetworkReporter() { - if #available(iOS 11.3, *) { - appEvents.logEvent(eventName, valueToSum: purchaseAmount) - XCTAssertEqual( - eventName.rawValue, - skAdNetworkReporter.capturedEvent, - "Logging a event should invoke the SKAdNetwork reporter with the expected event name" - ) - XCTAssertEqual( - purchaseAmount, - skAdNetworkReporter.capturedValue?.doubleValue, - "Logging a event should invoke the SKAdNetwork reporter with the expected event value" - ) - } + appEvents.logEvent(eventName, valueToSum: purchaseAmount) + XCTAssertEqual( + eventName.rawValue, + skAdNetworkReporter.capturedEvent, + "Logging a event should invoke the SKAdNetwork reporter with the expected event name" + ) + XCTAssertEqual( + purchaseAmount, + skAdNetworkReporter.capturedValue?.doubleValue, + "Logging a event should invoke the SKAdNetwork reporter with the expected event value" + ) validateAEMReporterCalled( eventName: eventName, currency: nil, @@ -1456,23 +1454,21 @@ final class AppEventsTests: XCTestCase { appEvents.fetchServerConfiguration(nil) appEventsConfigurationProvider.firstCapturedBlock?() serverConfigurationProvider.capturedCompletionBlock?(nil, nil) - if #available(iOS 11.3, *) { - featureManager.completeCheck( - forFeature: .skAdNetwork, - with: true - ) - featureManager.completeCheck( - forFeature: .skAdNetworkConversionValue, - with: true - ) - XCTAssertTrue( - skAdNetworkReporter.enableWasCalled, - """ - Fetching a configuration should enable SKAdNetworkReporter when SKAdNetworkReport \ - and SKAdNetworkConversionValue are enabled - """ - ) - } + featureManager.completeCheck( + forFeature: .skAdNetwork, + with: true + ) + featureManager.completeCheck( + forFeature: .skAdNetworkConversionValue, + with: true + ) + XCTAssertTrue( + skAdNetworkReporter.enableWasCalled, + """ + Fetching a configuration should enable SKAdNetworkReporter when SKAdNetworkReport \ + and SKAdNetworkConversionValue are enabled + """ + ) } func testFetchingConfigurationDoesNotEnableSKAdNetworkReporterWhenSKAdNetworkConversionValueIsDisabled() { @@ -1480,20 +1476,18 @@ final class AppEventsTests: XCTestCase { appEvents.fetchServerConfiguration(nil) appEventsConfigurationProvider.firstCapturedBlock?() serverConfigurationProvider.capturedCompletionBlock?(nil, nil) - if #available(iOS 11.3, *) { - featureManager.completeCheck( - forFeature: .skAdNetwork, - with: true - ) - featureManager.completeCheck( - forFeature: .skAdNetworkConversionValue, - with: false - ) - XCTAssertFalse( - skAdNetworkReporter.enableWasCalled, - "Fetching a configuration should NOT enable SKAdNetworkReporter if SKAdNetworkConversionValue is disabled" - ) - } + featureManager.completeCheck( + forFeature: .skAdNetwork, + with: true + ) + featureManager.completeCheck( + forFeature: .skAdNetworkConversionValue, + with: false + ) + XCTAssertFalse( + skAdNetworkReporter.enableWasCalled, + "Fetching a configuration should NOT enable SKAdNetworkReporter if SKAdNetworkConversionValue is disabled" + ) } func testFetchingConfigurationNotIncludingSKAdNetworkIfSKAdNetworkReportDisabled() { diff --git a/FBSDKCoreKit/FBSDKCoreKitTests/Internal/Helpers/SampleProducts.swift b/FBSDKCoreKit/FBSDKCoreKitTests/Internal/Helpers/SampleProducts.swift index 64bf0815eb..4b27de1993 100644 --- a/FBSDKCoreKit/FBSDKCoreKitTests/Internal/Helpers/SampleProducts.swift +++ b/FBSDKCoreKit/FBSDKCoreKitTests/Internal/Helpers/SampleProducts.swift @@ -6,7 +6,6 @@ * LICENSE file in the root directory of this source tree. */ -@available(iOS 11.2, *) enum SampleProducts { static func createValid() -> TestProduct { TestProduct() diff --git a/FBSDKCoreKit/FBSDKCoreKitTests/Internal/Helpers/TestProduct.swift b/FBSDKCoreKit/FBSDKCoreKitTests/Internal/Helpers/TestProduct.swift index 90b067353f..89377c8a7e 100644 --- a/FBSDKCoreKit/FBSDKCoreKitTests/Internal/Helpers/TestProduct.swift +++ b/FBSDKCoreKit/FBSDKCoreKitTests/Internal/Helpers/TestProduct.swift @@ -6,7 +6,6 @@ * LICENSE file in the root directory of this source tree. */ -@available(iOS 11.2, *) final class TestProduct: SKProduct { static let title = "Product title" static let productDescription = "Some description" diff --git a/FBSDKCoreKit/FBSDKCoreKitTests/Internal/Helpers/TestProductDiscount.swift b/FBSDKCoreKit/FBSDKCoreKitTests/Internal/Helpers/TestProductDiscount.swift index 13d10a7b8b..0ba4a92fb9 100644 --- a/FBSDKCoreKit/FBSDKCoreKitTests/Internal/Helpers/TestProductDiscount.swift +++ b/FBSDKCoreKit/FBSDKCoreKitTests/Internal/Helpers/TestProductDiscount.swift @@ -6,7 +6,6 @@ * LICENSE file in the root directory of this source tree. */ -@available(iOS 11.2, *) final class TestProductDiscount: SKProductDiscount { let stubbedIdentifier: String let stubbedPaymentMode: PaymentMode diff --git a/FBSDKCoreKit/FBSDKCoreKitTests/Internal/Helpers/TestProductSubscriptionPeriod.swift b/FBSDKCoreKit/FBSDKCoreKitTests/Internal/Helpers/TestProductSubscriptionPeriod.swift index ca520e8976..90734aaaf2 100644 --- a/FBSDKCoreKit/FBSDKCoreKitTests/Internal/Helpers/TestProductSubscriptionPeriod.swift +++ b/FBSDKCoreKit/FBSDKCoreKitTests/Internal/Helpers/TestProductSubscriptionPeriod.swift @@ -6,7 +6,6 @@ * LICENSE file in the root directory of this source tree. */ -@available(iOS 11.2, *) final class TestProductSubscriptionPeriod: SKProductSubscriptionPeriod { let stubbedNumberOfUnits: Int