Skip to content

Commit 740b258

Browse files
authored
refactor: Move MPRokt Swift interop to core SDK for single-import (#703)
* refactor: Move MPRokt Swift interop to core SDK for single-import experience Swift consumers previously needed two imports to access MPRokt APIs that use RoktContracts types: `import mParticle_Apple_SDK` and `import mParticle_Rokt_Swift`. This moves the bridge extensions into the core SDK target so a single `import mParticle_Apple_SDK` provides all MPRokt methods in Swift.
1 parent 27e482c commit 740b258

9 files changed

Lines changed: 372 additions & 55 deletions

File tree

Kits/rokt/rokt/Example/SPM-Objc-Example/SPM-Objc-Example.xcodeproj/project.pbxproj

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
/* Begin PBXBuildFile section */
1010
CC0001012F50000000000001 /* mParticle-Rokt in Frameworks */ = {isa = PBXBuildFile; productRef = CC0001022F50000000000002 /* mParticle-Rokt */; };
11+
CC0001032F50000000000003 /* mParticle-Apple-SDK in Frameworks */ = {isa = PBXBuildFile; productRef = CC0001042F50000000000004 /* mParticle-Apple-SDK */; };
12+
CC0001052F50000000000005 /* RoktContracts in Frameworks */ = {isa = PBXBuildFile; productRef = CC0001062F50000000000006 /* RoktContracts */; };
1113
/* End PBXBuildFile section */
1214

1315
/* Begin PBXFileReference section */
@@ -40,7 +42,9 @@
4042
isa = PBXFrameworksBuildPhase;
4143
buildActionMask = 2147483647;
4244
files = (
45+
CC0001032F50000000000003 /* mParticle-Apple-SDK in Frameworks */,
4346
CC0001012F50000000000001 /* mParticle-Rokt in Frameworks */,
47+
CC0001052F50000000000005 /* RoktContracts in Frameworks */,
4448
);
4549
runOnlyForDeploymentPostprocessing = 0;
4650
};
@@ -84,6 +88,8 @@
8488
name = "SPM-Objc-Example";
8589
packageProductDependencies = (
8690
CC0001022F50000000000002 /* mParticle-Rokt */,
91+
CC0001042F50000000000004 /* mParticle-Apple-SDK */,
92+
CC0001062F50000000000006 /* RoktContracts */,
8793
);
8894
productName = "SPM-Objc-Example";
8995
productReference = CC0002012F50000000000001 /* SPM-Objc-Example.app */;
@@ -114,6 +120,7 @@
114120
minimizedProjectReferenceProxies = 1;
115121
packageReferences = (
116122
CC000A012F50000000000001 /* XCLocalSwiftPackageReference "../.." */,
123+
CC000A022F50000000000002 /* XCLocalSwiftPackageReference "../../../../.." */,
117124
);
118125
preferredProjectObjectVersion = 77;
119126
productRefGroup = CC0007022F50000000000002 /* Products */;
@@ -346,13 +353,27 @@
346353
isa = XCLocalSwiftPackageReference;
347354
relativePath = "../..";
348355
};
356+
CC000A022F50000000000002 /* XCLocalSwiftPackageReference "../../../../.." */ = {
357+
isa = XCLocalSwiftPackageReference;
358+
relativePath = "../../../../..";
359+
};
349360
/* End XCLocalSwiftPackageReference section */
350361

351362
/* Begin XCSwiftPackageProductDependency section */
352363
CC0001022F50000000000002 /* mParticle-Rokt */ = {
353364
isa = XCSwiftPackageProductDependency;
365+
package = CC000A012F50000000000001 /* XCLocalSwiftPackageReference "../.." */;
354366
productName = "mParticle-Rokt";
355367
};
368+
CC0001042F50000000000004 /* mParticle-Apple-SDK */ = {
369+
isa = XCSwiftPackageProductDependency;
370+
package = CC000A022F50000000000002 /* XCLocalSwiftPackageReference "../../../../.." */;
371+
productName = "mParticle-Apple-SDK";
372+
};
373+
CC0001062F50000000000006 /* RoktContracts */ = {
374+
isa = XCSwiftPackageProductDependency;
375+
productName = RoktContracts;
376+
};
356377
/* End XCSwiftPackageProductDependency section */
357378
};
358379
rootObject = CC0009012F50000000000001 /* Project object */;

Kits/rokt/rokt/Example/SPM-Objc-Example/SPM-Objc-Example/AppDelegate.m

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#import "AppDelegate.h"
2-
@import mParticle_Apple_SDK;
3-
@import mParticle_Rokt;
2+
@import mParticle_Apple_SDK_ObjC;
43

54
@interface AppDelegate ()
65

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,241 @@
11
#import "ViewController.h"
2+
@import mParticle_Apple_SDK_ObjC;
3+
@import RoktContracts;
24

35
@interface ViewController ()
46

7+
@property (nonatomic, strong) UIScrollView *scrollView;
8+
@property (nonatomic, strong) UIStackView *stackView;
9+
@property (nonatomic, strong) UIButton *overlayButton;
10+
@property (nonatomic, strong) UIButton *bottomsheetButton;
11+
@property (nonatomic, strong) UIStackView *eventLogStack;
12+
@property (nonatomic, strong) UILabel *eventLogHeader;
13+
@property (nonatomic, strong) NSMutableArray<NSString *> *eventLog;
14+
@property (nonatomic, assign) BOOL overlayTriggered;
15+
@property (nonatomic, assign) BOOL bottomsheetTriggered;
16+
517
@end
618

719
@implementation ViewController
820

921
- (void)viewDidLoad {
1022
[super viewDidLoad];
23+
24+
self.eventLog = [NSMutableArray array];
25+
self.view.backgroundColor = UIColor.systemBackgroundColor;
26+
27+
[self setupUI];
28+
}
29+
30+
- (void)setupUI {
31+
// Checkmark icon
32+
UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:56];
33+
UIImageView *checkmark = [[UIImageView alloc] initWithImage:[UIImage systemImageNamed:@"checkmark.circle.fill" withConfiguration:config]];
34+
checkmark.tintColor = [self colorFromHex:@"#C20075"];
35+
checkmark.contentMode = UIViewContentModeCenter;
36+
37+
// Title
38+
UILabel *titleLabel = [[UILabel alloc] init];
39+
titleLabel.text = @"Order Confirmed";
40+
titleLabel.font = [UIFont boldSystemFontOfSize:28];
41+
titleLabel.textAlignment = NSTextAlignmentCenter;
42+
43+
// Subtitle
44+
UILabel *subtitleLabel = [[UILabel alloc] init];
45+
subtitleLabel.text = @"Reference: ORDER-12345";
46+
subtitleLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline];
47+
subtitleLabel.textColor = UIColor.secondaryLabelColor;
48+
subtitleLabel.textAlignment = NSTextAlignmentCenter;
49+
50+
// Overlay button
51+
self.overlayButton = [UIButton buttonWithType:UIButtonTypeSystem];
52+
[self.overlayButton setTitle:@"Load Rokt Placement" forState:UIControlStateNormal];
53+
[self.overlayButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
54+
self.overlayButton.backgroundColor = [self colorFromHex:@"#C20075"];
55+
self.overlayButton.layer.cornerRadius = 8;
56+
self.overlayButton.contentEdgeInsets = UIEdgeInsetsMake(12, 24, 12, 24);
57+
[self.overlayButton addTarget:self action:@selector(loadOverlayPlacement) forControlEvents:UIControlEventTouchUpInside];
58+
59+
// Bottomsheet button
60+
self.bottomsheetButton = [UIButton buttonWithType:UIButtonTypeSystem];
61+
[self.bottomsheetButton setTitle:@"Load Bottomsheet Placement" forState:UIControlStateNormal];
62+
[self.bottomsheetButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
63+
self.bottomsheetButton.backgroundColor = [self colorFromHex:@"#5A2D82"];
64+
self.bottomsheetButton.layer.cornerRadius = 8;
65+
self.bottomsheetButton.contentEdgeInsets = UIEdgeInsetsMake(12, 24, 12, 24);
66+
[self.bottomsheetButton addTarget:self action:@selector(loadBottomsheetPlacement) forControlEvents:UIControlEventTouchUpInside];
67+
68+
// Event log header (initially hidden)
69+
self.eventLogHeader = [[UILabel alloc] init];
70+
self.eventLogHeader.text = @"Event Log";
71+
self.eventLogHeader.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
72+
self.eventLogHeader.hidden = YES;
73+
74+
// Event log stack
75+
self.eventLogStack = [[UIStackView alloc] init];
76+
self.eventLogStack.axis = UILayoutConstraintAxisVertical;
77+
self.eventLogStack.spacing = 4;
78+
self.eventLogStack.alignment = UIStackViewAlignmentLeading;
79+
80+
// Event log container
81+
UIView *eventLogContainer = [[UIView alloc] init];
82+
eventLogContainer.backgroundColor = UIColor.secondarySystemGroupedBackgroundColor;
83+
eventLogContainer.layer.cornerRadius = 10;
84+
eventLogContainer.clipsToBounds = YES;
85+
eventLogContainer.hidden = YES;
86+
eventLogContainer.tag = 100;
87+
88+
[eventLogContainer addSubview:self.eventLogHeader];
89+
[eventLogContainer addSubview:self.eventLogStack];
90+
91+
self.eventLogHeader.translatesAutoresizingMaskIntoConstraints = NO;
92+
self.eventLogStack.translatesAutoresizingMaskIntoConstraints = NO;
93+
94+
[NSLayoutConstraint activateConstraints:@[
95+
[self.eventLogHeader.topAnchor constraintEqualToAnchor:eventLogContainer.topAnchor constant:12],
96+
[self.eventLogHeader.leadingAnchor constraintEqualToAnchor:eventLogContainer.leadingAnchor constant:12],
97+
[self.eventLogHeader.trailingAnchor constraintEqualToAnchor:eventLogContainer.trailingAnchor constant:-12],
98+
[self.eventLogStack.topAnchor constraintEqualToAnchor:self.eventLogHeader.bottomAnchor constant:8],
99+
[self.eventLogStack.leadingAnchor constraintEqualToAnchor:eventLogContainer.leadingAnchor constant:12],
100+
[self.eventLogStack.trailingAnchor constraintEqualToAnchor:eventLogContainer.trailingAnchor constant:-12],
101+
[self.eventLogStack.bottomAnchor constraintEqualToAnchor:eventLogContainer.bottomAnchor constant:-12],
102+
]];
103+
104+
// Main stack
105+
self.stackView = [[UIStackView alloc] initWithArrangedSubviews:@[
106+
checkmark, titleLabel, subtitleLabel,
107+
self.overlayButton, self.bottomsheetButton,
108+
eventLogContainer
109+
]];
110+
self.stackView.axis = UILayoutConstraintAxisVertical;
111+
self.stackView.spacing = 24;
112+
self.stackView.alignment = UIStackViewAlignmentCenter;
113+
self.stackView.translatesAutoresizingMaskIntoConstraints = NO;
114+
115+
// Scroll view
116+
self.scrollView = [[UIScrollView alloc] init];
117+
self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;
118+
[self.scrollView addSubview:self.stackView];
119+
[self.view addSubview:self.scrollView];
120+
121+
[NSLayoutConstraint activateConstraints:@[
122+
[self.scrollView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
123+
[self.scrollView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
124+
[self.scrollView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
125+
[self.scrollView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor],
126+
[self.stackView.topAnchor constraintEqualToAnchor:self.scrollView.topAnchor constant:40],
127+
[self.stackView.leadingAnchor constraintEqualToAnchor:self.scrollView.leadingAnchor constant:16],
128+
[self.stackView.trailingAnchor constraintEqualToAnchor:self.scrollView.trailingAnchor constant:-16],
129+
[self.stackView.bottomAnchor constraintEqualToAnchor:self.scrollView.bottomAnchor constant:-16],
130+
[self.stackView.widthAnchor constraintEqualToAnchor:self.scrollView.widthAnchor constant:-32],
131+
[eventLogContainer.widthAnchor constraintEqualToAnchor:self.stackView.widthAnchor],
132+
]];
11133
}
12134

135+
- (NSDictionary<NSString *, NSString *> *)attributes {
136+
return @{
137+
@"email": @"jenny.smith@rokt.com",
138+
@"firstname": @"Jenny",
139+
@"lastname": @"Smith",
140+
@"confirmationref": @"ORDER-12345",
141+
@"billingzipcode": @"10014",
142+
@"sandbox": @"true"
143+
};
144+
}
145+
146+
- (void)loadOverlayPlacement {
147+
self.overlayTriggered = YES;
148+
self.overlayButton.enabled = NO;
149+
self.overlayButton.alpha = 0.5;
150+
151+
[[MParticle sharedInstance].rokt selectPlacements:@"MSDKOverlayLayout"
152+
attributes:[self attributes]
153+
embeddedViews:nil
154+
config:nil
155+
onEvent:nil];
156+
}
157+
158+
- (void)loadBottomsheetPlacement {
159+
self.bottomsheetTriggered = YES;
160+
self.bottomsheetButton.enabled = NO;
161+
self.bottomsheetButton.alpha = 0.5;
162+
163+
__weak typeof(self) weakSelf = self;
164+
165+
[[MParticle sharedInstance].rokt events:@"MSDKBottomsheetLayout" onEvent:^(RoktEvent * _Nonnull event) {
166+
NSString *description = [weakSelf describeEvent:event];
167+
NSLog(@"RoktEvent: %@", description);
168+
dispatch_async(dispatch_get_main_queue(), ^{
169+
[weakSelf appendEventLog:description];
170+
});
171+
}];
172+
173+
[[MParticle sharedInstance].rokt selectPlacements:@"MSDKBottomsheetLayout"
174+
attributes:[self attributes]
175+
embeddedViews:nil
176+
config:nil
177+
onEvent:nil];
178+
}
179+
180+
- (void)appendEventLog:(NSString *)entry {
181+
[self.eventLog addObject:entry];
182+
183+
UIView *eventLogContainer = [self.view viewWithTag:100];
184+
eventLogContainer.hidden = NO;
185+
self.eventLogHeader.hidden = NO;
186+
187+
// Insert at top (reversed order like Swift example)
188+
UILabel *label = [[UILabel alloc] init];
189+
label.text = entry;
190+
label.font = [UIFont monospacedSystemFontOfSize:11 weight:UIFontWeightRegular];
191+
label.numberOfLines = 0;
192+
[self.eventLogStack insertArrangedSubview:label atIndex:0];
193+
}
194+
195+
- (NSString *)describeEvent:(RoktEvent *)event {
196+
if ([event isKindOfClass:[RoktShowLoadingIndicator class]]) {
197+
return @"ShowLoadingIndicator";
198+
} else if ([event isKindOfClass:[RoktHideLoadingIndicator class]]) {
199+
return @"HideLoadingIndicator";
200+
} else if ([event isKindOfClass:[RoktPlacementReady class]]) {
201+
RoktPlacementReady *e = (RoktPlacementReady *)event;
202+
return [NSString stringWithFormat:@"PlacementReady - %@", e.identifier ?: @""];
203+
} else if ([event isKindOfClass:[RoktPlacementInteractive class]]) {
204+
RoktPlacementInteractive *e = (RoktPlacementInteractive *)event;
205+
return [NSString stringWithFormat:@"PlacementInteractive - %@", e.identifier ?: @""];
206+
} else if ([event isKindOfClass:[RoktOfferEngagement class]]) {
207+
RoktOfferEngagement *e = (RoktOfferEngagement *)event;
208+
return [NSString stringWithFormat:@"OfferEngagement - %@", e.identifier ?: @""];
209+
} else if ([event isKindOfClass:[RoktPositiveEngagement class]]) {
210+
RoktPositiveEngagement *e = (RoktPositiveEngagement *)event;
211+
return [NSString stringWithFormat:@"PositiveEngagement - %@", e.identifier ?: @""];
212+
} else if ([event isKindOfClass:[RoktFirstPositiveEngagement class]]) {
213+
RoktFirstPositiveEngagement *e = (RoktFirstPositiveEngagement *)event;
214+
return [NSString stringWithFormat:@"FirstPositiveEngagement - %@", e.identifier ?: @""];
215+
} else if ([event isKindOfClass:[RoktOpenUrl class]]) {
216+
RoktOpenUrl *e = (RoktOpenUrl *)event;
217+
return [NSString stringWithFormat:@"OpenUrl - %@", e.url];
218+
} else if ([event isKindOfClass:[RoktPlacementClosed class]]) {
219+
RoktPlacementClosed *e = (RoktPlacementClosed *)event;
220+
return [NSString stringWithFormat:@"PlacementClosed - %@", e.identifier ?: @""];
221+
} else if ([event isKindOfClass:[RoktPlacementCompleted class]]) {
222+
RoktPlacementCompleted *e = (RoktPlacementCompleted *)event;
223+
return [NSString stringWithFormat:@"PlacementCompleted - %@", e.identifier ?: @""];
224+
} else if ([event isKindOfClass:[RoktPlacementFailure class]]) {
225+
RoktPlacementFailure *e = (RoktPlacementFailure *)event;
226+
return [NSString stringWithFormat:@"PlacementFailure - %@", e.identifier ?: @""];
227+
}
228+
return NSStringFromClass([event class]);
229+
}
230+
231+
- (UIColor *)colorFromHex:(NSString *)hex {
232+
NSString *cleaned = [[hex stringByTrimmingCharactersInSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]] uppercaseString];
233+
unsigned int rgbValue = 0;
234+
[[NSScanner scannerWithString:cleaned] scanHexInt:&rgbValue];
235+
return [UIColor colorWithRed:((rgbValue >> 16) & 0xFF) / 255.0
236+
green:((rgbValue >> 8) & 0xFF) / 255.0
237+
blue:(rgbValue & 0xFF) / 255.0
238+
alpha:1.0];
239+
}
13240

14241
@end

Kits/rokt/rokt/Example/SPM-Swift-Example/SPM-Swift-Example.xcodeproj/project.pbxproj

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10-
AA000007000000000000007A /* mParticle-Apple-SDK in Frameworks */ = {isa = PBXBuildFile; productRef = AA000003000000000000003A /* mParticle-Apple-SDK */; };
1110
AA000008000000000000008A /* mParticle-Rokt in Frameworks */ = {isa = PBXBuildFile; productRef = AA000004000000000000004A /* mParticle-Rokt */; };
11+
B34E89962F8087DA003A0ADE /* mParticle-Apple-SDK in Frameworks */ = {isa = PBXBuildFile; productRef = B34E89952F8087DA003A0ADE /* mParticle-Apple-SDK */; };
1212
/* End PBXBuildFile section */
1313

1414
/* Begin PBXFileReference section */
@@ -41,7 +41,7 @@
4141
isa = PBXFrameworksBuildPhase;
4242
buildActionMask = 2147483647;
4343
files = (
44-
AA000007000000000000007A /* mParticle-Apple-SDK in Frameworks */,
44+
B34E89962F8087DA003A0ADE /* mParticle-Apple-SDK in Frameworks */,
4545
AA000008000000000000008A /* mParticle-Rokt in Frameworks */,
4646
);
4747
runOnlyForDeploymentPostprocessing = 0;
@@ -85,8 +85,8 @@
8585
);
8686
name = "SPM-Swift-Example";
8787
packageProductDependencies = (
88-
AA000003000000000000003A /* mParticle-Apple-SDK */,
8988
AA000004000000000000004A /* mParticle-Rokt */,
89+
B34E89952F8087DA003A0ADE /* mParticle-Apple-SDK */,
9090
);
9191
productName = "SPM-Swift-Example";
9292
productReference = 891CF8042F68C57C0063792A /* SPM-Swift-Example.app */;
@@ -117,7 +117,6 @@
117117
mainGroup = 891CF7FB2F68C57C0063792A;
118118
minimizedProjectReferenceProxies = 1;
119119
packageReferences = (
120-
AA000001000000000000001A /* XCLocalSwiftPackageReference "../../../../../" */,
121120
AA000002000000000000002A /* XCLocalSwiftPackageReference "../../" */,
122121
);
123122
preferredProjectObjectVersion = 77;
@@ -358,27 +357,22 @@
358357
/* End XCConfigurationList section */
359358

360359
/* Begin XCLocalSwiftPackageReference section */
361-
AA000001000000000000001A /* XCLocalSwiftPackageReference "../../../../../" */ = {
362-
isa = XCLocalSwiftPackageReference;
363-
relativePath = ../../../../../;
364-
};
365360
AA000002000000000000002A /* XCLocalSwiftPackageReference "../../" */ = {
366361
isa = XCLocalSwiftPackageReference;
367362
relativePath = ../../;
368363
};
369364
/* End XCLocalSwiftPackageReference section */
370365

371366
/* Begin XCSwiftPackageProductDependency section */
372-
AA000003000000000000003A /* mParticle-Apple-SDK */ = {
373-
isa = XCSwiftPackageProductDependency;
374-
package = AA000001000000000000001A /* XCLocalSwiftPackageReference "../../../../../" */;
375-
productName = "mParticle-Apple-SDK";
376-
};
377367
AA000004000000000000004A /* mParticle-Rokt */ = {
378368
isa = XCSwiftPackageProductDependency;
379369
package = AA000002000000000000002A /* XCLocalSwiftPackageReference "../../" */;
380370
productName = "mParticle-Rokt";
381371
};
372+
B34E89952F8087DA003A0ADE /* mParticle-Apple-SDK */ = {
373+
isa = XCSwiftPackageProductDependency;
374+
productName = "mParticle-Apple-SDK";
375+
};
382376
/* End XCSwiftPackageProductDependency section */
383377
};
384378
rootObject = 891CF7FC2F68C57C0063792A /* Project object */;

0 commit comments

Comments
 (0)