Skip to content

Commit

Permalink
Merge pull request #116 from superwall-me/develop
Browse files Browse the repository at this point in the history
3.0.0-beta.7
  • Loading branch information
yusuftor committed Mar 9, 2023
2 parents ef4e17b + e9a6661 commit 58f17de
Show file tree
Hide file tree
Showing 33 changed files with 348 additions and 250 deletions.
16 changes: 15 additions & 1 deletion CHANGELOG.md
Expand Up @@ -2,6 +2,21 @@

The changelog for `SuperwallKit`. Also see the [releases](https://github.com/superwall-me/Superwall-iOS/releases) on GitHub.

## 3.0.0-beta.7

### Breaking Changes

- Changes Objective-C method `getTrackInfo` to `getTrackResult` to be in line with the Swift API.
- Removes the error case from the `TrackResult` and adds in `userIsSubscribed` and `paywallNotAvailable` cases.
- Moves main actor conformance to functions of PurchaseController protocol rather than the whole protocol.
- Changes Objective-C method `setUserAttributesDictionary(_:)` to `setUserAttributes(_:)`.

### Fixes

- Makes `NetworkEnvironment` Objective-C compatible.
- Fixes an issue where a manually dismissed modally presented paywall wouldn't properly dismiss.
- Fixes race condition when calling identify and tracking a paywall.

## 3.0.0-beta.6

### Breaking Changes
Expand All @@ -10,7 +25,6 @@ The changelog for `SuperwallKit`. Also see the [releases](https://github.com/sup
- `reset` is no longer an async function.
- `presentedViewController` and `latestPaywallInfo` no longer restricted to the main actor.
- Removes `localizationOverride(localeIdentifier:)` and replaces it with the `SuperwallOption` `localeIdentifier`. You set this on configure.
- `setUserAttributes(_:)` is now an async function. It always was async under the hood but this makes it more explicit and helps you avoid race conditions.
- Removes delegate from `configure`. You now set the delegate via `Superwall.shared.delegate`.
- Removes `presenter` introduced in beta 5.
- Removes ASN1Swift as a package dependency.
Expand Down
@@ -1,25 +1,14 @@
{
"object": {
"pins": [
{
"package": "ASN1Swift",
"repositoryURL": "https://github.com/tikhop/ASN1Swift",
"state": {
"branch": null,
"revision": "b53bee03a942623db25afc5bfb80227b2cb3b425",
"version": "1.2.4"
}
},
{
"package": "RevenueCat",
"repositoryURL": "https://github.com/RevenueCat/purchases-ios.git",
"state": {
"branch": null,
"revision": "390073e0dec72f2a4aabb1888ceda46a059808e5",
"version": "4.17.3"
}
"pins" : [
{
"identity" : "purchases-ios",
"kind" : "remoteSourceControl",
"location" : "https://github.com/RevenueCat/purchases-ios.git",
"state" : {
"revision" : "390073e0dec72f2a4aabb1888ceda46a059808e5",
"version" : "4.17.3"
}
]
},
"version": 1
}
],
"version" : 2
}

This file was deleted.

Expand Up @@ -91,7 +91,7 @@ - (nullable NSString *)name {

- (void)setName:(nullable NSString *)name {
id userAttributeFirstName = name ? : [NSNull null];
[[Superwall sharedInstance] setUserAttributesDictionary:@{ kUserAttributesFirstNameKey : userAttributeFirstName }];
[[Superwall sharedInstance] setUserAttributes:@{ kUserAttributesFirstNameKey : userAttributeFirstName }];
}

#pragma mark - Public Methods
Expand Down Expand Up @@ -139,7 +139,7 @@ - (void)restorePurchasesWithCompletion:(void (^ _Nonnull)(BOOL))completion {

- (void)didTrackSuperwallEventInfo:(SWKSuperwallEventInfo *)info {
NSLog(@"Analytics event called %@", @(info.event));

// Uncomment the following if you want to track the different analytics events received from the paywall:

// switch (info.event) {
Expand Down
Expand Up @@ -90,7 +90,7 @@ final class TrackEventViewController: UIViewController {
// The below function gives an example of how to track an event using Combine publishers:
/*
func trackEventUsingCombine() {
cancellable = Superwall
cancellable = Superwall.shared
.publisher(forEvent: "MyEvent")
.sink { paywallState in
switch paywallState {
Expand All @@ -113,10 +113,13 @@ final class TrackEventViewController: UIViewController {
print("The user is in a holdout group, with experiment id: \(experiment.id), group id: \(experiment.groupId), paywall id: \(experiment.variant.paywallId ?? "")")
case .eventNotFound:
print("The event wasn't found in a campaign on the dashboard.")
case .userIsSubscribed:
print("The user is subscribed.")
case .error(let error):
print("Failed to present paywall. Consider a native paywall fallback", error)
}
}
}
}*/
}
*/
}
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -76,7 +76,7 @@ The preferred installation method is with [Swift Package Manager](https://swift.
To include the *Superwall* SDK in your app, add the following to your Podfile:

```
pod 'SuperwallKit', '3.0.0-beta.6'
pod 'SuperwallKit', '3.0.0-beta.7'
```

If you don't want to use the v3 beta, you'll need to add this instead:
Expand Down
2 changes: 1 addition & 1 deletion Sources/SuperwallKit/Config/ConfigManager.swift
Expand Up @@ -259,7 +259,7 @@ class ConfigManager {
/// Preloads paywalls referenced by triggers.
private func preloadPaywalls(withIdentifiers paywallIdentifiers: Set<String>) {
for identifier in paywallIdentifiers {
Task {
Task { [unowned self] in
let request = factory.makePaywallRequest(
eventData: nil,
responseIdentifiers: .init(paywallId: identifier),
Expand Down
2 changes: 1 addition & 1 deletion Sources/SuperwallKit/Config/Options/SuperwallOptions.swift
Expand Up @@ -20,7 +20,7 @@ public final class SuperwallOptions: NSObject {
/// **WARNING**: The different network environments that the SDK should use.
/// Only use this enum to set ``SuperwallOptions/networkEnvironment-swift.property``
/// if told so explicitly by the Superwall team.
public enum NetworkEnvironment {
public enum NetworkEnvironment: Int {
/// Default: Uses the standard latest environment.
case release
/// **WARNING**: Uses a release candidate environment. This is not meant for a production environment.
Expand Down
Expand Up @@ -20,7 +20,6 @@ import StoreKit
///
/// To learn how to implement the ``PurchaseController`` in your app
/// and best practices, see <doc:AdvancedConfiguration>.
@MainActor
public protocol PurchaseController: AnyObject {
/// Called when the user initiates purchasing of a product.
///
Expand All @@ -31,6 +30,7 @@ public protocol PurchaseController: AnyObject {
///
/// - Returns: A``PurchaseResult`` object, which is the result of your purchase logic.
/// **Note**: Make sure you handle all cases of ``PurchaseResult``.
@MainActor
func purchase(product: SKProduct) async -> PurchaseResult

/// Called when the user initiates a restore.
Expand All @@ -39,5 +39,6 @@ public protocol PurchaseController: AnyObject {
/// and return its result.
///
/// - Returns: A boolean that's `true` if the user's purchases were restored or `false` if they weren't.
@MainActor
func restorePurchases() async -> Bool
}
Expand Up @@ -20,7 +20,6 @@ import StoreKit
///
/// To learn how to implement the ``PurchaseControllerObjc`` in your app
/// and best practices, see <doc:AdvancedConfiguration>.
@MainActor
@objc(SWKPurchaseController)
public protocol PurchaseControllerObjc: AnyObject {
/// Called when the user initiates purchasing of a product.
Expand All @@ -33,6 +32,7 @@ public protocol PurchaseControllerObjc: AnyObject {
/// Call this with the result of your purchase logic. When you pass a `.failed` result, make sure you also pass
/// the error.
/// **Note:** Make sure you handle all cases of ``PurchaseResult``.
@MainActor
@objc func purchase(
product: SKProduct,
completion: @escaping (PurchaseResultObjc, Error?) -> Void
Expand All @@ -45,5 +45,6 @@ public protocol PurchaseControllerObjc: AnyObject {
///
/// - Parameters:
/// - completion: Call the completion with `true` if the user's purchases were restored or `false` if they weren't.
@MainActor
@objc func restorePurchases(completion: @escaping (Bool) -> Void)
}
2 changes: 1 addition & 1 deletion Sources/SuperwallKit/Delegate/SuperwallDelegateObjc.swift
Expand Up @@ -7,7 +7,7 @@

import Foundation

/// The objective-c only delegate protocol that handles Superwall lifecycle events.
/// Objective-C-only delegate protocol that handles Superwall lifecycle events.
///
/// The delegate methods receive callbacks from the SDK in response to certain events that happen on the paywall.
///
Expand Down
Expand Up @@ -7,7 +7,7 @@ Use options and custom subscription-related logic for more control over the SDK.
By default, Superwall handles all subscription-related logic. However, if you're using RevenueCat, or you just want more control, you can return a ``PurchaseController`` when configuring the SDK via
``Superwall/configure(apiKey:purchaseController:options:completion:)-52tke``. In addition, you can customise aspects of the SDK by passing in a ``SuperwallOptions`` object on configure.

## Creating a Subscription Controller
## Creating a Purchase Controller

A purchase controller handles purchasing and restoring via protocol methods that you implement. You pass in your purchase controller when configuring the SDK:

Expand Down
Expand Up @@ -37,13 +37,16 @@ The ``Superwall`` class is used to access all the features of the SDK. Before us
- ``track(event:params:)``
- ``track(event:onSkip:onPresent:onDismiss:)``
- ``track(event:params:onSkip:onPresent:onDismiss:)``
- ``getTrackResult(forEvent:params:)``
- ``getTrackResult(forEvent:params:completion:)``
- ``getTrackInfo(forEvent:params:)``
- ``publisher(forEvent:params:paywallOverrides:)``
- ``getTrackResult(forEvent:params:)-1qexk``
- ``getTrackResult(forEvent:params:completion:)``
- ``getTrackResult(forEvent:params:)-2j7qn``
- ``getTrackResult(forEvent:)``
- ``dismiss()-844a9``
- ``dismiss()-4objm``
- ``dismiss(completion:)``
- ``TrackResult``
- ``TrackResultObjc``
- ``PaywallInfo``
- ``SuperwallEvent``
- ``SuperwallEventObjc``
Expand All @@ -62,8 +65,8 @@ The ``Superwall`` class is used to access all the features of the SDK. Before us
- ``identify(userId:)``
- ``IdentityOptions``
- ``reset()``
- ``setUserAttributes(_:)``
- ``setUserAttributesDictionary(_:)``
- ``setUserAttributes(_:)-1wql2``
- ``setUserAttributes(_:)-8jken``
- ``removeUserAttributes(_:)``
- ``userAttributes``

Expand Down
Expand Up @@ -6,7 +6,7 @@ Set user attributes for use in your paywalls and the dashboard.

You can display information about the user on the paywall by setting user attributes.

You do this by passing a `[String: Any?]` dictionary of attributes to ``Superwall/setUserAttributes(_:)``:
You do this by passing a `[String: Any?]` dictionary of attributes to ``Superwall/setUserAttributes(_:)-1wql2``:

```swift
extension SuperwallService {
Expand Down
16 changes: 15 additions & 1 deletion Sources/SuperwallKit/Identity/IdentityManager.swift
Expand Up @@ -12,6 +12,9 @@
// synchronised via a dispatch queue. When writing, use queue.async, when
// reading use a computed var with a queue.sync block. You do not need to
// use the queue during init.
// A Dispatch Group is used when calling functions that will call didSetIdentity.
// This is to prevent the case where identitySubject sends a true value before
// all functions affecting the identity have finished.
//
// *******************************************************************

Expand Down Expand Up @@ -80,6 +83,7 @@ class IdentityManager {
/// When `false`, the SDK is unable to present paywalls.
private let identitySubject = CurrentValueSubject<Bool, Never>(false)
private let queue = DispatchQueue(label: "com.superwall.identitymanager")
private let group = DispatchGroup()

private unowned let deviceHelper: DeviceHelper
private unowned let storage: Storage
Expand All @@ -100,6 +104,7 @@ class IdentityManager {

/// Checks for static config upgrade before setting identity.
func configure() async {
group.enter()
let neverCalledStaticConfig = storage.neverCalledStaticConfig
let isFirstAppOpen = !(storage.get(DidTrackFirstSeen.self) ?? false)

Expand All @@ -110,6 +115,7 @@ class IdentityManager {
) {
await configManager.getAssignments()
}
group.leave()

didSetIdentity()
}
Expand All @@ -129,6 +135,8 @@ class IdentityManager {
return
}

group.enter()

queue.async { [weak self] in
guard let self = self else {
return
Expand Down Expand Up @@ -156,6 +164,7 @@ class IdentityManager {
Task.detached {
await self.configManager.getAssignments()
}
self.group.leave()
self.didSetIdentity()
}

Expand All @@ -167,6 +176,7 @@ class IdentityManager {
if options.restorePaywallAssignments {
Task {
await self.configManager.getAssignments()
self.group.leave()
self.didSetIdentity()
}
} else {
Expand All @@ -181,7 +191,9 @@ class IdentityManager {
/// Sends a `true` value to the `identitySubject` in order to fire
/// triggers after reset.
func didSetIdentity() {
identitySubject.send(true)
group.notify(queue: .main) { [weak self] in
self?.identitySubject.send(true)
}
}

/// Saves the aliasId and appUserId to storage and user attributes.
Expand Down Expand Up @@ -220,8 +232,10 @@ extension IdentityManager {
if duringIdentify {
self._reset()
} else {
group.enter()
queue.async { [weak self] in
self?._reset()
self?.group.leave()
self?.didSetIdentity()
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/SuperwallKit/Identity/PublicIdentity.swift
Expand Up @@ -31,7 +31,7 @@ extension Superwall {
)
}

/// Objective-C only method. Creates an account with Superwall. This links a `userId` to Superwall's automatically generated alias.
/// Objective-C-only method. Creates an account with Superwall. This links a `userId` to Superwall's automatically generated alias.
///
/// Call this as soon as you have a `userId`.
///
Expand Down
4 changes: 2 additions & 2 deletions Sources/SuperwallKit/Identity/UserAttributes.swift
Expand Up @@ -47,7 +47,7 @@ extension Superwall {
///
/// ```
/// NSDictionary *userAttributes = @{ key : value, key2 : value2};
/// [[Superwall sharedInstance] setUserAttributesDictionary: userAttributes];
/// [[Superwall sharedInstance] setUserAttributes:userAttributes];
/// ```
///
/// - Parameters:
Expand All @@ -56,7 +56,7 @@ extension Superwall {
/// Note: Keys beginning with `$` are reserved for Superwall and will be dropped. Arrays and dictionaries
/// as values are not supported at this time, and will be dropped.
@available(swift, obsoleted: 1.0)
@objc public func setUserAttributesDictionary(_ attributes: NSDictionary) {
@objc public func setUserAttributes(_ attributes: NSDictionary) {
var swiftDictionary: [String: Any?] = [:]
let keys = attributes.allKeys.compactMap { $0 as? String }
for key in keys {
Expand Down
2 changes: 1 addition & 1 deletion Sources/SuperwallKit/Misc/Constants.swift
Expand Up @@ -18,5 +18,5 @@ let sdkVersion = """
*/

let sdkVersion = """
3.0.0-beta.6
3.0.0-beta.7
"""
5 changes: 0 additions & 5 deletions Sources/SuperwallKit/Models/Triggers/TriggerResult.swift
Expand Up @@ -7,11 +7,6 @@

import Foundation

/// The result of a tracking an event.
///
/// Contains the possible cases resulting from tracking an event.
public typealias TrackResult = TriggerResult

/// The result of a paywall trigger.
///
/// Triggers can conditionally show paywalls. Contains the possible cases resulting from the trigger.
Expand Down

0 comments on commit 58f17de

Please sign in to comment.