diff --git a/.jazzy.yaml b/.jazzy.yaml
index c64b597b26..68ea448951 100644
--- a/.jazzy.yaml
+++ b/.jazzy.yaml
@@ -2,9 +2,9 @@ clean: true
author: RevenueCat
author_url: https://revenuecat.com
sdk: iphonesimulator
-module_version: 4.17.7
+module_version: 4.17.8
github_url: https://github.com/revenuecat/purchases-ios
-github_file_prefix: https://github.com/revenuecat/purchases-ios/tree/4.17.7
+github_file_prefix: https://github.com/revenuecat/purchases-ios/tree/4.17.8
output: generated_docs
include:
- "Sources/**/*"
diff --git a/.version b/.version
index 87fe993c5e..cda47759e9 100644
--- a/.version
+++ b/.version
@@ -1 +1 @@
-4.17.7
+4.17.8
diff --git a/CHANGELOG.latest.md b/CHANGELOG.latest.md
index 147e4a9eb0..5eb849cc63 100644
--- a/CHANGELOG.latest.md
+++ b/CHANGELOG.latest.md
@@ -1,4 +1,17 @@
+### Bugfixes
+* `DispatchTimeInterval` & `Date`: avoid 32-bit overflows, fix `watchOS` crashes (#2342) via NachoSoto (@NachoSoto)
+* Fix issue with missing subscriber attributes if set after login but before login callback (#2313) via @tonidero
+
+### Performance Improvements
+* `AppleReceipt.mostRecentActiveSubscription`: performance optimization (#2332) via NachoSoto (@NachoSoto)
+
### Other Changes
-* Fixed `Bundle: Sendable` conformance (#2301)
-* Fixed `PurchasesOrchestrator` compilation error on Xcode 14.3 beta 1 (#2292) via NachoSoto (@NachoSoto)
-* Clarifies error messages for StoreKit 1 bugs (#2294)
\ No newline at end of file
+* `CI`: also run tests on `watchOS` (#2340) via NachoSoto (@NachoSoto)
+* `RELEASING.md`: added GitHub rate limiting parameter (#2336) via NachoSoto (@NachoSoto)
+* Add additional logging on init (#2324) via Cody Kerns (@codykerns)
+* Replace `iff` with `if and only if` (#2323) via @aboedo
+* Fix typo in log (#2315) via @nickkohrn
+* `Purchases.restorePurchases`: added docstring about successful results (#2316) via NachoSoto (@NachoSoto)
+* `RELEASING.md`: fixed hotfix instructions (#2304) via NachoSoto (@NachoSoto)
+* `PurchaseTester`: fixed leak when reconfiguring `Purchases` (#2311) via NachoSoto (@NachoSoto)
+* `ProductsFetcherSK2`: add underlying error to description (#2281) via Chris Vasselli (@chrisvasselli)
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5bb1ac8296..1b2b69d9b2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,21 @@
+## 4.17.8
+### Bugfixes
+* `DispatchTimeInterval` & `Date`: avoid 32-bit overflows, fix `watchOS` crashes (#2342) via NachoSoto (@NachoSoto)
+* Fix issue with missing subscriber attributes if set after login but before login callback (#2313) via @tonidero
+
+### Performance Improvements
+* `AppleReceipt.mostRecentActiveSubscription`: performance optimization (#2332) via NachoSoto (@NachoSoto)
+
+### Other Changes
+* `CI`: also run tests on `watchOS` (#2340) via NachoSoto (@NachoSoto)
+* `RELEASING.md`: added GitHub rate limiting parameter (#2336) via NachoSoto (@NachoSoto)
+* Add additional logging on init (#2324) via Cody Kerns (@codykerns)
+* Replace `iff` with `if and only if` (#2323) via @aboedo
+* Fix typo in log (#2315) via @nickkohrn
+* `Purchases.restorePurchases`: added docstring about successful results (#2316) via NachoSoto (@NachoSoto)
+* `RELEASING.md`: fixed hotfix instructions (#2304) via NachoSoto (@NachoSoto)
+* `PurchaseTester`: fixed leak when reconfiguring `Purchases` (#2311) via NachoSoto (@NachoSoto)
+* `ProductsFetcherSK2`: add underlying error to description (#2281) via Chris Vasselli (@chrisvasselli)
## 4.17.7
### Other Changes
* Fixed `Bundle: Sendable` conformance (#2301)
diff --git a/RevenueCat.podspec b/RevenueCat.podspec
index 623c9a290c..e620fe1422 100644
--- a/RevenueCat.podspec
+++ b/RevenueCat.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "RevenueCat"
- s.version = "4.17.7"
+ s.version = "4.17.8"
s.summary = "Subscription and in-app-purchase backend service."
s.description = <<-DESC
diff --git a/Sources/Info.plist b/Sources/Info.plist
index a325b53617..9b27f81fda 100644
--- a/Sources/Info.plist
+++ b/Sources/Info.plist
@@ -17,7 +17,7 @@
SKProduct assigned to this package. https://developer.apple.com/documentation/storekit/skproduct
-@property (nonatomic, readonly, strong) SKProduct * _Nonnull product SWIFT_AVAILABILITY(maccatalyst,obsoleted=1,message="'product' has been renamed to 'storeProduct': Use StoreProduct instead") SWIFT_AVAILABILITY(macos,obsoleted=1,message="'product' has been renamed to 'storeProduct': Use StoreProduct instead") SWIFT_AVAILABILITY(watchos,obsoleted=1,message="'product' has been renamed to 'storeProduct': Use StoreProduct instead") SWIFT_AVAILABILITY(tvos,obsoleted=1,message="'product' has been renamed to 'storeProduct': Use StoreProduct instead") SWIFT_AVAILABILITY(ios,obsoleted=1,message="'product' has been renamed to 'storeProduct': Use StoreProduct instead");
-@end
-
@interface RCPackage (SWIFT_EXTENSION(RevenueCat))
/// \param packageType A PackageType.
@@ -1284,6 +1276,13 @@ SWIFT_CLASS_NAMED("Package")
+ (enum RCPackageType)packageTypeFrom:(NSString * _Nonnull)string SWIFT_WARN_UNUSED_RESULT;
@end
+@class SKProduct;
+
+@interface RCPackage (SWIFT_EXTENSION(RevenueCat))
+/// SKProduct assigned to this package. https://developer.apple.com/documentation/storekit/skproduct
+@property (nonatomic, readonly, strong) SKProduct * _Nonnull product SWIFT_AVAILABILITY(maccatalyst,obsoleted=1,message="'product' has been renamed to 'storeProduct': Use StoreProduct instead") SWIFT_AVAILABILITY(macos,obsoleted=1,message="'product' has been renamed to 'storeProduct': Use StoreProduct instead") SWIFT_AVAILABILITY(watchos,obsoleted=1,message="'product' has been renamed to 'storeProduct': Use StoreProduct instead") SWIFT_AVAILABILITY(tvos,obsoleted=1,message="'product' has been renamed to 'storeProduct': Use StoreProduct instead") SWIFT_AVAILABILITY(ios,obsoleted=1,message="'product' has been renamed to 'storeProduct': Use StoreProduct instead");
+@end
+
/// Enumeration of all possible Package types, as configured on the package.
///
Purchases/syncPurchases(completion:) if you need to restore transactions programmatically.
+/// warning:
+/// Receiving a CustomerInfo instead of an error does not imply that the user has any
+/// entitlements, simply that the process was successful. You must verify the CustomerInfo/entitlements
+/// to confirm that they are active.
- (void)restorePurchasesWithCompletion:(void (^ _Nullable)(RCCustomerInfo * _Nullable, NSError * _Nullable))completion;
/// This method will post all purchases associated with the current App Store account to RevenueCat and become
/// associated with the current appUserID. If the receipt is being used by an existing user, the current
@@ -1886,6 +1889,10 @@ SWIFT_PROTOCOL_NAMED("PurchasesType")
/// This may force your users to enter the App Store password so should only be performed on request of
/// the user. Typically with a button in settings or near your purchase UI. Use
/// Purchases/syncPurchases(completion:) if you need to restore transactions programmatically.
+/// warning:
+/// Receiving a CustomerInfo instead of an error does not imply that the user has any
+/// entitlements, simply that the process was successful. You must verify the CustomerInfo/entitlements
+/// to confirm that they are active.
- (void)restorePurchasesWithCompletionHandler:(void (^ _Nonnull)(RCCustomerInfo * _Nullable, NSError * _Nullable))completionHandler SWIFT_AVAILABILITY(watchos,introduced=6.2) SWIFT_AVAILABILITY(tvos,introduced=13.0) SWIFT_AVAILABILITY(macos,introduced=10.15) SWIFT_AVAILABILITY(ios,introduced=13.0);
/// This method will post all purchases associated with the current App Store account to RevenueCat and
/// become associated with the current appUserID.
@@ -2296,6 +2303,33 @@ SWIFT_CLASS_NAMED("PlatformInfo")
+@interface RCPurchases (SWIFT_EXTENSION(RevenueCat))
+/// Enable debug logging. Useful for debugging issues with the lovely team @RevenueCat.
+SWIFT_CLASS_PROPERTY(@property (nonatomic, class) BOOL debugLogsEnabled SWIFT_DEPRECATED_MSG("use Purchases.logLevel instead");)
++ (BOOL)debugLogsEnabled SWIFT_WARN_UNUSED_RESULT;
++ (void)setDebugLogsEnabled:(BOOL)newValue;
+/// Deprecated
+@property (nonatomic) BOOL allowSharingAppStoreAccount SWIFT_DEPRECATED_MSG("Configure behavior through the RevenueCat dashboard instead");
+/// Deprecated
++ (void)addAttributionData:(NSDictionaryAttributionNetwork for supported
+/// networks.
+///
+/// \param networkUserId User Id that should be sent to the network. Default is the current App User Id.
+///
++ (void)addAttributionData:(NSDictionaryConfiguration.
/// The instance will be set as a singleton.
@@ -2389,33 +2423,6 @@ SWIFT_CLASS_NAMED("PlatformInfo")
@end
-@interface RCPurchases (SWIFT_EXTENSION(RevenueCat))
-/// Enable debug logging. Useful for debugging issues with the lovely team @RevenueCat.
-SWIFT_CLASS_PROPERTY(@property (nonatomic, class) BOOL debugLogsEnabled SWIFT_DEPRECATED_MSG("use Purchases.logLevel instead");)
-+ (BOOL)debugLogsEnabled SWIFT_WARN_UNUSED_RESULT;
-+ (void)setDebugLogsEnabled:(BOOL)newValue;
-/// Deprecated
-@property (nonatomic) BOOL allowSharingAppStoreAccount SWIFT_DEPRECATED_MSG("Configure behavior through the RevenueCat dashboard instead");
-/// Deprecated
-+ (void)addAttributionData:(NSDictionaryAttributionNetwork for supported
-/// networks.
-///
-/// \param networkUserId User Id that should be sent to the network. Default is the current App User Id.
-///
-+ (void)addAttributionData:(NSDictionaryPurchasesReceiptParser/default:
@@ -2774,7 +2781,6 @@ SWIFT_CLASS("_TtC10RevenueCat22PurchasesReceiptParser")
-
@interface PurchasesReceiptParser (SWIFT_EXTENSION(RevenueCat))
- (BOOL)receiptHasTransactionsWithReceiptData:(NSData * _Nonnull)receiptData SWIFT_WARN_UNUSED_RESULT;
@end
@@ -2790,6 +2796,7 @@ SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly, strong, getter=defau
+
SWIFT_CLASS("_TtC10RevenueCat21RCPurchasesErrorUtils") SWIFT_AVAILABILITY(maccatalyst,obsoleted=1) SWIFT_AVAILABILITY(macos,obsoleted=1) SWIFT_AVAILABILITY(watchos,obsoleted=1) SWIFT_AVAILABILITY(tvos,obsoleted=1) SWIFT_AVAILABILITY(ios,obsoleted=1)
@interface RCPurchasesErrorUtils : NSObject
- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
@@ -2889,7 +2896,7 @@ SWIFT_CLASS_NAMED("StoreProduct")
@property (nonatomic, readonly, copy) NSString * _Nullable currencyCode;
@property (nonatomic, readonly, copy) NSString * _Nonnull localizedPriceString;
@property (nonatomic, readonly, copy) NSString * _Nonnull productIdentifier;
-@property (nonatomic, readonly) BOOL isFamilyShareable SWIFT_AVAILABILITY(watchos,introduced=8.0) SWIFT_AVAILABILITY(tvos,introduced=14.0) SWIFT_AVAILABILITY(macos,introduced=11.0) SWIFT_AVAILABILITY(ios,introduced=14.0);
+@property (nonatomic, readonly) BOOL isFamilyShareable SWIFT_AVAILABILITY(watchos,introduced=7.0) SWIFT_AVAILABILITY(tvos,introduced=14.0) SWIFT_AVAILABILITY(macos,introduced=11.0) SWIFT_AVAILABILITY(ios,introduced=14.0);
@property (nonatomic, readonly, copy) NSString * _Nullable subscriptionGroupIdentifier SWIFT_AVAILABILITY(watchos,introduced=6.2) SWIFT_AVAILABILITY(macos,introduced=10.14) SWIFT_AVAILABILITY(tvos,introduced=12.0) SWIFT_AVAILABILITY(maccatalyst,introduced=13.0) SWIFT_AVAILABILITY(ios,introduced=12.0);
@property (nonatomic, readonly, strong) NSNumberFormatter * _Nullable priceFormatter;
@property (nonatomic, readonly, strong) RCSubscriptionPeriod * _Nullable subscriptionPeriod SWIFT_AVAILABILITY(watchos,introduced=6.2) SWIFT_AVAILABILITY(tvos,introduced=11.2) SWIFT_AVAILABILITY(macos,introduced=10.13.2) SWIFT_AVAILABILITY(ios,introduced=11.2);
@@ -2946,6 +2953,13 @@ typedef SWIFT_ENUM_NAMED(NSInteger, RCStoreProductType, "ProductType", open) {
@property (nonatomic, readonly, copy) NSLocale * _Nonnull priceLocale SWIFT_AVAILABILITY(macos,unavailable,message="Use localizedPriceString instead") SWIFT_AVAILABILITY(watchos,unavailable,message="Use localizedPriceString instead") SWIFT_AVAILABILITY(tvos,unavailable,message="Use localizedPriceString instead") SWIFT_AVAILABILITY(ios,unavailable,message="Use localizedPriceString instead");
@end
+
+@interface RCStoreProduct (SWIFT_EXTENSION(RevenueCat))
+- (nonnull instancetype)initWithSk1Product:(SKProduct * _Nonnull)sk1Product;
+/// Returns the SKProduct if this StoreProduct represents a StoreKit.SKProduct.
+@property (nonatomic, readonly, strong) SKProduct * _Nullable sk1Product;
+@end
+
@class NSDecimalNumber;
@interface RCStoreProduct (SWIFT_EXTENSION(RevenueCat))
@@ -2972,13 +2986,6 @@ typedef SWIFT_ENUM_NAMED(NSInteger, RCStoreProductType, "ProductType", open) {
@property (nonatomic, readonly, copy) NSString * _Nullable localizedIntroductoryPriceString;
@end
-
-@interface RCStoreProduct (SWIFT_EXTENSION(RevenueCat))
-- (nonnull instancetype)initWithSk1Product:(SKProduct * _Nonnull)sk1Product;
-/// Returns the SKProduct if this StoreProduct represents a StoreKit.SKProduct.
-@property (nonatomic, readonly, strong) SKProduct * _Nullable sk1Product;
-@end
-
enum RCPaymentMode : NSInteger;
enum RCDiscountType : NSInteger;
@@ -3136,13 +3143,13 @@ typedef SWIFT_ENUM_NAMED(NSInteger, RCSubscriptionPeriodUnit, "Unit", open) {
@interface RCSubscriptionPeriod (SWIFT_EXTENSION(RevenueCat))
-@property (nonatomic, readonly, copy) NSString * _Nonnull debugDescription;
+/// The number of units per subscription period
+@property (nonatomic, readonly) NSInteger numberOfUnits SWIFT_AVAILABILITY(macos,unavailable,message="'numberOfUnits' has been renamed to 'value'") SWIFT_AVAILABILITY(watchos,unavailable,message="'numberOfUnits' has been renamed to 'value'") SWIFT_AVAILABILITY(tvos,unavailable,message="'numberOfUnits' has been renamed to 'value'") SWIFT_AVAILABILITY(ios,unavailable,message="'numberOfUnits' has been renamed to 'value'");
@end
@interface RCSubscriptionPeriod (SWIFT_EXTENSION(RevenueCat))
-/// The number of units per subscription period
-@property (nonatomic, readonly) NSInteger numberOfUnits SWIFT_AVAILABILITY(macos,unavailable,message="'numberOfUnits' has been renamed to 'value'") SWIFT_AVAILABILITY(watchos,unavailable,message="'numberOfUnits' has been renamed to 'value'") SWIFT_AVAILABILITY(tvos,unavailable,message="'numberOfUnits' has been renamed to 'value'") SWIFT_AVAILABILITY(ios,unavailable,message="'numberOfUnits' has been renamed to 'value'");
+@property (nonatomic, readonly, copy) NSString * _Nonnull debugDescription;
@end
diff --git a/Tests/UnitTests/Info.plist b/Tests/UnitTests/Info.plist
index e87b027bb3..b76bd42034 100644
--- a/Tests/UnitTests/Info.plist
+++ b/Tests/UnitTests/Info.plist
@@ -15,7 +15,7 @@