Skip to content

Commit a54a69b

Browse files
authored
Merge branch 'main' into add_privacy_manifests_to_all_targets
2 parents 1c5d7e8 + 8c70169 commit a54a69b

17 files changed

+773
-110
lines changed

iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
3C6299A72BEEA41900649187 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 3C6299A62BEEA40100649187 /* PrivacyInfo.xcprivacy */; };
8989
3C6299A92BEEA46C00649187 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 3C6299A82BEEA46C00649187 /* PrivacyInfo.xcprivacy */; };
9090
3C6299AB2BEEA4C000649187 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 3C6299AA2BEEA4C000649187 /* PrivacyInfo.xcprivacy */; };
91+
3C67F77A2BEB2B710085A0F0 /* SwitchUserIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C67F7792BEB2B710085A0F0 /* SwitchUserIntegrationTests.swift */; };
9192
3C789DBD293C2206004CF83D /* OSFocusInfluenceParam.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A600B432453790700514A53 /* OSFocusInfluenceParam.m */; };
9293
3C789DBE293D8EAD004CF83D /* OSFocusInfluenceParam.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A600B41245378ED00514A53 /* OSFocusInfluenceParam.h */; settings = {ATTRIBUTES = (Public, ); }; };
9394
3C7A39C12B7BED900082665E /* OneSignalCoreMocks.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3CC0639A2B6D7A8C002BB07F /* OneSignalCoreMocks.framework */; };
@@ -122,6 +123,8 @@
122123
3CA283A92B86A30400097465 /* OneSignalCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DE7D17E627026B95002D3A5D /* OneSignalCore.framework */; };
123124
3CA283AA2B86A30400097465 /* OneSignalCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DE7D17E627026B95002D3A5D /* OneSignalCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
124125
3CA6CE0A28E4F19B00CA0585 /* OSUserRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CA6CE0928E4F19B00CA0585 /* OSUserRequest.swift */; };
126+
3CA8B8822BEC2FCB0010ADA1 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C7A39D42B7C18EE0082665E /* XCTest.framework */; };
127+
3CA8B8832BEC2FCB0010ADA1 /* XCTest.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3C7A39D42B7C18EE0082665E /* XCTest.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
125128
3CC063942B6D6B6B002BB07F /* OneSignalCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CC063932B6D6B6B002BB07F /* OneSignalCore.m */; };
126129
3CC063A22B6D7A8E002BB07F /* OneSignalCoreMocks.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3CC0639A2B6D7A8C002BB07F /* OneSignalCoreMocks.framework */; };
127130
3CC063A72B6D7A8E002BB07F /* OneSignalCoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CC063A62B6D7A8E002BB07F /* OneSignalCoreTests.swift */; };
@@ -1028,6 +1031,7 @@
10281031
dstSubfolderSpec = 10;
10291032
files = (
10301033
3CEE93542B7C78EC008440BD /* OneSignalUser.framework in Embed Frameworks */,
1034+
3CA8B8832BEC2FCB0010ADA1 /* XCTest.framework in Embed Frameworks */,
10311035
3CEE934F2B7C787B008440BD /* OneSignalOSCore.framework in Embed Frameworks */,
10321036
);
10331037
name = "Embed Frameworks";
@@ -1133,6 +1137,7 @@
11331137
3C6299A62BEEA40100649187 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
11341138
3C6299A82BEEA46C00649187 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
11351139
3C6299AA2BEEA4C000649187 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
1140+
3C67F7792BEB2B710085A0F0 /* SwitchUserIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwitchUserIntegrationTests.swift; sourceTree = "<group>"; };
11361141
3C7A39D42B7C18EE0082665E /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
11371142
3C87066F2BDE0957000D8CD2 /* MockUserRequests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockUserRequests.swift; sourceTree = "<group>"; };
11381143
3C8706712BDEE076000D8CD2 /* MockUserDefines.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockUserDefines.swift; sourceTree = "<group>"; };
@@ -1581,6 +1586,7 @@
15811586
buildActionMask = 2147483647;
15821587
files = (
15831588
3CEE93532B7C78EC008440BD /* OneSignalUser.framework in Frameworks */,
1589+
3CA8B8822BEC2FCB0010ADA1 /* XCTest.framework in Frameworks */,
15841590
3CEE934E2B7C787B008440BD /* OneSignalOSCore.framework in Frameworks */,
15851591
);
15861592
runOnlyForDeploymentPostprocessing = 0;
@@ -1972,6 +1978,7 @@
19721978
isa = PBXGroup;
19731979
children = (
19741980
3CC063ED2B6D7FE8002BB07F /* OneSignalUserTests.swift */,
1981+
3C67F7792BEB2B710085A0F0 /* SwitchUserIntegrationTests.swift */,
19751982
);
19761983
path = OneSignalUserTests;
19771984
sourceTree = "<group>";
@@ -3763,6 +3770,7 @@
37633770
isa = PBXSourcesBuildPhase;
37643771
buildActionMask = 2147483647;
37653772
files = (
3773+
3C67F77A2BEB2B710085A0F0 /* SwitchUserIntegrationTests.swift in Sources */,
37663774
3CC063EE2B6D7FE8002BB07F /* OneSignalUserTests.swift in Sources */,
37673775
);
37683776
runOnlyForDeploymentPostprocessing = 0;

iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OneSignalClient.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ - (void)handleJSONNSURLResponse:(NSURLResponse*)response data:(NSData*)data erro
203203
if (data != nil && [data length] > 0) {
204204
innerJson = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonError];
205205
innerJson[@"httpStatusCode"] = [NSNumber numberWithLong:statusCode];
206-
[OneSignalLog onesignalLog:ONE_S_LL_VERBOSE message:[NSString stringWithFormat:@"network response (%@): %@", NSStringFromClass([request class]), innerJson]];
206+
[OneSignalLog onesignalLog:ONE_S_LL_VERBOSE message:[NSString stringWithFormat:@"network response (%@) with URL %@: %@", NSStringFromClass([request class]), request.urlRequest.URL.absoluteString, innerJson]];
207207
if (jsonError) {
208208
if (failureBlock != nil)
209209
failureBlock([NSError errorWithDomain:@"OneSignal Error" code:statusCode userInfo:@{@"returned" : jsonError}]);

iOS_SDK/OneSignalSDK/OneSignalCoreMocks/Extensions/NSDictionary+UnitTests.swift

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,62 @@
11
extension NSDictionary {
2-
func contains(key: String, value: Any) -> Bool {
2+
/*
3+
This method goes one level deep into dictionaries
4+
*/
5+
private func contains(key: String, value: Any) -> Bool {
36
guard let dictVal = self[key] else {
47
return false
58
}
6-
7-
return equals(dictVal, value)
9+
if let value = value as? [String: Any],
10+
let dictVal = dictVal as? NSDictionary {
11+
return dictVal.contains(value)
12+
} else {
13+
return equals(dictVal, value)
14+
}
815
}
916

10-
func contains(_ dict: [String: Any]) -> Bool {
17+
/*
18+
let parent = [
19+
"apple": [
20+
"type": "fruit",
21+
"count": 5,
22+
"fresh": true
23+
],
24+
"orange": [
25+
"type": "color"
26+
],
27+
"cactus": "error"
28+
]
29+
30+
// 1. Example 1 -
31+
let child1 = [
32+
"apple": [
33+
"type": "fruit",
34+
"fresh": true
35+
]
36+
]
37+
parent.contains(child1) = true
38+
39+
// 2. Example 2 -
40+
let child2 = [
41+
"apple": [
42+
"type": "fruit"
43+
],
44+
"orange": [
45+
"type": "fruit"
46+
]
47+
]
48+
parent.contains(child2) = false
49+
50+
// 3. Example 3 -
51+
let child3 = [
52+
"orange": [
53+
"type": "color"
54+
],
55+
"cactus": "error"
56+
]
57+
parent.contains(child3) = true
58+
*/
59+
public func contains(_ dict: [String: Any]) -> Bool {
1160
for (key, value) in dict {
1261
if !contains(key: key, value: value) {
1362
return false

iOS_SDK/OneSignalSDK/OneSignalCoreMocks/MockOneSignalClient.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public class MockOneSignalClient: NSObject, IOneSignalClient {
3535
public var lastHTTPRequest: OneSignalRequest?
3636
public var networkRequestCount = 0
3737
public var executedRequests: [OneSignalRequest] = []
38-
public var executeInstantaneously = true
38+
public var executeInstantaneously = false
3939

4040
var remoteParamsResponse: [String: Any]?
4141
var shouldUseProvisionalAuthorization = false // new in iOS 12 (aka Direct to History)
@@ -95,7 +95,7 @@ public class MockOneSignalClient: NSObject, IOneSignalClient {
9595
if executeInstantaneously {
9696
finishExecutingRequest(request, onSuccess: successBlock, onFailure: failureBlock)
9797
} else {
98-
executionQueue.async {
98+
executionQueue.asyncAfter(deadline: .now() + .milliseconds(50)) {
9999
self.finishExecutingRequest(request, onSuccess: successBlock, onFailure: failureBlock)
100100
}
101101
}
@@ -177,4 +177,10 @@ extension MockOneSignalClient {
177177

178178
return found
179179
}
180+
181+
public func hasExecutedRequestOfType(_ type: AnyClass) -> Bool {
182+
executedRequests.contains { request in
183+
request.isKind(of: type)
184+
}
185+
}
180186
}

iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSUserExecutor.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,10 @@ class OSUserExecutor {
329329
if OneSignalUserManagerImpl.sharedInstance.isCurrentUser(request.identityModelToUpdate) {
330330
fetchUser(aliasLabel: OS_EXTERNAL_ID, aliasId: request.aliasId, identityModel: request.identityModelToUpdate)
331331
} else {
332+
// Need to hydrate the identity model for any pending requests
333+
if let osid = request.identityModelToIdentify.onesignalId {
334+
request.identityModelToUpdate.hydrate([OS_ONESIGNAL_ID: osid])
335+
}
332336
executePendingRequests()
333337
}
334338
} onFailure: { error in
@@ -340,12 +344,15 @@ class OSUserExecutor {
340344
OneSignalLog.onesignalLog(.LL_DEBUG, message: "executeIdentifyUserRequest returned error code user-2. Now handling user-2 error response... switch to this user.")
341345

342346
removeFromQueue(request)
343-
// Fetch the user only if its the current user
347+
// Transfer the push subscription, and fetch only if it's the current user
344348
if OneSignalUserManagerImpl.sharedInstance.isCurrentUser(request.identityModelToUpdate) {
345349
fetchUser(aliasLabel: OS_EXTERNAL_ID, aliasId: request.aliasId, identityModel: request.identityModelToUpdate)
346-
// TODO: Link ^ to the new user... what was this todo for?
350+
transferPushSubscriptionTo(aliasLabel: request.aliasLabel, aliasId: request.aliasId)
351+
} else {
352+
// Use external_id for any pending requests, avoiding a fetch to hydrate onesignal_id
353+
request.identityModelToUpdate.primaryAliasLabel = .external_id
354+
executePendingRequests()
347355
}
348-
transferPushSubscriptionTo(aliasLabel: request.aliasLabel, aliasId: request.aliasId)
349356
} else if responseType == .invalid || responseType == .unauthorized {
350357
// Failed, no retry
351358
removeFromQueue(request)

iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSIdentityModel.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,23 @@ import Foundation
2929
import OneSignalCore
3030
import OneSignalOSCore
3131

32+
// By matching the enum name to the raw value, it will always stringify correctly
33+
enum OSDefaultAlias: String {
34+
// swiftlint:disable identifier_name
35+
case onesignal_id = "onesignal_id"
36+
case external_id = "external_id"
37+
// swiftlint:enable identifier_name
38+
}
39+
3240
class OSIdentityModel: OSModel {
41+
/**
42+
Set either `onesignal_id` or `external_id`, representing the alias that will be used in requests.
43+
*/
44+
var primaryAliasLabel: OSDefaultAlias = .onesignal_id
45+
var primaryAliasId: String? {
46+
return if primaryAliasLabel == .external_id { externalId } else { onesignalId }
47+
}
48+
3349
var onesignalId: String? {
3450
return internalGetAlias(OS_ONESIGNAL_ID)
3551
}
@@ -57,6 +73,7 @@ class OSIdentityModel: OSModel {
5773
aliasesLock.withLock {
5874
super.encode(with: coder)
5975
coder.encode(aliases, forKey: "aliases")
76+
coder.encode(primaryAliasLabel.rawValue, forKey: "primaryAliasLabel") // Encodes as String
6077
}
6178
}
6279

@@ -66,6 +83,12 @@ class OSIdentityModel: OSModel {
6683
// log error
6784
return nil
6885
}
86+
if let rawType = coder.decodeObject(forKey: "primaryAliasLabel") as? String,
87+
let label = OSDefaultAlias(rawValue: rawType) {
88+
self.primaryAliasLabel = label
89+
} else {
90+
self.primaryAliasLabel = .onesignal_id
91+
}
6992
self.aliases = aliases
7093
}
7194

iOS_SDK/OneSignalSDK/OneSignalUser/Source/Requests/OSRequestAddAliases.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,10 @@ class OSRequestAddAliases: OneSignalRequest, OSUserRequest {
3939

4040
// requires a `onesignal_id` to send this request
4141
func prepareForExecution() -> Bool {
42-
if let onesignalId = identityModel.onesignalId, let appId = OneSignalConfigManager.getAppId() {
42+
let aliasLabel = identityModel.primaryAliasLabel
43+
if let aliasId = identityModel.primaryAliasId, let appId = OneSignalConfigManager.getAppId() {
4344
self.addJWTHeader(identityModel: identityModel)
44-
self.path = "apps/\(appId)/users/by/\(OS_ONESIGNAL_ID)/\(onesignalId)/identity"
45+
self.path = "apps/\(appId)/users/by/\(aliasLabel)/\(aliasId)/identity"
4546
return true
4647
} else {
4748
// self.path is non-nil, so set to empty string
@@ -53,7 +54,7 @@ class OSRequestAddAliases: OneSignalRequest, OSUserRequest {
5354
init(aliases: [String: String], identityModel: OSIdentityModel) {
5455
self.identityModel = identityModel
5556
self.aliases = aliases
56-
self.stringDescription = "OSRequestAddAliases with aliases: \(aliases)"
57+
self.stringDescription = "<OSRequestAddAliases with aliases: \(aliases)>"
5758
super.init()
5859
self.parameters = ["identity": aliases]
5960
self.method = PATCH
@@ -81,7 +82,7 @@ class OSRequestAddAliases: OneSignalRequest, OSUserRequest {
8182
}
8283
self.identityModel = identityModel
8384
self.aliases = aliases
84-
self.stringDescription = "OSRequestAddAliases with parameters: \(parameters)"
85+
self.stringDescription = "<OSRequestAddAliases with aliases: \(aliases)>"
8586
super.init()
8687
self.parameters = parameters
8788
self.method = HTTPMethod(rawValue: rawMethod)

iOS_SDK/OneSignalSDK/OneSignalUser/Source/Requests/OSRequestCreateSubscription.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,10 @@ class OSRequestCreateSubscription: OneSignalRequest, OSUserRequest {
4444

4545
// Need the onesignal_id of the user
4646
func prepareForExecution() -> Bool {
47-
if let onesignalId = identityModel.onesignalId, let appId = OneSignalConfigManager.getAppId() {
47+
let aliasLabel = identityModel.primaryAliasLabel
48+
if let aliasId = identityModel.primaryAliasId, let appId = OneSignalConfigManager.getAppId() {
4849
self.addJWTHeader(identityModel: identityModel)
49-
self.path = "apps/\(appId)/users/by/\(OS_ONESIGNAL_ID)/\(onesignalId)/subscriptions"
50+
self.path = "apps/\(appId)/users/by/\(aliasLabel)/\(aliasId)/subscriptions"
5051
return true
5152
} else {
5253
self.path = "" // self.path is non-nil, so set to empty string
@@ -57,7 +58,7 @@ class OSRequestCreateSubscription: OneSignalRequest, OSUserRequest {
5758
init(subscriptionModel: OSSubscriptionModel, identityModel: OSIdentityModel) {
5859
self.subscriptionModel = subscriptionModel
5960
self.identityModel = identityModel
60-
self.stringDescription = "OSRequestCreateSubscription with subscriptionModel: \(subscriptionModel.address ?? "nil")"
61+
self.stringDescription = "<OSRequestCreateSubscription with token: \(subscriptionModel.address ?? "nil")>"
6162
super.init()
6263
self.parameters = ["subscription": subscriptionModel.jsonRepresentation()]
6364
self.method = POST
@@ -85,7 +86,7 @@ class OSRequestCreateSubscription: OneSignalRequest, OSUserRequest {
8586
}
8687
self.subscriptionModel = subscriptionModel
8788
self.identityModel = identityModel
88-
self.stringDescription = "OSRequestCreateSubscription with subscriptionModel: \(subscriptionModel.address ?? "nil")"
89+
self.stringDescription = "<OSRequestCreateSubscription with token: \(subscriptionModel.address ?? "nil")>"
8990
super.init()
9091
self.parameters = parameters
9192
self.method = HTTPMethod(rawValue: rawMethod)

iOS_SDK/OneSignalSDK/OneSignalUser/Source/Requests/OSRequestFetchUser.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class OSRequestFetchUser: OneSignalRequest, OSUserRequest {
5858
self.aliasLabel = aliasLabel
5959
self.aliasId = aliasId
6060
self.onNewSession = onNewSession
61-
self.stringDescription = "<OSRequestFetchUser with aliasLabel: \(aliasLabel) aliasId: \(aliasId)>"
61+
self.stringDescription = "<OSRequestFetchUser with \(aliasLabel): \(aliasId)>"
6262
super.init()
6363
self.method = GET
6464
_ = prepareForExecution() // sets the path property
@@ -88,7 +88,7 @@ class OSRequestFetchUser: OneSignalRequest, OSUserRequest {
8888
self.aliasLabel = aliasLabel
8989
self.aliasId = aliasId
9090
self.onNewSession = coder.decodeBool(forKey: "onNewSession")
91-
self.stringDescription = "<OSRequestFetchUser with aliasLabel: \(aliasLabel) aliasId: \(aliasId)>"
91+
self.stringDescription = "<OSRequestFetchUser with \(aliasLabel): \(aliasId)>"
9292
super.init()
9393
self.method = HTTPMethod(rawValue: rawMethod)
9494
self.timestamp = timestamp

iOS_SDK/OneSignalSDK/OneSignalUser/Source/Requests/OSRequestIdentifyUser.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,15 @@ class OSRequestIdentifyUser: OneSignalRequest, OSUserRequest {
4848

4949
// requires a onesignal_id to send this request
5050
func prepareForExecution() -> Bool {
51-
if let onesignalId = identityModelToIdentify.onesignalId, let appId = OneSignalConfigManager.getAppId() {
51+
let aliasLabel = identityModelToIdentify.primaryAliasLabel
52+
if let aliasId = identityModelToIdentify.primaryAliasId, let appId = OneSignalConfigManager.getAppId() {
5253
self.addJWTHeader(identityModel: identityModelToIdentify)
53-
self.path = "apps/\(appId)/users/by/\(OS_ONESIGNAL_ID)/\(onesignalId)/identity"
54+
self.path = "apps/\(appId)/users/by/\(aliasLabel)/\(aliasId)/identity"
5455
return true
5556
} else {
5657
// self.path is non-nil, so set to empty string
5758
self.path = ""
58-
OneSignalLog.onesignalLog(.LL_DEBUG, message: "Cannot generate the Identify User request due to null app ID or null OneSignal ID.")
59+
OneSignalLog.onesignalLog(.LL_DEBUG, message: "Cannot generate the Identify User request due to null app ID or null \(aliasLabel) ID.")
5960
return false
6061
}
6162
}
@@ -72,7 +73,7 @@ class OSRequestIdentifyUser: OneSignalRequest, OSUserRequest {
7273
self.identityModelToUpdate = identityModelToUpdate
7374
self.aliasLabel = aliasLabel
7475
self.aliasId = aliasId
75-
self.stringDescription = "<OSRequestIdentifyUser with aliasLabel: \(aliasLabel) aliasId: \(aliasId)>"
76+
self.stringDescription = "<OSRequestIdentifyUser with \(aliasLabel): \(aliasId)>"
7677
super.init()
7778
self.parameters = ["identity": [aliasLabel: aliasId]]
7879
self.method = PATCH
@@ -106,7 +107,7 @@ class OSRequestIdentifyUser: OneSignalRequest, OSUserRequest {
106107
self.identityModelToUpdate = identityModelToUpdate
107108
self.aliasLabel = aliasLabel
108109
self.aliasId = aliasId
109-
self.stringDescription = "<OSRequestIdentifyUser with aliasLabel: \(aliasLabel) aliasId: \(aliasId)>"
110+
self.stringDescription = "<OSRequestIdentifyUser with \(aliasLabel): \(aliasId)>"
110111
super.init()
111112
self.timestamp = timestamp
112113
self.parameters = parameters

0 commit comments

Comments
 (0)