diff --git a/BrazeKit.podspec b/BrazeKit.podspec
index 851cda5a93..71b69adc2e 100644
--- a/BrazeKit.podspec
+++ b/BrazeKit.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'BrazeKit'
- s.version = '5.4.0'
+ s.version = '5.5.0'
s.summary = 'Braze Main SDK library providing support for analytics and push notifications.'
s.homepage = 'https://braze.com'
@@ -9,8 +9,8 @@ Pod::Spec.new do |s|
s.authors = 'Braze, Inc.'
s.source = {
- :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.4.0/BrazeKit-CocoaPods.zip',
- :sha256 => '4228d1670c639b4139d6530d41c06e0ac670f0f4f6f517e836168aae007fbe42'
+ :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.5.0/BrazeKit-CocoaPods.zip',
+ :sha256 => '13e15c450429fa081c0745f51e8382030781c72d8f46657aa7a7af726d7713db'
}
s.swift_version = '5.0'
diff --git a/BrazeLocation.podspec b/BrazeLocation.podspec
index 5c17d9f4f4..d245c94126 100644
--- a/BrazeLocation.podspec
+++ b/BrazeLocation.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'BrazeLocation'
- s.version = '5.4.0'
+ s.version = '5.5.0'
s.summary = 'Braze location library providing support for location analytics and geofence monitoring.'
s.homepage = 'https://braze.com'
@@ -9,8 +9,8 @@ Pod::Spec.new do |s|
s.authors = 'Braze, Inc.'
s.source = {
- :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.4.0/BrazeLocation-CocoaPods.zip',
- :sha256 => '26f732381af0031999ea19bb4386cfe999db4d467786f18449f075e82c55f6d6'
+ :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.5.0/BrazeLocation-CocoaPods.zip',
+ :sha256 => '3c7303f70658aa07ff8cff7442e9f1f64e2e5e09cdb826012090b07c291d6073'
}
s.swift_version = '5.0'
@@ -21,5 +21,5 @@ Pod::Spec.new do |s|
# Depends on BrazeKit because BrazeKit includes the internal _BrazeLocationClient symbols required
# for linking against BrazeLocation.
- s.dependency 'BrazeKit', '5.4.0'
+ s.dependency 'BrazeKit', '5.5.0'
end
diff --git a/BrazeNotificationService.podspec b/BrazeNotificationService.podspec
index 15803f5a05..e2b8b59118 100644
--- a/BrazeNotificationService.podspec
+++ b/BrazeNotificationService.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'BrazeNotificationService'
- s.version = '5.4.0'
+ s.version = '5.5.0'
s.summary = 'Braze notification service extension library providing support for Rich Push notifications.'
s.homepage = 'https://braze.com'
@@ -9,8 +9,8 @@ Pod::Spec.new do |s|
s.authors = 'Braze, Inc.'
s.source = {
- :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.4.0/BrazeNotificationService-CocoaPods.zip',
- :sha256 => '3ad4ccb1557c338f8a5018731aa6b543f523326cc54a055127a8c66d5ff212d4'
+ :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.5.0/BrazeNotificationService-CocoaPods.zip',
+ :sha256 => '47333461d0e12918222d755348158c496d9f296b9b5bf2e71b15d40b725ffcfb'
}
s.swift_version = '5.0'
diff --git a/BrazePushStory.podspec b/BrazePushStory.podspec
index 228f11c529..d6bcea2d24 100644
--- a/BrazePushStory.podspec
+++ b/BrazePushStory.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'BrazePushStory'
- s.version = '5.4.0'
+ s.version = '5.5.0'
s.summary = 'Braze notification content extension library providing support for Push Stories.'
s.homepage = 'https://braze.com'
@@ -9,8 +9,8 @@ Pod::Spec.new do |s|
s.authors = 'Braze, Inc.'
s.source = {
- :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.4.0/BrazePushStory-CocoaPods.zip',
- :sha256 => '47d56c8a5a79e72d2a87744d8f3207ee3a09943f460cf7d11d4a12ff97df1cdd'
+ :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.5.0/BrazePushStory-CocoaPods.zip',
+ :sha256 => '563764ac805374f75df403fa91c13b5611d8eb8aad4fde64dc385b3c0623f68c'
}
s.swift_version = '5.0'
diff --git a/BrazeUI.podspec b/BrazeUI.podspec
index 5e6d4e3b57..8860de85bc 100644
--- a/BrazeUI.podspec
+++ b/BrazeUI.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'BrazeUI'
- s.version = '5.4.0'
+ s.version = '5.5.0'
s.summary = 'Braze-provided user interface library for In-App Messages.'
s.homepage = 'https://braze.com'
@@ -8,7 +8,7 @@ Pod::Spec.new do |s|
s.license = { :type => 'Commercial' }
s.authors = 'Braze, Inc.'
- s.source = { :git => 'https://github.com/braze-inc/braze-swift-sdk.git', :tag => '5.4.0' }
+ s.source = { :git => 'https://github.com/braze-inc/braze-swift-sdk.git', :tag => '5.5.0' }
s.swift_version = '5.0'
s.ios.deployment_target = '10.0'
@@ -17,5 +17,5 @@ Pod::Spec.new do |s|
s.source_files = 'Sources/BrazeUI/**/*.swift'
s.resource_bundles = { 'BrazeUI' => 'Sources/BrazeUI/Resources/**/*' }
- s.dependency 'BrazeKit', '5.4.0'
+ s.dependency 'BrazeKit', '5.5.0'
end
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7feea1aefe..40d6eba564 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,23 @@
+## 5.5.0
+
+##### Added
+- Adds support for host apps written in Objective-C.
+ - Braze Objective-C types start either with `BRZ` or `Braze`, e.g.:
+ - `Braze`
+ - `BrazeDelegate`
+ - `BRZContentCardRaw`
+ - See our Objective-C [Examples](Examples/) project.
+- Adds [`BrazeDelegate.braze(_:noMatchingTriggerForEvent:)`](https://braze-inc.github.io/braze-swift-sdk/documentation/brazekit/brazedelegate/braze(_:nomatchingtriggerforevent:)-8rt7y) which is called if no Braze in-app message is triggered for a given event.
+
+##### Changed
+- In `Braze.Configuration.Api`:
+ - Renamed `SdkMetadata` to `SDKMetadata`.
+ - Renamed `addSdkMetadata(_:)` to `addSDKMetadata(_:)`.
+- In `Braze.InAppMessage`:
+ - Renamed `Themes.default` to `Themes.defaults`.
+ - Renamed `ClickAction.uri` to `ClickAction.url`.
+ - Renamed `ClickAction.uri(_:useWebView:)` to `ClickAction.url(_:useWebView:)`.
+
## 5.4.0
##### Fixed
@@ -29,7 +49,7 @@
- Available on iOS and tvOS.
- Adds [`Braze.InAppMessage.ClickAction.uri`](https://braze-inc.github.io/braze-swift-sdk/documentation/brazekit/braze/inappmessage/clickaction/uri) for direct access.
- Adds [`Braze.ContentCard.ClickAction.uri`](https://braze-inc.github.io/braze-swift-sdk/documentation/brazekit/braze/contentcard/clickaction/uri/) for direct access.
-- Adds [`Braze.deviceId(queue:completion:)`](https://braze-inc.github.io/braze-swift-sdk/documentation/brazekit/brazekit/braze/deviceid(queue:completion:)) to retrieve the device identifier used by Braze.
+- Adds [`Braze.deviceId(queue:completion:)`](https://braze-inc.github.io/braze-swift-sdk/documentation/brazekit/braze/deviceid(queue:completion:)) to retrieve the device identifier used by Braze.
## 5.3.0
@@ -80,7 +100,8 @@ The Braze Swift SDK is set to replace the [current Braze iOS SDK](https://github
### Current limitations
The following features are not supported yet:
-- Objective-C integration
+- ~~Objective-C integration~~
+ - Added in [5.5.0](#550)
- ~~tvOS integration~~
- Added in [5.3.0](#530)
- News Feed
diff --git a/Examples/ObjC/Examples-CocoaPods.xcodeproj/project.pbxproj b/Examples/ObjC/Examples-CocoaPods.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..625730200e
--- /dev/null
+++ b/Examples/ObjC/Examples-CocoaPods.xcodeproj/project.pbxproj
@@ -0,0 +1,1652 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 51;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 021241249E788C93F8B9B58C /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; };
+ 02D39B681AC38D3E38167BC9 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; };
+ 0575EAD45DC713FDFA430364 /* CustomInAppMessagePresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2697E60398EE452C7E362B83 /* CustomInAppMessagePresenter.m */; };
+ 0AD73B7EB7D9DC710E0CC91D /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; };
+ 0BE8CE4982452A0E74D7F309 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 52F765C494ACFF150F0A76C4 /* Readme.m */; };
+ 0DE3276319B3F7EDE9E5761D /* NotificationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61DA261A3969E80D4910B919 /* NotificationViewController.swift */; };
+ 14ED490CA83487F672B6CA64 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; };
+ 161DC1259C44AD89479BA698 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA064323F91A22F4E14CAE9D /* NotificationService.swift */; };
+ 181CEE421636AF991665AF53 /* AuthenticationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 11D86AE9D1DC590AC4694323 /* AuthenticationManager.m */; };
+ 18DE204B580AF59319172A34 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; };
+ 1EB7F46010C2EE195B7F82DA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; };
+ 2004486C1F497F0D78D3C3C7 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CABCDD10D6E23AB146F9F7BA /* LaunchScreen.storyboard */; };
+ 210B445D7948A3019E0B61DE /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; };
+ 21406C5977E35E2DB91079C1 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B0E04E20E4B1C458222BA1 /* Readme.m */; };
+ 2198B5052B89F561E1408347 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5A56AB422F8DA782A8D2B6FD /* LaunchScreen.storyboard */; };
+ 237398E27F20D11B4A8D6F32 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; };
+ 2599D92D219E7BB320EB918C /* CardsInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CF4B96FFF47505E424237B85 /* CardsInfoViewController.m */; };
+ 2A65F13CBADEAEA072B1962A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CABCDD10D6E23AB146F9F7BA /* LaunchScreen.storyboard */; };
+ 30D7A569B1A652D533C6DFF4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CABCDD10D6E23AB146F9F7BA /* LaunchScreen.storyboard */; };
+ 3170955318006DA2CDC1D371 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; };
+ 330538042DBA8D66FE29106B /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; };
+ 34C9C566ACB7B6220C782866 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5A56AB422F8DA782A8D2B6FD /* LaunchScreen.storyboard */; };
+ 3C8DEAC1C01DE222C1FD7715 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = C92AD7CCB90625B324C9E200 /* Readme.m */; };
+ 3CCF8C060E64864FF2F0FBC5 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; };
+ 406136EAB546AFD30FFF4326 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; };
+ 40BBC96C23C0D03C1876EFB3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; };
+ 40C2532843ABD07521BDA072 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 381A82D8567D19A639A65555 /* Readme.m */; };
+ 4668AEE87D6BFB57357E49F8 /* InAppMessageInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 763258DB970F0A96B2A3DF74 /* InAppMessageInfoViewController.m */; };
+ 4E6928C0008070173370990E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; };
+ 4E9C8479947558025D64171B /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; };
+ 4F93A8E59C746BA0FE66EFD6 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; };
+ 4FBBFDC7A8AD63635182DCCC /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; };
+ 5443B297E55EFFA3D9531EB5 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A9AF15EF29118835FEB5D5E2 /* AppDelegate.m */; };
+ 56E71FBF34C707A0C76D4E92 /* PushNotificationsServiceExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 40B660242E5E30D22F3AC51E /* PushNotificationsServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
+ 5752C25DC8C2CA0C0925C10F /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6208C00FB5F7F0284A26EF20 /* UserNotifications.framework */; };
+ 5EA1891740935FEB0EB49789 /* BRZGIFViewProvider+SDWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 645D4CFE35E1C189EF76D681 /* BRZGIFViewProvider+SDWebImage.m */; };
+ 60D9B416B69C17AD0FF5FD87 /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6208C00FB5F7F0284A26EF20 /* UserNotifications.framework */; };
+ 639A93232862A95314463DE5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; };
+ 656FFF89336D3AA397B40D7C /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = C92AD7CCB90625B324C9E200 /* Readme.m */; };
+ 6AA695612AC940383057198A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; };
+ 7440800FB6329FCB28FC0FD6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DCD5EA6DB57BDEF9D156AF3B /* AppDelegate.m */; };
+ 756350E7C92625894BC8B509 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; };
+ 7B7F572DEB2E96237482FFB3 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; };
+ 7BA952D41DC54C1A728AB539 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; };
+ 7BF8E94ED7F5FC6A1C24A470 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; };
+ 7E8AD3897D9983306EE938B9 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; };
+ 7FC56E25CCA1B6080699728A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; };
+ 8AA046F58DFE835A8DBDC2FB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; };
+ 8B29E2C7B7EB260EAC5AB91D /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CD0DE7DB00697D75457F7CE /* Readme.m */; };
+ 8F470EAC78320B9B5E3C2093 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; };
+ 90A4F6B53E0118D3661585D4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; };
+ 9ACDCF377DDDFE68EC46E40C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 201DC51A7B4BD5035790D967 /* AppDelegate.m */; };
+ A08302940AC13A1B149928CE /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; };
+ A2BE6EE947CA0EB7BB800F8C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B0DC0BEFE722FE52D53AA96B /* AppDelegate.m */; };
+ A59B5541D8BDA70A1818AFDB /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; };
+ A841C03E3FC310874204BBBF /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DCD5EA6DB57BDEF9D156AF3B /* AppDelegate.m */; };
+ AA9687A7D3DF585AC6F6D718 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 201DC51A7B4BD5035790D967 /* AppDelegate.m */; };
+ AB2FE63CFBECFD1045D16ED7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; };
+ AEDDEDC6F9B5D7838BE908D6 /* PushNotificationsContentExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 7EFD35FD440D538F5EB8F021 /* PushNotificationsContentExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
+ B20E5CC4144654C1689934FE /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; };
+ B23023008FC1FDB8D94A41F5 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 318B57C50A12DB5F02FC6224 /* AppDelegate.m */; };
+ BAA8122F4149259E86294F99 /* CustomInAppMessagePresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2697E60398EE452C7E362B83 /* CustomInAppMessagePresenter.m */; };
+ BC696EE76324DB0A73B65DE7 /* BRZGIFViewProvider+SDWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = AC38A6DD46A5E7EBC7B8FB4B /* BRZGIFViewProvider+SDWebImage.m */; };
+ BCE0FBAE8B29B501C5C77992 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 318B57C50A12DB5F02FC6224 /* AppDelegate.m */; };
+ C0D38B13A94DADB550966E38 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5A56AB422F8DA782A8D2B6FD /* LaunchScreen.storyboard */; };
+ C25E42027E9FF502BA7D7269 /* CardsInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CF4B96FFF47505E424237B85 /* CardsInfoViewController.m */; };
+ C650783920A53EDD98DD19E5 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CABCDD10D6E23AB146F9F7BA /* LaunchScreen.storyboard */; };
+ C6A06C3B17248E8369F21897 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C307795934847C752765580 /* Readme.m */; };
+ C75C09FC6605F02E7646AF0F /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B0E04E20E4B1C458222BA1 /* Readme.m */; };
+ CF19792AFCEF53A28612612B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; };
+ D0DECD56C8F8201D27F59B32 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; };
+ D1B4FEFA476833265065E137 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5A56AB422F8DA782A8D2B6FD /* LaunchScreen.storyboard */; };
+ D48FBF169A83BB8BCADCB80C /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EE8EFDC1CAFFB4F4CB5D00D /* Readme.m */; };
+ DAA18481E36225A541BF8091 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CABCDD10D6E23AB146F9F7BA /* LaunchScreen.storyboard */; };
+ DB825090EC9CD3D9BEB01EFA /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EE8EFDC1CAFFB4F4CB5D00D /* Readme.m */; };
+ E0941C6B0D49A073B0A87A0F /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; };
+ E4206A2DEA0A202587F0F715 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; };
+ E5D78AA4EE4F9494D6AA85FA /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C307795934847C752765580 /* Readme.m */; };
+ E63FFCC8439CC53E8F297431 /* UserNotificationsUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1874579DE7E406E73A3CB3A1 /* UserNotificationsUI.framework */; };
+ E93521F5478A08F3837B041D /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; };
+ E9B14BAEC929FC550EC4C235 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A9AF15EF29118835FEB5D5E2 /* AppDelegate.m */; };
+ E9E8435129B8C5C86F579395 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; };
+ EAD8D9FD10FB71AB1C44F22E /* AuthenticationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 11D86AE9D1DC590AC4694323 /* AuthenticationManager.m */; };
+ EB71881CFACEA23DC2CF8112 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; };
+ ECF4B3DD82D61470A3EFC3E6 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CABCDD10D6E23AB146F9F7BA /* LaunchScreen.storyboard */; };
+ EE1A489AA9350D6C14CBBBCE /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CABCDD10D6E23AB146F9F7BA /* LaunchScreen.storyboard */; };
+ EE9EDAC6D65BA1F0AC69EE89 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 75054C03D57540CE91A71920 /* AppDelegate.m */; };
+ F2395EC507EC1C960CFC6118 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; };
+ F331DB6CEE9AAC6AC1252F1D /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; };
+ F3EF4E7F2CFCC0512F4F642F /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; };
+ F49C339077170329AC8926A3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; };
+ F527CC79A52C51B1D2B30FAF /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; };
+ F6077FC0D214B2BA1BFBD720 /* CheckoutViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 133CC7FED120DA4BC4F63478 /* CheckoutViewController.m */; };
+ F81FA5EDF6E6E785AD09482B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6AE76A96578D95F43B9C0849 /* AppDelegate.m */; };
+ FDFE0B5AD6C85ABC76895E1F /* CheckoutViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 133CC7FED120DA4BC4F63478 /* CheckoutViewController.m */; };
+ FE9AA3224EFAE15896E7A1DA /* InAppMessageInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 763258DB970F0A96B2A3DF74 /* InAppMessageInfoViewController.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 2E6E453ED2C838C4006D08F8 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = C9F9231105531CE428ADD921 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = C7435EF6816986F173CAB4E9;
+ remoteInfo = PushNotificationsContentExtension;
+ };
+ 33F46D6820611AA9F861E4F9 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = C9F9231105531CE428ADD921 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = CCD5FB3CEF0797FD385EA7F3;
+ remoteInfo = PushNotificationsServiceExtension;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 59784E19DCC3D0A5254ECC61 /* Embed App Extensions */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 13;
+ files = (
+ 56E71FBF34C707A0C76D4E92 /* PushNotificationsServiceExtension.appex in Embed App Extensions */,
+ AEDDEDC6F9B5D7838BE908D6 /* PushNotificationsContentExtension.appex in Embed App Extensions */,
+ );
+ name = "Embed App Extensions";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ 05A5CB32692A4493359A70F2 /* InAppMessages-Custom-UI.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "InAppMessages-Custom-UI.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 0CD0DE7DB00697D75457F7CE /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; };
+ 11D86AE9D1DC590AC4694323 /* AuthenticationManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AuthenticationManager.m; sourceTree = ""; };
+ 133CC7FED120DA4BC4F63478 /* CheckoutViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CheckoutViewController.m; sourceTree = ""; };
+ 14EDA84CD87233E1D5B6725B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ 1874579DE7E406E73A3CB3A1 /* UserNotificationsUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotificationsUI.framework; path = System/Library/Frameworks/UserNotificationsUI.framework; sourceTree = SDKROOT; };
+ 1CA06BB2ED58DC38DE098EEB /* CustomInAppMessagePresenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CustomInAppMessagePresenter.h; sourceTree = ""; };
+ 201DC51A7B4BD5035790D967 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ 249AA3BCC2DA49BBBD853C61 /* InAppMessageInfoViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InAppMessageInfoViewController.h; sourceTree = ""; };
+ 2697E60398EE452C7E362B83 /* CustomInAppMessagePresenter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CustomInAppMessagePresenter.m; sourceTree = ""; };
+ 2D50867A0DB9C8686F63A371 /* InAppMessages.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = InAppMessages.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 318B57C50A12DB5F02FC6224 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ 34DB46A770028DFE645A3AE4 /* Location.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Location.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 381A82D8567D19A639A65555 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; };
+ 3EE8EFDC1CAFFB4F4CB5D00D /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; };
+ 40B660242E5E30D22F3AC51E /* PushNotificationsServiceExtension.appex */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.app-extension"; path = PushNotificationsServiceExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
+ 42BA0F61D883E0421B3FA7CA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ 4E9C1C30C3119B822A6C482D /* ReadmeViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReadmeViewController.h; sourceTree = ""; };
+ 52B0E04E20E4B1C458222BA1 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; };
+ 52EBE792F20E4F26BC0E7F48 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ 52F765C494ACFF150F0A76C4 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; };
+ 61DA261A3969E80D4910B919 /* NotificationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationViewController.swift; sourceTree = ""; };
+ 6208C00FB5F7F0284A26EF20 /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; };
+ 645D4CFE35E1C189EF76D681 /* BRZGIFViewProvider+SDWebImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "BRZGIFViewProvider+SDWebImage.m"; sourceTree = ""; };
+ 6832319B66FB76CAA84519FA /* Location.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Location.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 6AE76A96578D95F43B9C0849 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ 75054C03D57540CE91A71920 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ 763258DB970F0A96B2A3DF74 /* InAppMessageInfoViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InAppMessageInfoViewController.m; sourceTree = ""; };
+ 77273E47E0A73317EF0235A7 /* Credentials.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Credentials.m; sourceTree = ""; };
+ 7EFD35FD440D538F5EB8F021 /* PushNotificationsContentExtension.appex */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.app-extension"; path = PushNotificationsContentExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
+ 80CF36610D640D20AB35926E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ 858AE4349E1D1D1849DB97B4 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ 8854CADF86F02FA64B2CC3F1 /* ContentCards-Custom-UI.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "ContentCards-Custom-UI.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 8C307795934847C752765580 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; };
+ 9E2B80BBE3951963FBA6BBD3 /* Analytics.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Analytics.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ A2AC34AC6990B2FA6CD647CC /* ReadmeAction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReadmeAction.h; sourceTree = ""; };
+ A37E3B0FA418AB843D26F7F9 /* PushNotifications.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = PushNotifications.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ A6EEBA52A1C6E13DE9B07326 /* BRZGIFViewProvider+SDWebImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BRZGIFViewProvider+SDWebImage.h"; sourceTree = ""; };
+ A77BCD95413ADCF8578235CE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ A9AF15EF29118835FEB5D5E2 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ AC38A6DD46A5E7EBC7B8FB4B /* BRZGIFViewProvider+SDWebImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "BRZGIFViewProvider+SDWebImage.m"; sourceTree = ""; };
+ B0DC0BEFE722FE52D53AA96B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ BA064323F91A22F4E14CAE9D /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; };
+ BA37FE8457A48CD8683BE79A /* CardsInfoViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CardsInfoViewController.h; sourceTree = ""; };
+ C0EA46B7F46275141BF76209 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
+ C78E0B5A5D52F990511A4091 /* ContentCards-Custom-UI.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "ContentCards-Custom-UI.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ C92AD7CCB90625B324C9E200 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; };
+ C9C1B6158983BCB0C593DAE4 /* ContentCards.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = ContentCards.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ CAF8A0D7B315DF4FF0A9CFC8 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ CD47A5A37513C58A6E380918 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ CF4B96FFF47505E424237B85 /* CardsInfoViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CardsInfoViewController.m; sourceTree = ""; };
+ D1FC7DF6067EFA59329D3B00 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ D6EF14C19329871CCA47A1AF /* BRZGIFViewProvider+SDWebImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BRZGIFViewProvider+SDWebImage.h"; sourceTree = ""; };
+ DCD5EA6DB57BDEF9D156AF3B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ DE3608B9E460175A349CDB87 /* Analytics.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Analytics.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReadmeViewController.m; sourceTree = ""; };
+ EFB767A3E5938B98AE96F91B /* AuthenticationManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AuthenticationManager.h; sourceTree = ""; };
+ F6DB4DC3F7A190B73055DD78 /* CheckoutViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CheckoutViewController.h; sourceTree = ""; };
+ FE50398A21EB6A33EE9874A2 /* InAppMessages-Custom-UI.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "InAppMessages-Custom-UI.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 9C12D40A1EC1FBCBD6CA4D4C /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 5752C25DC8C2CA0C0925C10F /* UserNotifications.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E5DFE50012E3C956DEE08F20 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 60D9B416B69C17AD0FF5FD87 /* UserNotifications.framework in Frameworks */,
+ E63FFCC8439CC53E8F297431 /* UserNotificationsUI.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 4F38F2ACA591DCA04EF16BB1 /* Location */ = {
+ isa = PBXGroup;
+ children = (
+ CAF8A0D7B315DF4FF0A9CFC8 /* AppDelegate.h */,
+ 318B57C50A12DB5F02FC6224 /* AppDelegate.m */,
+ 8C307795934847C752765580 /* Readme.m */,
+ );
+ name = Location;
+ path = Sources/Location;
+ sourceTree = "";
+ };
+ 51FBDA444B2130ED53F050CB /* Analytics */ = {
+ isa = PBXGroup;
+ children = (
+ D1FC7DF6067EFA59329D3B00 /* AppDelegate.h */,
+ 201DC51A7B4BD5035790D967 /* AppDelegate.m */,
+ EFB767A3E5938B98AE96F91B /* AuthenticationManager.h */,
+ 11D86AE9D1DC590AC4694323 /* AuthenticationManager.m */,
+ F6DB4DC3F7A190B73055DD78 /* CheckoutViewController.h */,
+ 133CC7FED120DA4BC4F63478 /* CheckoutViewController.m */,
+ C92AD7CCB90625B324C9E200 /* Readme.m */,
+ );
+ name = Analytics;
+ path = Sources/Analytics;
+ sourceTree = "";
+ };
+ 5F61F41FECA7453CB4C2C3CA = {
+ isa = PBXGroup;
+ children = (
+ EB043806B7BB06DCA25E0177 /* Common */,
+ 51FBDA444B2130ED53F050CB /* Analytics */,
+ EE1BF73C17001D2912250407 /* ContentCards */,
+ 6F112DA3865BFE3961698859 /* ContentCards-Custom-UI */,
+ 9AA2DA5B878C1242DBDD0410 /* InAppMessages */,
+ E3BAE1A02E5A97AD717C4DE1 /* InAppMessages-Custom-UI */,
+ 4F38F2ACA591DCA04EF16BB1 /* Location */,
+ E956091874C7F622B207B35A /* PushNotifications */,
+ 79BD163F0CE766FD84A15D5A /* PushNotificationsContentExtension */,
+ E239AFF5E3F3085D7A50AFF6 /* PushNotificationsServiceExtension */,
+ DDE0D6627F8681F53997C26F /* Frameworks */,
+ 944D5C0BF6DC0B28ACDA2036 /* Products */,
+ );
+ sourceTree = "";
+ };
+ 6F112DA3865BFE3961698859 /* ContentCards-Custom-UI */ = {
+ isa = PBXGroup;
+ children = (
+ 80CF36610D640D20AB35926E /* AppDelegate.h */,
+ DCD5EA6DB57BDEF9D156AF3B /* AppDelegate.m */,
+ BA37FE8457A48CD8683BE79A /* CardsInfoViewController.h */,
+ CF4B96FFF47505E424237B85 /* CardsInfoViewController.m */,
+ 52B0E04E20E4B1C458222BA1 /* Readme.m */,
+ );
+ name = "ContentCards-Custom-UI";
+ path = "Sources/ContentCards-Custom-UI";
+ sourceTree = "";
+ };
+ 79BD163F0CE766FD84A15D5A /* PushNotificationsContentExtension */ = {
+ isa = PBXGroup;
+ children = (
+ 61DA261A3969E80D4910B919 /* NotificationViewController.swift */,
+ );
+ name = PushNotificationsContentExtension;
+ path = Sources/PushNotificationsContentExtension;
+ sourceTree = "";
+ };
+ 7D73AC8BFC703A7B9ECA6177 /* tvOS */ = {
+ isa = PBXGroup;
+ children = (
+ 5A56AB422F8DA782A8D2B6FD /* LaunchScreen.storyboard */,
+ );
+ path = tvOS;
+ sourceTree = "";
+ };
+ 944D5C0BF6DC0B28ACDA2036 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 9E2B80BBE3951963FBA6BBD3 /* Analytics.app */,
+ DE3608B9E460175A349CDB87 /* Analytics.app */,
+ 8854CADF86F02FA64B2CC3F1 /* ContentCards-Custom-UI.app */,
+ C78E0B5A5D52F990511A4091 /* ContentCards-Custom-UI.app */,
+ C9C1B6158983BCB0C593DAE4 /* ContentCards.app */,
+ 05A5CB32692A4493359A70F2 /* InAppMessages-Custom-UI.app */,
+ FE50398A21EB6A33EE9874A2 /* InAppMessages-Custom-UI.app */,
+ 2D50867A0DB9C8686F63A371 /* InAppMessages.app */,
+ 6832319B66FB76CAA84519FA /* Location.app */,
+ 34DB46A770028DFE645A3AE4 /* Location.app */,
+ A37E3B0FA418AB843D26F7F9 /* PushNotifications.app */,
+ 7EFD35FD440D538F5EB8F021 /* PushNotificationsContentExtension.appex */,
+ 40B660242E5E30D22F3AC51E /* PushNotificationsServiceExtension.appex */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 9AA2DA5B878C1242DBDD0410 /* InAppMessages */ = {
+ isa = PBXGroup;
+ children = (
+ 858AE4349E1D1D1849DB97B4 /* AppDelegate.h */,
+ 6AE76A96578D95F43B9C0849 /* AppDelegate.m */,
+ D6EF14C19329871CCA47A1AF /* BRZGIFViewProvider+SDWebImage.h */,
+ AC38A6DD46A5E7EBC7B8FB4B /* BRZGIFViewProvider+SDWebImage.m */,
+ 381A82D8567D19A639A65555 /* Readme.m */,
+ );
+ name = InAppMessages;
+ path = Sources/InAppMessages;
+ sourceTree = "";
+ };
+ CFAFCFEE58CC8AA1F0BDA699 /* iOS */ = {
+ isa = PBXGroup;
+ children = (
+ CABCDD10D6E23AB146F9F7BA /* LaunchScreen.storyboard */,
+ );
+ path = iOS;
+ sourceTree = "";
+ };
+ DDE0D6627F8681F53997C26F /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 6208C00FB5F7F0284A26EF20 /* UserNotifications.framework */,
+ 1874579DE7E406E73A3CB3A1 /* UserNotificationsUI.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ E239AFF5E3F3085D7A50AFF6 /* PushNotificationsServiceExtension */ = {
+ isa = PBXGroup;
+ children = (
+ BA064323F91A22F4E14CAE9D /* NotificationService.swift */,
+ );
+ name = PushNotificationsServiceExtension;
+ path = Sources/PushNotificationsServiceExtension;
+ sourceTree = "";
+ };
+ E3BAE1A02E5A97AD717C4DE1 /* InAppMessages-Custom-UI */ = {
+ isa = PBXGroup;
+ children = (
+ CD47A5A37513C58A6E380918 /* AppDelegate.h */,
+ A9AF15EF29118835FEB5D5E2 /* AppDelegate.m */,
+ 1CA06BB2ED58DC38DE098EEB /* CustomInAppMessagePresenter.h */,
+ 2697E60398EE452C7E362B83 /* CustomInAppMessagePresenter.m */,
+ 249AA3BCC2DA49BBBD853C61 /* InAppMessageInfoViewController.h */,
+ 763258DB970F0A96B2A3DF74 /* InAppMessageInfoViewController.m */,
+ 3EE8EFDC1CAFFB4F4CB5D00D /* Readme.m */,
+ );
+ name = "InAppMessages-Custom-UI";
+ path = "Sources/InAppMessages-Custom-UI";
+ sourceTree = "";
+ };
+ E956091874C7F622B207B35A /* PushNotifications */ = {
+ isa = PBXGroup;
+ children = (
+ 52EBE792F20E4F26BC0E7F48 /* AppDelegate.h */,
+ B0DC0BEFE722FE52D53AA96B /* AppDelegate.m */,
+ 52F765C494ACFF150F0A76C4 /* Readme.m */,
+ );
+ name = PushNotifications;
+ path = Sources/PushNotifications;
+ sourceTree = "";
+ };
+ EB043806B7BB06DCA25E0177 /* Common */ = {
+ isa = PBXGroup;
+ children = (
+ 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */,
+ 77273E47E0A73317EF0235A7 /* Credentials.m */,
+ C0EA46B7F46275141BF76209 /* main.m */,
+ A2AC34AC6990B2FA6CD647CC /* ReadmeAction.h */,
+ 4E9C1C30C3119B822A6C482D /* ReadmeViewController.h */,
+ E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */,
+ CFAFCFEE58CC8AA1F0BDA699 /* iOS */,
+ 7D73AC8BFC703A7B9ECA6177 /* tvOS */,
+ );
+ name = Common;
+ path = Sources/Common;
+ sourceTree = "";
+ };
+ EE1BF73C17001D2912250407 /* ContentCards */ = {
+ isa = PBXGroup;
+ children = (
+ 14EDA84CD87233E1D5B6725B /* AppDelegate.h */,
+ 75054C03D57540CE91A71920 /* AppDelegate.m */,
+ A6EEBA52A1C6E13DE9B07326 /* BRZGIFViewProvider+SDWebImage.h */,
+ 645D4CFE35E1C189EF76D681 /* BRZGIFViewProvider+SDWebImage.m */,
+ 0CD0DE7DB00697D75457F7CE /* Readme.m */,
+ );
+ name = ContentCards;
+ path = Sources/ContentCards;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 0FD7FC35072A5B75852D15F7 /* InAppMessages-Custom-UI-iOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 72920B71D538BFAF8A028D09 /* Build configuration list for PBXNativeTarget "InAppMessages-Custom-UI-iOS" */;
+ buildPhases = (
+ 1FF8AFF6708BEE3883392041 /* Sources */,
+ 39044F4BABFFCBF62ACFCECB /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "InAppMessages-Custom-UI-iOS";
+ productName = "InAppMessages-Custom-UI-iOS";
+ productReference = 05A5CB32692A4493359A70F2 /* InAppMessages-Custom-UI.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 177B908F6B162DDA447880C8 /* ContentCards-Custom-UI-tvOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 38CA0A5742C4A4988D4584C2 /* Build configuration list for PBXNativeTarget "ContentCards-Custom-UI-tvOS" */;
+ buildPhases = (
+ 070EDE6E9735E579169F2D68 /* Sources */,
+ 52CCB0B63165D1463D683A73 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "ContentCards-Custom-UI-tvOS";
+ productName = "ContentCards-Custom-UI-tvOS";
+ productReference = C78E0B5A5D52F990511A4091 /* ContentCards-Custom-UI.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 1A7E9979FC152DE4F7D5DC2A /* InAppMessages */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = C8DA1DB107E7EE64BBBAEBE7 /* Build configuration list for PBXNativeTarget "InAppMessages" */;
+ buildPhases = (
+ E446E3B55477F3BA5FB625C4 /* Sources */,
+ 324A65B0C1348D482EBD2C51 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = InAppMessages;
+ productName = InAppMessages;
+ productReference = 2D50867A0DB9C8686F63A371 /* InAppMessages.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 284840096E199840E3A733BC /* Location-tvOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B76990766EAEC18717669D6F /* Build configuration list for PBXNativeTarget "Location-tvOS" */;
+ buildPhases = (
+ 5FEBF68A041A50636A7C63D7 /* Sources */,
+ 78CBE3D7946A65CD24DD6D8A /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "Location-tvOS";
+ productName = "Location-tvOS";
+ productReference = 34DB46A770028DFE645A3AE4 /* Location.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 4A34648A0491D5D28D9A7E8A /* InAppMessages-Custom-UI-tvOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E26727234EAA2C9FFB557AF2 /* Build configuration list for PBXNativeTarget "InAppMessages-Custom-UI-tvOS" */;
+ buildPhases = (
+ 923462222067359F78BABE34 /* Sources */,
+ 3FC37E07E197AB909115976A /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "InAppMessages-Custom-UI-tvOS";
+ productName = "InAppMessages-Custom-UI-tvOS";
+ productReference = FE50398A21EB6A33EE9874A2 /* InAppMessages-Custom-UI.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 726E40C6A0B9D7595B53FE5E /* PushNotifications */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 59402C8CB5DE66A776947595 /* Build configuration list for PBXNativeTarget "PushNotifications" */;
+ buildPhases = (
+ D2ACF4659AEA97A06A724AF3 /* Sources */,
+ B62AC56D63A64203ECF45AAE /* Resources */,
+ 59784E19DCC3D0A5254ECC61 /* Embed App Extensions */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 9D311561DBF39BC8DEEAF340 /* PBXTargetDependency */,
+ 1CEA284D6D77D29EF745D466 /* PBXTargetDependency */,
+ );
+ name = PushNotifications;
+ productName = PushNotifications;
+ productReference = A37E3B0FA418AB843D26F7F9 /* PushNotifications.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 9097C3EC847DC7AE4B1CA969 /* ContentCards */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 9D35AC44AE90C1C27CBF8577 /* Build configuration list for PBXNativeTarget "ContentCards" */;
+ buildPhases = (
+ C7726F7D79339C85CB8B1FDB /* Sources */,
+ 0607C6FAE74CA8A0F8E5224B /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = ContentCards;
+ productName = ContentCards;
+ productReference = C9C1B6158983BCB0C593DAE4 /* ContentCards.app */;
+ productType = "com.apple.product-type.application";
+ };
+ A0EF8DC5C1ED6288C32D3D23 /* Analytics-iOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 43414268546ED18E21E7E892 /* Build configuration list for PBXNativeTarget "Analytics-iOS" */;
+ buildPhases = (
+ F57A2A4DF2E99DAA2F0E38B4 /* Sources */,
+ 38AC76FC42776531F9D2414E /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "Analytics-iOS";
+ productName = "Analytics-iOS";
+ productReference = 9E2B80BBE3951963FBA6BBD3 /* Analytics.app */;
+ productType = "com.apple.product-type.application";
+ };
+ BC720D0A2A3B555DF4D1268A /* Location-iOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4CBDCD32BF67ACE4E2977EFA /* Build configuration list for PBXNativeTarget "Location-iOS" */;
+ buildPhases = (
+ DBA50E39A4B67698A1CA8F34 /* Sources */,
+ 7299DD69BA7DDA59FA7F954F /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "Location-iOS";
+ productName = "Location-iOS";
+ productReference = 6832319B66FB76CAA84519FA /* Location.app */;
+ productType = "com.apple.product-type.application";
+ };
+ C7435EF6816986F173CAB4E9 /* PushNotificationsContentExtension */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 03D1E503F9863A03CB17E53A /* Build configuration list for PBXNativeTarget "PushNotificationsContentExtension" */;
+ buildPhases = (
+ C7487814AD5323F755B1E524 /* Sources */,
+ E5DFE50012E3C956DEE08F20 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = PushNotificationsContentExtension;
+ productName = PushNotificationsContentExtension;
+ productReference = 7EFD35FD440D538F5EB8F021 /* PushNotificationsContentExtension.appex */;
+ productType = "com.apple.product-type.app-extension";
+ };
+ CCD5FB3CEF0797FD385EA7F3 /* PushNotificationsServiceExtension */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = D767F3158D7C98C16E53CE31 /* Build configuration list for PBXNativeTarget "PushNotificationsServiceExtension" */;
+ buildPhases = (
+ 9AD321D868E1638BA51BFDA7 /* Sources */,
+ 9C12D40A1EC1FBCBD6CA4D4C /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = PushNotificationsServiceExtension;
+ productName = PushNotificationsServiceExtension;
+ productReference = 40B660242E5E30D22F3AC51E /* PushNotificationsServiceExtension.appex */;
+ productType = "com.apple.product-type.app-extension";
+ };
+ E4E9F3507C9F70F681E5417F /* ContentCards-Custom-UI-iOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 33777E174E4CC017CCCB31A8 /* Build configuration list for PBXNativeTarget "ContentCards-Custom-UI-iOS" */;
+ buildPhases = (
+ 38F46412EEF2D23C9901E6A3 /* Sources */,
+ CD72E9C8C68A5D330D1ED959 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "ContentCards-Custom-UI-iOS";
+ productName = "ContentCards-Custom-UI-iOS";
+ productReference = 8854CADF86F02FA64B2CC3F1 /* ContentCards-Custom-UI.app */;
+ productType = "com.apple.product-type.application";
+ };
+ FDA0A7B4C40914EAF405D9FC /* Analytics-tvOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 33A0A8897465C6BD7C17C2E6 /* Build configuration list for PBXNativeTarget "Analytics-tvOS" */;
+ buildPhases = (
+ 51C89F4377C3E0870055A1CA /* Sources */,
+ 24EBDE35CCCBEFEFF53E707D /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "Analytics-tvOS";
+ productName = "Analytics-tvOS";
+ productReference = DE3608B9E460175A349CDB87 /* Analytics.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ C9F9231105531CE428ADD921 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 1200;
+ TargetAttributes = {
+ };
+ };
+ buildConfigurationList = 1D61EB4EA4EACDE551DB7D19 /* Build configuration list for PBXProject "Examples-CocoaPods" */;
+ compatibilityVersion = "Xcode 11.0";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ Base,
+ en,
+ );
+ mainGroup = 5F61F41FECA7453CB4C2C3CA;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ A0EF8DC5C1ED6288C32D3D23 /* Analytics-iOS */,
+ FDA0A7B4C40914EAF405D9FC /* Analytics-tvOS */,
+ 9097C3EC847DC7AE4B1CA969 /* ContentCards */,
+ E4E9F3507C9F70F681E5417F /* ContentCards-Custom-UI-iOS */,
+ 177B908F6B162DDA447880C8 /* ContentCards-Custom-UI-tvOS */,
+ 1A7E9979FC152DE4F7D5DC2A /* InAppMessages */,
+ 0FD7FC35072A5B75852D15F7 /* InAppMessages-Custom-UI-iOS */,
+ 4A34648A0491D5D28D9A7E8A /* InAppMessages-Custom-UI-tvOS */,
+ BC720D0A2A3B555DF4D1268A /* Location-iOS */,
+ 284840096E199840E3A733BC /* Location-tvOS */,
+ 726E40C6A0B9D7595B53FE5E /* PushNotifications */,
+ C7435EF6816986F173CAB4E9 /* PushNotificationsContentExtension */,
+ CCD5FB3CEF0797FD385EA7F3 /* PushNotificationsServiceExtension */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 0607C6FAE74CA8A0F8E5224B /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F49C339077170329AC8926A3 /* Assets.xcassets in Resources */,
+ 30D7A569B1A652D533C6DFF4 /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 24EBDE35CCCBEFEFF53E707D /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 1EB7F46010C2EE195B7F82DA /* Assets.xcassets in Resources */,
+ D1B4FEFA476833265065E137 /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 324A65B0C1348D482EBD2C51 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E4206A2DEA0A202587F0F715 /* Assets.xcassets in Resources */,
+ 2A65F13CBADEAEA072B1962A /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 38AC76FC42776531F9D2414E /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ AB2FE63CFBECFD1045D16ED7 /* Assets.xcassets in Resources */,
+ C650783920A53EDD98DD19E5 /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 39044F4BABFFCBF62ACFCECB /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CF19792AFCEF53A28612612B /* Assets.xcassets in Resources */,
+ EE1A489AA9350D6C14CBBBCE /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 3FC37E07E197AB909115976A /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EB71881CFACEA23DC2CF8112 /* Assets.xcassets in Resources */,
+ 2198B5052B89F561E1408347 /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 52CCB0B63165D1463D683A73 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 639A93232862A95314463DE5 /* Assets.xcassets in Resources */,
+ 34C9C566ACB7B6220C782866 /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 7299DD69BA7DDA59FA7F954F /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E9E8435129B8C5C86F579395 /* Assets.xcassets in Resources */,
+ 2004486C1F497F0D78D3C3C7 /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 78CBE3D7946A65CD24DD6D8A /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8AA046F58DFE835A8DBDC2FB /* Assets.xcassets in Resources */,
+ C0D38B13A94DADB550966E38 /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B62AC56D63A64203ECF45AAE /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 7FC56E25CCA1B6080699728A /* Assets.xcassets in Resources */,
+ DAA18481E36225A541BF8091 /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ CD72E9C8C68A5D330D1ED959 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 40BBC96C23C0D03C1876EFB3 /* Assets.xcassets in Resources */,
+ ECF4B3DD82D61470A3EFC3E6 /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 070EDE6E9735E579169F2D68 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 7440800FB6329FCB28FC0FD6 /* AppDelegate.m in Sources */,
+ C25E42027E9FF502BA7D7269 /* CardsInfoViewController.m in Sources */,
+ F2395EC507EC1C960CFC6118 /* Credentials.m in Sources */,
+ 21406C5977E35E2DB91079C1 /* Readme.m in Sources */,
+ E93521F5478A08F3837B041D /* ReadmeViewController.m in Sources */,
+ 4E6928C0008070173370990E /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 1FF8AFF6708BEE3883392041 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 5443B297E55EFFA3D9531EB5 /* AppDelegate.m in Sources */,
+ E0941C6B0D49A073B0A87A0F /* Credentials.m in Sources */,
+ BAA8122F4149259E86294F99 /* CustomInAppMessagePresenter.m in Sources */,
+ 4668AEE87D6BFB57357E49F8 /* InAppMessageInfoViewController.m in Sources */,
+ DB825090EC9CD3D9BEB01EFA /* Readme.m in Sources */,
+ 02D39B681AC38D3E38167BC9 /* ReadmeViewController.m in Sources */,
+ 7BA952D41DC54C1A728AB539 /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 38F46412EEF2D23C9901E6A3 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ A841C03E3FC310874204BBBF /* AppDelegate.m in Sources */,
+ 2599D92D219E7BB320EB918C /* CardsInfoViewController.m in Sources */,
+ 7B7F572DEB2E96237482FFB3 /* Credentials.m in Sources */,
+ C75C09FC6605F02E7646AF0F /* Readme.m in Sources */,
+ D0DECD56C8F8201D27F59B32 /* ReadmeViewController.m in Sources */,
+ A59B5541D8BDA70A1818AFDB /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 51C89F4377C3E0870055A1CA /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 9ACDCF377DDDFE68EC46E40C /* AppDelegate.m in Sources */,
+ 181CEE421636AF991665AF53 /* AuthenticationManager.m in Sources */,
+ F6077FC0D214B2BA1BFBD720 /* CheckoutViewController.m in Sources */,
+ 4FBBFDC7A8AD63635182DCCC /* Credentials.m in Sources */,
+ 656FFF89336D3AA397B40D7C /* Readme.m in Sources */,
+ 4F93A8E59C746BA0FE66EFD6 /* ReadmeViewController.m in Sources */,
+ F527CC79A52C51B1D2B30FAF /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 5FEBF68A041A50636A7C63D7 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B23023008FC1FDB8D94A41F5 /* AppDelegate.m in Sources */,
+ 330538042DBA8D66FE29106B /* Credentials.m in Sources */,
+ C6A06C3B17248E8369F21897 /* Readme.m in Sources */,
+ 210B445D7948A3019E0B61DE /* ReadmeViewController.m in Sources */,
+ 3170955318006DA2CDC1D371 /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 923462222067359F78BABE34 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E9B14BAEC929FC550EC4C235 /* AppDelegate.m in Sources */,
+ 18DE204B580AF59319172A34 /* Credentials.m in Sources */,
+ 0575EAD45DC713FDFA430364 /* CustomInAppMessagePresenter.m in Sources */,
+ FE9AA3224EFAE15896E7A1DA /* InAppMessageInfoViewController.m in Sources */,
+ D48FBF169A83BB8BCADCB80C /* Readme.m in Sources */,
+ F3EF4E7F2CFCC0512F4F642F /* ReadmeViewController.m in Sources */,
+ 90A4F6B53E0118D3661585D4 /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 9AD321D868E1638BA51BFDA7 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 161DC1259C44AD89479BA698 /* NotificationService.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ C7487814AD5323F755B1E524 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 0DE3276319B3F7EDE9E5761D /* NotificationViewController.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ C7726F7D79339C85CB8B1FDB /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EE9EDAC6D65BA1F0AC69EE89 /* AppDelegate.m in Sources */,
+ 5EA1891740935FEB0EB49789 /* BRZGIFViewProvider+SDWebImage.m in Sources */,
+ 021241249E788C93F8B9B58C /* Credentials.m in Sources */,
+ 8B29E2C7B7EB260EAC5AB91D /* Readme.m in Sources */,
+ 0AD73B7EB7D9DC710E0CC91D /* ReadmeViewController.m in Sources */,
+ 406136EAB546AFD30FFF4326 /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ D2ACF4659AEA97A06A724AF3 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ A2BE6EE947CA0EB7BB800F8C /* AppDelegate.m in Sources */,
+ 3CCF8C060E64864FF2F0FBC5 /* Credentials.m in Sources */,
+ 0BE8CE4982452A0E74D7F309 /* Readme.m in Sources */,
+ 4E9C8479947558025D64171B /* ReadmeViewController.m in Sources */,
+ B20E5CC4144654C1689934FE /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ DBA50E39A4B67698A1CA8F34 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ BCE0FBAE8B29B501C5C77992 /* AppDelegate.m in Sources */,
+ 8F470EAC78320B9B5E3C2093 /* Credentials.m in Sources */,
+ E5D78AA4EE4F9494D6AA85FA /* Readme.m in Sources */,
+ A08302940AC13A1B149928CE /* ReadmeViewController.m in Sources */,
+ 756350E7C92625894BC8B509 /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E446E3B55477F3BA5FB625C4 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F81FA5EDF6E6E785AD09482B /* AppDelegate.m in Sources */,
+ BC696EE76324DB0A73B65DE7 /* BRZGIFViewProvider+SDWebImage.m in Sources */,
+ F331DB6CEE9AAC6AC1252F1D /* Credentials.m in Sources */,
+ 40C2532843ABD07521BDA072 /* Readme.m in Sources */,
+ 14ED490CA83487F672B6CA64 /* ReadmeViewController.m in Sources */,
+ 7BF8E94ED7F5FC6A1C24A470 /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F57A2A4DF2E99DAA2F0E38B4 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ AA9687A7D3DF585AC6F6D718 /* AppDelegate.m in Sources */,
+ EAD8D9FD10FB71AB1C44F22E /* AuthenticationManager.m in Sources */,
+ FDFE0B5AD6C85ABC76895E1F /* CheckoutViewController.m in Sources */,
+ 7E8AD3897D9983306EE938B9 /* Credentials.m in Sources */,
+ 3C8DEAC1C01DE222C1FD7715 /* Readme.m in Sources */,
+ 237398E27F20D11B4A8D6F32 /* ReadmeViewController.m in Sources */,
+ 6AA695612AC940383057198A /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 1CEA284D6D77D29EF745D466 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = C7435EF6816986F173CAB4E9 /* PushNotificationsContentExtension */;
+ targetProxy = 2E6E453ED2C838C4006D08F8 /* PBXContainerItemProxy */;
+ };
+ 9D311561DBF39BC8DEEAF340 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = CCD5FB3CEF0797FD385EA7F3 /* PushNotificationsServiceExtension */;
+ targetProxy = 33F46D6820611AA9F861E4F9 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 5A56AB422F8DA782A8D2B6FD /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 42BA0F61D883E0421B3FA7CA /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+ CABCDD10D6E23AB146F9F7BA /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ A77BCD95413ADCF8578235CE /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 0B6E144276BF004EFE80A784 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = "Sources/ContentCards-Custom-UI/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.ContentCards-Custom-UI-iOS";
+ PRODUCT_NAME = "ContentCards-Custom-UI";
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 0B782479BDDFAA91B90B6411 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = "Sources/InAppMessages-Custom-UI/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.InAppMessages-Custom-UI-iOS";
+ PRODUCT_NAME = "InAppMessages-Custom-UI";
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ 0DB286FC893227921592442C /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INFOPLIST_FILE = Sources/PushNotificationsServiceExtension/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@executable_path/../../Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications.PushNotificationsServiceExtension;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ 0FF3E9103BDC67C9723BD0CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/ContentCards/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.ContentCards;
+ PRODUCT_NAME = ContentCards;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 1CE2539A10E8624E8EDD3601 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ INFOPLIST_FILE = "Sources/InAppMessages-Custom-UI/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.InAppMessages-Custom-UI-tvOS";
+ PRODUCT_NAME = "InAppMessages-Custom-UI";
+ SDKROOT = appletvos;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Release;
+ };
+ 2178EDBFBF71828E507601C1 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ INFOPLIST_FILE = "Sources/InAppMessages-Custom-UI/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.InAppMessages-Custom-UI-tvOS";
+ PRODUCT_NAME = "InAppMessages-Custom-UI";
+ SDKROOT = appletvos;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Debug;
+ };
+ 277ABE8F9A11018387A77412 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ INFOPLIST_FILE = Sources/Location/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Location-tvOS";
+ PRODUCT_NAME = Location;
+ SDKROOT = appletvos;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Debug;
+ };
+ 4BCF9BD39CEB19E634B6FD81 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/InAppMessages/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.InAppMessages;
+ PRODUCT_NAME = InAppMessages;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 4EBD32EE3B16C9EBF7493F73 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/Analytics/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Analytics-iOS";
+ PRODUCT_NAME = Analytics;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 4FCE20B3E84CE39D624EFA02 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/InAppMessages/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.InAppMessages;
+ PRODUCT_NAME = InAppMessages;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ 508970482D723EDFFD096AB1 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/ContentCards/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.ContentCards;
+ PRODUCT_NAME = ContentCards;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ 61077A56E64ADBA96CA8CE0C /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ INFOPLIST_FILE = Sources/Location/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Location-tvOS";
+ PRODUCT_NAME = Location;
+ SDKROOT = appletvos;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Release;
+ };
+ 67E21615E4F6D7BFAA160A31 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ INFOPLIST_FILE = "Sources/ContentCards-Custom-UI/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.ContentCards-Custom-UI-tvOS";
+ PRODUCT_NAME = "ContentCards-Custom-UI";
+ SDKROOT = appletvos;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Release;
+ };
+ 74B3175DE3731381F52D100D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/Location/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Location-iOS";
+ PRODUCT_NAME = Location;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 77420AEFB5CE84A97B402C8C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = "Sources/InAppMessages-Custom-UI/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.InAppMessages-Custom-UI-iOS";
+ PRODUCT_NAME = "InAppMessages-Custom-UI";
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 947EC0697CF1F01DDC513FD6 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "DEBUG=1",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TVOS_DEPLOYMENT_TARGET = 11.0;
+ };
+ name = Debug;
+ };
+ A653F811811645548266EC3A /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ INFOPLIST_FILE = Sources/Analytics/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Analytics-tvOS";
+ PRODUCT_NAME = Analytics;
+ SDKROOT = appletvos;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Release;
+ };
+ AEB7354D56CC1297356D6010 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/Location/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Location-iOS";
+ PRODUCT_NAME = Location;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ BA01071103F7280839CDFBF1 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ INFOPLIST_FILE = "Sources/ContentCards-Custom-UI/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.ContentCards-Custom-UI-tvOS";
+ PRODUCT_NAME = "ContentCards-Custom-UI";
+ SDKROOT = appletvos;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Debug;
+ };
+ C53D3849AB3D8DAE264A3A51 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INFOPLIST_FILE = Sources/PushNotificationsServiceExtension/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@executable_path/../../Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications.PushNotificationsServiceExtension;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ CFC0E247B97C5CEDBAF0B857 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_ENTITLEMENTS = Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements;
+ INFOPLIST_FILE = Sources/PushNotificationsContentExtension/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@executable_path/../../Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications.PushNotificationsContentExtension;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ D34FC9390D8C12046901C916 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_ENTITLEMENTS = Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements;
+ INFOPLIST_FILE = Sources/PushNotificationsContentExtension/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@executable_path/../../Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications.PushNotificationsContentExtension;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ D41CC2321BB3390AFD4C3C77 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_ENTITLEMENTS = Sources/PushNotifications/PushNotifications.entitlements;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/PushNotifications/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications;
+ PRODUCT_NAME = PushNotifications;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ D42220F54B188367F09D51F2 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/Analytics/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Analytics-iOS";
+ PRODUCT_NAME = Analytics;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ D73FE2FD92F59639E0E66547 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ INFOPLIST_FILE = Sources/Analytics/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Analytics-tvOS";
+ PRODUCT_NAME = Analytics;
+ SDKROOT = appletvos;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Debug;
+ };
+ E93F9B7A3E25FB962107ED6A /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ SWIFT_VERSION = 5.0;
+ TVOS_DEPLOYMENT_TARGET = 11.0;
+ };
+ name = Release;
+ };
+ F97E175B39C55208E8A73860 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = "Sources/ContentCards-Custom-UI/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.ContentCards-Custom-UI-iOS";
+ PRODUCT_NAME = "ContentCards-Custom-UI";
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ FB51E977835920E25D8EB81E /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_ENTITLEMENTS = Sources/PushNotifications/PushNotifications.entitlements;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/PushNotifications/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications;
+ PRODUCT_NAME = PushNotifications;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 03D1E503F9863A03CB17E53A /* Build configuration list for PBXNativeTarget "PushNotificationsContentExtension" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ CFC0E247B97C5CEDBAF0B857 /* Debug */,
+ D34FC9390D8C12046901C916 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ 1D61EB4EA4EACDE551DB7D19 /* Build configuration list for PBXProject "Examples-CocoaPods" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 947EC0697CF1F01DDC513FD6 /* Debug */,
+ E93F9B7A3E25FB962107ED6A /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ 33777E174E4CC017CCCB31A8 /* Build configuration list for PBXNativeTarget "ContentCards-Custom-UI-iOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 0B6E144276BF004EFE80A784 /* Debug */,
+ F97E175B39C55208E8A73860 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ 33A0A8897465C6BD7C17C2E6 /* Build configuration list for PBXNativeTarget "Analytics-tvOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ D73FE2FD92F59639E0E66547 /* Debug */,
+ A653F811811645548266EC3A /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ 38CA0A5742C4A4988D4584C2 /* Build configuration list for PBXNativeTarget "ContentCards-Custom-UI-tvOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ BA01071103F7280839CDFBF1 /* Debug */,
+ 67E21615E4F6D7BFAA160A31 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ 43414268546ED18E21E7E892 /* Build configuration list for PBXNativeTarget "Analytics-iOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4EBD32EE3B16C9EBF7493F73 /* Debug */,
+ D42220F54B188367F09D51F2 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ 4CBDCD32BF67ACE4E2977EFA /* Build configuration list for PBXNativeTarget "Location-iOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 74B3175DE3731381F52D100D /* Debug */,
+ AEB7354D56CC1297356D6010 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ 59402C8CB5DE66A776947595 /* Build configuration list for PBXNativeTarget "PushNotifications" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ FB51E977835920E25D8EB81E /* Debug */,
+ D41CC2321BB3390AFD4C3C77 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ 72920B71D538BFAF8A028D09 /* Build configuration list for PBXNativeTarget "InAppMessages-Custom-UI-iOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 77420AEFB5CE84A97B402C8C /* Debug */,
+ 0B782479BDDFAA91B90B6411 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ 9D35AC44AE90C1C27CBF8577 /* Build configuration list for PBXNativeTarget "ContentCards" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 0FF3E9103BDC67C9723BD0CD /* Debug */,
+ 508970482D723EDFFD096AB1 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ B76990766EAEC18717669D6F /* Build configuration list for PBXNativeTarget "Location-tvOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 277ABE8F9A11018387A77412 /* Debug */,
+ 61077A56E64ADBA96CA8CE0C /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ C8DA1DB107E7EE64BBBAEBE7 /* Build configuration list for PBXNativeTarget "InAppMessages" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4BCF9BD39CEB19E634B6FD81 /* Debug */,
+ 4FCE20B3E84CE39D624EFA02 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ D767F3158D7C98C16E53CE31 /* Build configuration list for PBXNativeTarget "PushNotificationsServiceExtension" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C53D3849AB3D8DAE264A3A51 /* Debug */,
+ 0DB286FC893227921592442C /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ E26727234EAA2C9FFB557AF2 /* Build configuration list for PBXNativeTarget "InAppMessages-Custom-UI-tvOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 2178EDBFBF71828E507601C1 /* Debug */,
+ 1CE2539A10E8624E8EDD3601 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = C9F9231105531CE428ADD921 /* Project object */;
+}
diff --git a/Examples/Examples-CocoaPods.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/ObjC/Examples-CocoaPods.xcodeproj/project.xcworkspace/contents.xcworkspacedata
similarity index 100%
rename from Examples/Examples-CocoaPods.xcodeproj/project.xcworkspace/contents.xcworkspacedata
rename to Examples/ObjC/Examples-CocoaPods.xcodeproj/project.xcworkspace/contents.xcworkspacedata
diff --git a/Examples/ObjC/Examples-SwiftPM.xcodeproj/project.pbxproj b/Examples/ObjC/Examples-SwiftPM.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..f0f2dc6790
--- /dev/null
+++ b/Examples/ObjC/Examples-SwiftPM.xcodeproj/project.pbxproj
@@ -0,0 +1,1928 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 51;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 01B00D06564F5BC3CC2CDD91 /* CardsInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5634FD53344A83FD267AB580 /* CardsInfoViewController.m */; };
+ 02C558571508A77542FBC26C /* SDWebImage in Frameworks */ = {isa = PBXBuildFile; productRef = 0D08CDAB0AE57DFC38F9B590 /* SDWebImage */; };
+ 06F87FDA5F0E0E87D405F0BB /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = BC5EE8BE3BAD32DB6D66AC70 /* AppDelegate.m */; };
+ 07DD9E6B75B3C3E0B7B93FF9 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; };
+ 0D0836D2DE975E4BF0F3D051 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 75CC1E79A9D6815B60835BA2 /* Readme.m */; };
+ 0E4B45AF1E749BA1333419FA /* AuthenticationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BF7AC51A554A71CFA452B84 /* AuthenticationManager.m */; };
+ 0EA9500525189479BEEA2579 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; };
+ 0F7C946151DE727574B396A6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; };
+ 140EBDD7D126C0DB7E24563C /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; };
+ 14174CD7F71ACF6F4F3E3808 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; };
+ 176536B39FED72ECC2028BFC /* SDWebImage in Frameworks */ = {isa = PBXBuildFile; productRef = 0BF370808D2F5C21870331A0 /* SDWebImage */; };
+ 17B09479DD77FD4EEFFF95E8 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; };
+ 18ED90A49FD6D7527CB90B7E /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; };
+ 1A810C7DA64E86D3A828A920 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 415A55D2760CB84A0CC3A13B /* LaunchScreen.storyboard */; };
+ 1A93472F1D5EF8BE86567BE6 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FFCA5A7A3B8EF9BFE4BF145 /* Readme.m */; };
+ 23FF6692F5A6D268DC355315 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5F65978FE19A988D7A5454A3 /* LaunchScreen.storyboard */; };
+ 241F4F1F41D820C55156841D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; };
+ 24400D6B97710B109BDD8A60 /* BrazePushStory in Frameworks */ = {isa = PBXBuildFile; productRef = 5133F5A2D91882A4AE649D4D /* BrazePushStory */; };
+ 28C5F7A47286B0D4233CFD93 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D56D9CC866EB37EFC5EFD4 /* Readme.m */; };
+ 2A160FCCE45E4690E694D46A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F7D912E013554F7C8A41F0ED /* AppDelegate.m */; };
+ 2C47D73C2D8F2F68DF83612B /* BrazeNotificationService in Frameworks */ = {isa = PBXBuildFile; productRef = 47F3E12B1114B00B4CB70C60 /* BrazeNotificationService */; };
+ 2D4560AC04CE0BEC2BB8749B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; };
+ 2E68CB6DC13AC6CB1441D20B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5F65978FE19A988D7A5454A3 /* LaunchScreen.storyboard */; };
+ 2EB145FE4832264DD7ACC3F3 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 971900217FE69BE4658FE8B2 /* AppDelegate.m */; };
+ 2F8F5E0C5161968068CC2A05 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; };
+ 312590E9832D85052B8D9759 /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = F4168F1485105BAAD54B813C /* BrazeKit */; };
+ 335CAD4EA24AFBE63B9199B9 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; };
+ 35D55D4145464F3D006D4019 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 40B1FA52497F602A50792867 /* Readme.m */; };
+ 365EF0CD30923A1254130722 /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = F68192C4A0D4928F78762878 /* BrazeKit */; };
+ 3B3CDE3FA9E39EE3140F5421 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; };
+ 3B90DD85782F3701AD557A6A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5F65978FE19A988D7A5454A3 /* LaunchScreen.storyboard */; };
+ 3CF570CEA985E07B3DBFBBBE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A5ECFB24E396F30D56AC2C5 /* AppDelegate.m */; };
+ 432AF81580216BC7FECF3E0A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; };
+ 437AA7B38193226049B72FBE /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 74D6487EFD8114F6B61637AB /* BrazeKit */; };
+ 4484E207BCFD002822F2BB7D /* NotificationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE00D10FF658213E5A00188D /* NotificationViewController.swift */; };
+ 4B2B9B16A40D85A3093F1C41 /* CustomInAppMessagePresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A8584CCE6D9BBC4C2F634BB /* CustomInAppMessagePresenter.m */; };
+ 4BC9D0026B4908271DF68F19 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; };
+ 4D223F6F99924DC08BF93EE6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; };
+ 4EFDEFD372D670CB56731D3E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; };
+ 4FCC18D09440113FCC444C49 /* PushNotificationsContentExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = A7B092ACAEC915379923328F /* PushNotificationsContentExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
+ 51E6A2F0C6E2C992A51F5F20 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; };
+ 55343C252FC045A6B70D521D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; };
+ 59DE5747C69E47CB456FDA44 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; };
+ 5C0D56998D46869E0617E5A4 /* BrazeUI in Frameworks */ = {isa = PBXBuildFile; productRef = 9AF0AF048F752A5C62317470 /* BrazeUI */; };
+ 5C506223F8E16936EFF1ECAA /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 75CC1E79A9D6815B60835BA2 /* Readme.m */; };
+ 60A6EE4C2AF712684F1045C5 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; };
+ 627920814F95860FB73D560F /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; };
+ 6859B8749DCA922A8E670008 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; };
+ 693EE86FDDA758DF36715F51 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 90388C63B5CA3065EB14C5E7 /* Readme.m */; };
+ 69765CD7313717A7FF7B4C30 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F7D912E013554F7C8A41F0ED /* AppDelegate.m */; };
+ 6CE3551AF54503A3FA2E7853 /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 046845029FE9235B46B84104 /* BrazeKit */; };
+ 6D91E6B536F0C7585E809607 /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 17D80570112755DC2EEEF450 /* BrazeKit */; };
+ 6DA15916A0F0F7ECF3968E42 /* PushNotificationsServiceExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = B5666DA142189EEEDFAFB41F /* PushNotificationsServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
+ 6E358B236135C54CF185EEDC /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; };
+ 6FAFF3BA371E41638E044127 /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 89598718421C181B57346379 /* BrazeKit */; };
+ 75D4A5808678A333BC37FD62 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; };
+ 78D5F4892287E2A080AFD065 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; };
+ 7CCE66927CDCF27343C8A19F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; };
+ 7F8916648BED7D17A1F5F6D4 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 40B1FA52497F602A50792867 /* Readme.m */; };
+ 80D345EAA814805B7B762A4E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 415A55D2760CB84A0CC3A13B /* LaunchScreen.storyboard */; };
+ 85EBAD10002EFE00116C0892 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; };
+ 87824C15AAA2003EC964C107 /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08CE7C19F258AF40B394B358 /* UserNotifications.framework */; };
+ 8992304A2D2955D1BA1A6F32 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; };
+ 89CC79B20BACB82640928264 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 415A55D2760CB84A0CC3A13B /* LaunchScreen.storyboard */; };
+ 8A8EC9A9DB4F12593F3BA68F /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FFCA5A7A3B8EF9BFE4BF145 /* Readme.m */; };
+ 8EC99177B84C2FD480B24D33 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; };
+ 99DA0F0635AE21C1096495B9 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8783B6A324D425D55615AFD9 /* AppDelegate.m */; };
+ 99EF7BD971D6D5849078F00F /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; };
+ 9CE6B2D9DC0F3B277094AEB9 /* BrazeUI in Frameworks */ = {isa = PBXBuildFile; productRef = 26C11D75220DCD8456AEAA39 /* BrazeUI */; };
+ 9D70D60D63C3590056AE7BE9 /* CustomInAppMessagePresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A8584CCE6D9BBC4C2F634BB /* CustomInAppMessagePresenter.m */; };
+ 9EC27A7D337A4DF0A2F94484 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; };
+ A47F4EBAA7A0D8D9694CDBED /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 9F5A50D1AF8D80AC6C465155 /* BrazeKit */; };
+ A4BD0CF594F83266F2C9DFB1 /* CardsInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5634FD53344A83FD267AB580 /* CardsInfoViewController.m */; };
+ A725268792A6C2039D9C402B /* CheckoutViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CFCDF89427142AC55571D3A4 /* CheckoutViewController.m */; };
+ AD0FB326BFA4C3E7A64469FA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 415A55D2760CB84A0CC3A13B /* LaunchScreen.storyboard */; };
+ ADBC780DCB0B446D08B01BD7 /* InAppMessageInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AF02C869BF9AFF144C7C90DF /* InAppMessageInfoViewController.m */; };
+ AE9B5583963142DD6C7E2B7F /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63F498CAD1B487B718A6064 /* NotificationService.swift */; };
+ AF2CC1B40270C6B61BCB36F3 /* UserNotificationsUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B0D325AE1E7E717D151B9B6B /* UserNotificationsUI.framework */; };
+ B17B4317A4822F6631A83E7B /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 7509FFDD2664F798C716F648 /* Readme.m */; };
+ B1EA445BF1E43473B3F7A9EF /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B01598D5924C3065B7D516B /* Readme.m */; };
+ B4AC1050912335DCAFDA50DC /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; };
+ B596113707879825CDA4F233 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 971900217FE69BE4658FE8B2 /* AppDelegate.m */; };
+ B8FC11110451BE51D3352A0D /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; };
+ BA93CBED2945FD7B06611823 /* InAppMessageInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AF02C869BF9AFF144C7C90DF /* InAppMessageInfoViewController.m */; };
+ BD418D0ABB09B10266CCEB9A /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 7793FD8C8DE601EC38DD8DD7 /* BrazeKit */; };
+ BD7243FA7D8B321F7E1B5BBF /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; };
+ C412D2A3E605123FE5CBFAB2 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 415A55D2760CB84A0CC3A13B /* LaunchScreen.storyboard */; };
+ C81EA3048E9D8CED3B3EDD97 /* BrazeLocation in Frameworks */ = {isa = PBXBuildFile; productRef = 2C4994F9E91F986F0629979F /* BrazeLocation */; };
+ C871120C2B04423F52FA3E92 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 415A55D2760CB84A0CC3A13B /* LaunchScreen.storyboard */; };
+ CBE072256EDCC746C7BC2D29 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 12036F06D0B199D8445FCB1B /* AppDelegate.m */; };
+ CD7221C36FFBC58EB536C550 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; };
+ CEC66A96DFFBEFAF75B10DD0 /* BrazeLocation in Frameworks */ = {isa = PBXBuildFile; productRef = A2D57BF9CEBB2DC10A5B3AE6 /* BrazeLocation */; };
+ D02EBC8DF2A796ED2C9CEFC0 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 7509FFDD2664F798C716F648 /* Readme.m */; };
+ D0680AB119405ED4AD4AB35A /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; };
+ D0FB8791620F800C7485E52B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5F65978FE19A988D7A5454A3 /* LaunchScreen.storyboard */; };
+ D24015C9E60BC0AB214C4F83 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = BC5EE8BE3BAD32DB6D66AC70 /* AppDelegate.m */; };
+ D2A2CF406EE7D523247B45DD /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; };
+ DB84622E0C40467BD20C3779 /* BRZGIFViewProvider+SDWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = FBA572CA696173DD712458AD /* BRZGIFViewProvider+SDWebImage.m */; };
+ DBC0B617306F2A138194200C /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 80661DB9711EFD43546E249C /* BrazeKit */; };
+ DD69D41758F99D463763675A /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; };
+ DE22594DD1123178B1CC7771 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; };
+ DF5F3076246E4D156FA5A3F8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; };
+ DFB6A101BCD151F5B9651D82 /* AuthenticationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BF7AC51A554A71CFA452B84 /* AuthenticationManager.m */; };
+ E743EAE4518F62189A4D3C8A /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = F173FCAB52D0340802119A34 /* BrazeKit */; };
+ E7996808D67A3A1A043A0731 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8783B6A324D425D55615AFD9 /* AppDelegate.m */; };
+ EA8ED23E897565712389CE3F /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EE7DAF62AE545D7087BB7032 /* AppDelegate.m */; };
+ EC57F25FE46BBD05EA33C939 /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08CE7C19F258AF40B394B358 /* UserNotifications.framework */; };
+ ED42AFACDCE40F3510BCCB65 /* BRZGIFViewProvider+SDWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = A372FC98EA508F503CE11C30 /* BRZGIFViewProvider+SDWebImage.m */; };
+ EEDF56D9E060B1301014A6B0 /* CheckoutViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CFCDF89427142AC55571D3A4 /* CheckoutViewController.m */; };
+ EF5ED1AD6790AA461DC0B2C6 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; };
+ EF5EF251D34064B14F500469 /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 09701E67CAE64FCE46458059 /* BrazeKit */; };
+ F658BE141364C2F62F7866D1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 415A55D2760CB84A0CC3A13B /* LaunchScreen.storyboard */; };
+ F85EF5BC8A69B68633529B36 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; };
+ F95AE350417AB5ED6CEDECCB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; };
+ FF9046579962F0EBB98DB78C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 401588D076F789179E1A0954 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = D0C505F98E2813EFE5D58816 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 842A3D91E0A246B872DA9846;
+ remoteInfo = PushNotificationsServiceExtension;
+ };
+ E63F56BE4C659BB9547002CB /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = D0C505F98E2813EFE5D58816 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E59DB4201FEAE1A212979375;
+ remoteInfo = PushNotificationsContentExtension;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 75C027D366D7264EE07F1AC3 /* Embed App Extensions */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 13;
+ files = (
+ 6DA15916A0F0F7ECF3968E42 /* PushNotificationsServiceExtension.appex in Embed App Extensions */,
+ 4FCC18D09440113FCC444C49 /* PushNotificationsContentExtension.appex in Embed App Extensions */,
+ );
+ name = "Embed App Extensions";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 01BB19FD80E90EE93B172CF8 /* InAppMessageInfoViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InAppMessageInfoViewController.h; sourceTree = ""; };
+ 08CE7C19F258AF40B394B358 /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; };
+ 0B3605C45690205D4A58D1C3 /* Analytics.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Analytics.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ 12036F06D0B199D8445FCB1B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ 142C43EBD6AA34841D26163C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ 16F703E30F0CDB139F4DBC8E /* ContentCards-Custom-UI.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "ContentCards-Custom-UI.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReadmeViewController.m; sourceTree = ""; };
+ 220432BEC0EA7628608EA5BA /* braze-swift-sdk */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "braze-swift-sdk"; path = ../..; sourceTree = SOURCE_ROOT; };
+ 31F63E82703CC19F27872526 /* BRZGIFViewProvider+SDWebImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BRZGIFViewProvider+SDWebImage.h"; sourceTree = ""; };
+ 324D8E917E21EC25C2E0EC7C /* AuthenticationManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AuthenticationManager.h; sourceTree = ""; };
+ 34BD000896FB64DC78BBF177 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ 35A0BE5C8816D747CCA37863 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ 3A8584CCE6D9BBC4C2F634BB /* CustomInAppMessagePresenter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CustomInAppMessagePresenter.m; sourceTree = ""; };
+ 3BF7AC51A554A71CFA452B84 /* AuthenticationManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AuthenticationManager.m; sourceTree = ""; };
+ 40B1FA52497F602A50792867 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; };
+ 54B2132B425902ECA87672DE /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ 5634FD53344A83FD267AB580 /* CardsInfoViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CardsInfoViewController.m; sourceTree = ""; };
+ 5B01598D5924C3065B7D516B /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; };
+ 5DFFFE740A88297EE59DB98F /* Location.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Location.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 5FFCA5A7A3B8EF9BFE4BF145 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; };
+ 631AC4EE3B6D81ACA0DBEFBE /* CardsInfoViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CardsInfoViewController.h; sourceTree = ""; };
+ 6459ADE015D6A93F4DDEF4D8 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
+ 64B22ACFDEB977C9F3B3B67E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ 65785E585247CC7A8661ED6B /* InAppMessages.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = InAppMessages.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 7509FFDD2664F798C716F648 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; };
+ 75CC1E79A9D6815B60835BA2 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; };
+ 7D76AFE44929AD2F889183E3 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ 84D56D9CC866EB37EFC5EFD4 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; };
+ 85EB91B2555C84CBD26F79F6 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ 870B27433E30991ABA197CD2 /* ContentCards-Custom-UI.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "ContentCards-Custom-UI.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 8783B6A324D425D55615AFD9 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ 8D441B5B5424C3E129B2DA54 /* PushNotifications.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = PushNotifications.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 90388C63B5CA3065EB14C5E7 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; };
+ 971900217FE69BE4658FE8B2 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ 9A5ECFB24E396F30D56AC2C5 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ 9EDFB6B6D9E65C9BFD47EA17 /* Analytics.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Analytics.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ A372FC98EA508F503CE11C30 /* BRZGIFViewProvider+SDWebImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "BRZGIFViewProvider+SDWebImage.m"; sourceTree = ""; };
+ A7B092ACAEC915379923328F /* PushNotificationsContentExtension.appex */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.app-extension"; path = PushNotificationsContentExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
+ A900B781B2DFE220B129E338 /* Credentials.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Credentials.m; sourceTree = ""; };
+ AF02C869BF9AFF144C7C90DF /* InAppMessageInfoViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InAppMessageInfoViewController.m; sourceTree = ""; };
+ B0D325AE1E7E717D151B9B6B /* UserNotificationsUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotificationsUI.framework; path = System/Library/Frameworks/UserNotificationsUI.framework; sourceTree = SDKROOT; };
+ B558422CCA055B4615F43572 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ B5666DA142189EEEDFAFB41F /* PushNotificationsServiceExtension.appex */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.app-extension"; path = PushNotificationsServiceExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
+ B7F06535E19BAEA9F5B73F86 /* ContentCards.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = ContentCards.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ BC5EE8BE3BAD32DB6D66AC70 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ C1B822E14D6196E0BDCC531E /* ReadmeAction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReadmeAction.h; sourceTree = ""; };
+ C79CCF16B994DB3DCD63BE74 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ CE00D10FF658213E5A00188D /* NotificationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationViewController.swift; sourceTree = ""; };
+ CF2BBB04F875FF5FA863FC82 /* CustomInAppMessagePresenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CustomInAppMessagePresenter.h; sourceTree = ""; };
+ CFCDF89427142AC55571D3A4 /* CheckoutViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CheckoutViewController.m; sourceTree = ""; };
+ D63F498CAD1B487B718A6064 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; };
+ E5F704300A66AB9522AA5F94 /* CheckoutViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CheckoutViewController.h; sourceTree = ""; };
+ E86CD93FBF04F90F0ADCF89D /* BRZGIFViewProvider+SDWebImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BRZGIFViewProvider+SDWebImage.h"; sourceTree = ""; };
+ ECA5D86743A8F050AB493312 /* InAppMessages-Custom-UI.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "InAppMessages-Custom-UI.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ EE631F5EEEEB707468BF265A /* Location.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Location.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ EE718585DF8925CE6290EB8E /* ReadmeViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReadmeViewController.h; sourceTree = ""; };
+ EE7DAF62AE545D7087BB7032 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ F7D912E013554F7C8A41F0ED /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ FBA572CA696173DD712458AD /* BRZGIFViewProvider+SDWebImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "BRZGIFViewProvider+SDWebImage.m"; sourceTree = ""; };
+ FF31C634A18224DB9ED02834 /* InAppMessages-Custom-UI.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "InAppMessages-Custom-UI.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 034FEEA975C05994B9129B8E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 437AA7B38193226049B72FBE /* BrazeKit in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 183E99B0677A3CBB42A80754 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EC57F25FE46BBD05EA33C939 /* UserNotifications.framework in Frameworks */,
+ 2C47D73C2D8F2F68DF83612B /* BrazeNotificationService in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 324CB6E38E7D86E327812A17 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ DBC0B617306F2A138194200C /* BrazeKit in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 3FE4CCA5EE34D160D3BA7E65 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EF5EF251D34064B14F500469 /* BrazeKit in Frameworks */,
+ 5C0D56998D46869E0617E5A4 /* BrazeUI in Frameworks */,
+ 176536B39FED72ECC2028BFC /* SDWebImage in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4049520CA36B4E21D2DCFCC1 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 312590E9832D85052B8D9759 /* BrazeKit in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4E1BD2E76D5B08698C2D0853 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 87824C15AAA2003EC964C107 /* UserNotifications.framework in Frameworks */,
+ AF2CC1B40270C6B61BCB36F3 /* UserNotificationsUI.framework in Frameworks */,
+ 24400D6B97710B109BDD8A60 /* BrazePushStory in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4F5A962E7AA8DBEA0DB50C60 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ A47F4EBAA7A0D8D9694CDBED /* BrazeKit in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 6E70CCCD8CEE5D68B1E92800 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 6FAFF3BA371E41638E044127 /* BrazeKit in Frameworks */,
+ 9CE6B2D9DC0F3B277094AEB9 /* BrazeUI in Frameworks */,
+ 02C558571508A77542FBC26C /* SDWebImage in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 76AEEA4F011020D515A98A7F /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ BD418D0ABB09B10266CCEB9A /* BrazeKit in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8263C301708EEA6D3CF6B118 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 6D91E6B536F0C7585E809607 /* BrazeKit in Frameworks */,
+ CEC66A96DFFBEFAF75B10DD0 /* BrazeLocation in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 9D55980B7C6BF6E4EEC94491 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 365EF0CD30923A1254130722 /* BrazeKit in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ BC9BA8958DF88D295215D932 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 6CE3551AF54503A3FA2E7853 /* BrazeKit in Frameworks */,
+ C81EA3048E9D8CED3B3EDD97 /* BrazeLocation in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EFAF41E4C424F1D471C539B5 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E743EAE4518F62189A4D3C8A /* BrazeKit in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 051DD5EB27092FF8E610A438 /* tvOS */ = {
+ isa = PBXGroup;
+ children = (
+ 5F65978FE19A988D7A5454A3 /* LaunchScreen.storyboard */,
+ );
+ path = tvOS;
+ sourceTree = "";
+ };
+ 119FF3F930BD1BF66DEB0B47 /* ContentCards-Custom-UI */ = {
+ isa = PBXGroup;
+ children = (
+ 54B2132B425902ECA87672DE /* AppDelegate.h */,
+ 8783B6A324D425D55615AFD9 /* AppDelegate.m */,
+ 631AC4EE3B6D81ACA0DBEFBE /* CardsInfoViewController.h */,
+ 5634FD53344A83FD267AB580 /* CardsInfoViewController.m */,
+ 7509FFDD2664F798C716F648 /* Readme.m */,
+ );
+ name = "ContentCards-Custom-UI";
+ path = "Sources/ContentCards-Custom-UI";
+ sourceTree = "";
+ };
+ 234FC0FDE1EB1D2B1EE92CDA /* ContentCards */ = {
+ isa = PBXGroup;
+ children = (
+ C79CCF16B994DB3DCD63BE74 /* AppDelegate.h */,
+ EE7DAF62AE545D7087BB7032 /* AppDelegate.m */,
+ E86CD93FBF04F90F0ADCF89D /* BRZGIFViewProvider+SDWebImage.h */,
+ A372FC98EA508F503CE11C30 /* BRZGIFViewProvider+SDWebImage.m */,
+ 90388C63B5CA3065EB14C5E7 /* Readme.m */,
+ );
+ name = ContentCards;
+ path = Sources/ContentCards;
+ sourceTree = "";
+ };
+ 256C64FD5A9C547C95ED205A /* Location */ = {
+ isa = PBXGroup;
+ children = (
+ B558422CCA055B4615F43572 /* AppDelegate.h */,
+ BC5EE8BE3BAD32DB6D66AC70 /* AppDelegate.m */,
+ 40B1FA52497F602A50792867 /* Readme.m */,
+ );
+ name = Location;
+ path = Sources/Location;
+ sourceTree = "";
+ };
+ 258F28BC46EE3F2D3E079C37 /* Analytics */ = {
+ isa = PBXGroup;
+ children = (
+ 64B22ACFDEB977C9F3B3B67E /* AppDelegate.h */,
+ 971900217FE69BE4658FE8B2 /* AppDelegate.m */,
+ 324D8E917E21EC25C2E0EC7C /* AuthenticationManager.h */,
+ 3BF7AC51A554A71CFA452B84 /* AuthenticationManager.m */,
+ E5F704300A66AB9522AA5F94 /* CheckoutViewController.h */,
+ CFCDF89427142AC55571D3A4 /* CheckoutViewController.m */,
+ 75CC1E79A9D6815B60835BA2 /* Readme.m */,
+ );
+ name = Analytics;
+ path = Sources/Analytics;
+ sourceTree = "";
+ };
+ 602D317DF9E1FCBC46B4F176 /* PushNotificationsContentExtension */ = {
+ isa = PBXGroup;
+ children = (
+ CE00D10FF658213E5A00188D /* NotificationViewController.swift */,
+ );
+ name = PushNotificationsContentExtension;
+ path = Sources/PushNotificationsContentExtension;
+ sourceTree = "";
+ };
+ 63C766BFE288147BB97F9A4E /* iOS */ = {
+ isa = PBXGroup;
+ children = (
+ 415A55D2760CB84A0CC3A13B /* LaunchScreen.storyboard */,
+ );
+ path = iOS;
+ sourceTree = "";
+ };
+ 67175574AAFF46A4632B42DA /* PushNotifications */ = {
+ isa = PBXGroup;
+ children = (
+ 35A0BE5C8816D747CCA37863 /* AppDelegate.h */,
+ 12036F06D0B199D8445FCB1B /* AppDelegate.m */,
+ 84D56D9CC866EB37EFC5EFD4 /* Readme.m */,
+ );
+ name = PushNotifications;
+ path = Sources/PushNotifications;
+ sourceTree = "";
+ };
+ 6E715B0CD6028EAEB53373C9 /* InAppMessages-Custom-UI */ = {
+ isa = PBXGroup;
+ children = (
+ 85EB91B2555C84CBD26F79F6 /* AppDelegate.h */,
+ F7D912E013554F7C8A41F0ED /* AppDelegate.m */,
+ CF2BBB04F875FF5FA863FC82 /* CustomInAppMessagePresenter.h */,
+ 3A8584CCE6D9BBC4C2F634BB /* CustomInAppMessagePresenter.m */,
+ 01BB19FD80E90EE93B172CF8 /* InAppMessageInfoViewController.h */,
+ AF02C869BF9AFF144C7C90DF /* InAppMessageInfoViewController.m */,
+ 5FFCA5A7A3B8EF9BFE4BF145 /* Readme.m */,
+ );
+ name = "InAppMessages-Custom-UI";
+ path = "Sources/InAppMessages-Custom-UI";
+ sourceTree = "";
+ };
+ A3A2735A5DC208B24378D437 /* InAppMessages */ = {
+ isa = PBXGroup;
+ children = (
+ 7D76AFE44929AD2F889183E3 /* AppDelegate.h */,
+ 9A5ECFB24E396F30D56AC2C5 /* AppDelegate.m */,
+ 31F63E82703CC19F27872526 /* BRZGIFViewProvider+SDWebImage.h */,
+ FBA572CA696173DD712458AD /* BRZGIFViewProvider+SDWebImage.m */,
+ 5B01598D5924C3065B7D516B /* Readme.m */,
+ );
+ name = InAppMessages;
+ path = Sources/InAppMessages;
+ sourceTree = "";
+ };
+ AD1929AE02C13E7023AE1CA4 /* PushNotificationsServiceExtension */ = {
+ isa = PBXGroup;
+ children = (
+ D63F498CAD1B487B718A6064 /* NotificationService.swift */,
+ );
+ name = PushNotificationsServiceExtension;
+ path = Sources/PushNotificationsServiceExtension;
+ sourceTree = "";
+ };
+ B4F25C051708E808116165D4 /* Common */ = {
+ isa = PBXGroup;
+ children = (
+ 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */,
+ A900B781B2DFE220B129E338 /* Credentials.m */,
+ 6459ADE015D6A93F4DDEF4D8 /* main.m */,
+ C1B822E14D6196E0BDCC531E /* ReadmeAction.h */,
+ EE718585DF8925CE6290EB8E /* ReadmeViewController.h */,
+ 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */,
+ 63C766BFE288147BB97F9A4E /* iOS */,
+ 051DD5EB27092FF8E610A438 /* tvOS */,
+ );
+ name = Common;
+ path = Sources/Common;
+ sourceTree = "";
+ };
+ CD535985A50FFC8EDE928813 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 9EDFB6B6D9E65C9BFD47EA17 /* Analytics.app */,
+ 0B3605C45690205D4A58D1C3 /* Analytics.app */,
+ 870B27433E30991ABA197CD2 /* ContentCards-Custom-UI.app */,
+ 16F703E30F0CDB139F4DBC8E /* ContentCards-Custom-UI.app */,
+ B7F06535E19BAEA9F5B73F86 /* ContentCards.app */,
+ FF31C634A18224DB9ED02834 /* InAppMessages-Custom-UI.app */,
+ ECA5D86743A8F050AB493312 /* InAppMessages-Custom-UI.app */,
+ 65785E585247CC7A8661ED6B /* InAppMessages.app */,
+ EE631F5EEEEB707468BF265A /* Location.app */,
+ 5DFFFE740A88297EE59DB98F /* Location.app */,
+ 8D441B5B5424C3E129B2DA54 /* PushNotifications.app */,
+ A7B092ACAEC915379923328F /* PushNotificationsContentExtension.appex */,
+ B5666DA142189EEEDFAFB41F /* PushNotificationsServiceExtension.appex */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ D8CC2266D736859D7DD9A8FF = {
+ isa = PBXGroup;
+ children = (
+ E3AF9F206199B993ACB3E63D /* Packages */,
+ B4F25C051708E808116165D4 /* Common */,
+ 258F28BC46EE3F2D3E079C37 /* Analytics */,
+ 234FC0FDE1EB1D2B1EE92CDA /* ContentCards */,
+ 119FF3F930BD1BF66DEB0B47 /* ContentCards-Custom-UI */,
+ A3A2735A5DC208B24378D437 /* InAppMessages */,
+ 6E715B0CD6028EAEB53373C9 /* InAppMessages-Custom-UI */,
+ 256C64FD5A9C547C95ED205A /* Location */,
+ 67175574AAFF46A4632B42DA /* PushNotifications */,
+ 602D317DF9E1FCBC46B4F176 /* PushNotificationsContentExtension */,
+ AD1929AE02C13E7023AE1CA4 /* PushNotificationsServiceExtension */,
+ DF23D21F2F74022094519AC3 /* Frameworks */,
+ CD535985A50FFC8EDE928813 /* Products */,
+ );
+ sourceTree = "";
+ };
+ DF23D21F2F74022094519AC3 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 08CE7C19F258AF40B394B358 /* UserNotifications.framework */,
+ B0D325AE1E7E717D151B9B6B /* UserNotificationsUI.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ E3AF9F206199B993ACB3E63D /* Packages */ = {
+ isa = PBXGroup;
+ children = (
+ 220432BEC0EA7628608EA5BA /* braze-swift-sdk */,
+ );
+ name = Packages;
+ sourceTree = SOURCE_ROOT;
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 3AA5E6D1B97103DC27376A6D /* Analytics-tvOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E00B5C25BE5714D67E69A3EF /* Build configuration list for PBXNativeTarget "Analytics-tvOS" */;
+ buildPhases = (
+ B0576C5CB7B8374AB804BA17 /* Sources */,
+ 664A25CB9C7D704EEBC5573D /* Resources */,
+ 324CB6E38E7D86E327812A17 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "Analytics-tvOS";
+ packageProductDependencies = (
+ 80661DB9711EFD43546E249C /* BrazeKit */,
+ );
+ productName = "Analytics-tvOS";
+ productReference = 0B3605C45690205D4A58D1C3 /* Analytics.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 4B98C28FD93E5AD15DE94535 /* Analytics-iOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 264E98511670D6BD7B0E64D2 /* Build configuration list for PBXNativeTarget "Analytics-iOS" */;
+ buildPhases = (
+ BDD30223625DA51AFB115FE3 /* Sources */,
+ 1B55699C3892866CC2E3380D /* Resources */,
+ 034FEEA975C05994B9129B8E /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "Analytics-iOS";
+ packageProductDependencies = (
+ 74D6487EFD8114F6B61637AB /* BrazeKit */,
+ );
+ productName = "Analytics-iOS";
+ productReference = 9EDFB6B6D9E65C9BFD47EA17 /* Analytics.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 5BE2DFC918DF0CC5E69FE387 /* InAppMessages */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F76B079D8771880EE7A2C01D /* Build configuration list for PBXNativeTarget "InAppMessages" */;
+ buildPhases = (
+ 629101DE070207860B0FF0B5 /* Sources */,
+ 3D8D07DBB7AF1C865DA26D8E /* Resources */,
+ 3FE4CCA5EE34D160D3BA7E65 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = InAppMessages;
+ packageProductDependencies = (
+ 09701E67CAE64FCE46458059 /* BrazeKit */,
+ 9AF0AF048F752A5C62317470 /* BrazeUI */,
+ 0BF370808D2F5C21870331A0 /* SDWebImage */,
+ );
+ productName = InAppMessages;
+ productReference = 65785E585247CC7A8661ED6B /* InAppMessages.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 6EC91F0D0FFF467CD90FB0D3 /* InAppMessages-Custom-UI-tvOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 5FD7F38C2E047474FF2AE862 /* Build configuration list for PBXNativeTarget "InAppMessages-Custom-UI-tvOS" */;
+ buildPhases = (
+ ED315B5B4830F964E3577CD9 /* Sources */,
+ 1555F7408F765567E3544A08 /* Resources */,
+ 76AEEA4F011020D515A98A7F /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "InAppMessages-Custom-UI-tvOS";
+ packageProductDependencies = (
+ 7793FD8C8DE601EC38DD8DD7 /* BrazeKit */,
+ );
+ productName = "InAppMessages-Custom-UI-tvOS";
+ productReference = ECA5D86743A8F050AB493312 /* InAppMessages-Custom-UI.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 842A3D91E0A246B872DA9846 /* PushNotificationsServiceExtension */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = FB6122990820F57E6DB4A7D6 /* Build configuration list for PBXNativeTarget "PushNotificationsServiceExtension" */;
+ buildPhases = (
+ 0F4E3ECA66B0F7D180D317DF /* Sources */,
+ 183E99B0677A3CBB42A80754 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = PushNotificationsServiceExtension;
+ packageProductDependencies = (
+ 47F3E12B1114B00B4CB70C60 /* BrazeNotificationService */,
+ );
+ productName = PushNotificationsServiceExtension;
+ productReference = B5666DA142189EEEDFAFB41F /* PushNotificationsServiceExtension.appex */;
+ productType = "com.apple.product-type.app-extension";
+ };
+ 9292D3D6E47059505F536422 /* Location-tvOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 340804EFAD862F854E93596B /* Build configuration list for PBXNativeTarget "Location-tvOS" */;
+ buildPhases = (
+ 2A4DDD3E0061EBB62528F184 /* Sources */,
+ 01F1E28DC32E6EFA39BE54C8 /* Resources */,
+ 8263C301708EEA6D3CF6B118 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "Location-tvOS";
+ packageProductDependencies = (
+ 17D80570112755DC2EEEF450 /* BrazeKit */,
+ A2D57BF9CEBB2DC10A5B3AE6 /* BrazeLocation */,
+ );
+ productName = "Location-tvOS";
+ productReference = 5DFFFE740A88297EE59DB98F /* Location.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 960C133F6A6AD264A11DD8D9 /* ContentCards-Custom-UI-iOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 52115E4788F114BD9F51C612 /* Build configuration list for PBXNativeTarget "ContentCards-Custom-UI-iOS" */;
+ buildPhases = (
+ E2EFE22428A2F3EEA61751F5 /* Sources */,
+ FDCF284FAF6DD56D949E0F0F /* Resources */,
+ 4F5A962E7AA8DBEA0DB50C60 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "ContentCards-Custom-UI-iOS";
+ packageProductDependencies = (
+ 9F5A50D1AF8D80AC6C465155 /* BrazeKit */,
+ );
+ productName = "ContentCards-Custom-UI-iOS";
+ productReference = 870B27433E30991ABA197CD2 /* ContentCards-Custom-UI.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 9B3876462D904A1496AF569D /* Location-iOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 9D5AEEE5B58C1044A4BA612B /* Build configuration list for PBXNativeTarget "Location-iOS" */;
+ buildPhases = (
+ DADCD7F86B712F9D6A7C1EB7 /* Sources */,
+ 69FB3C575524EEDC0F2FC486 /* Resources */,
+ BC9BA8958DF88D295215D932 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "Location-iOS";
+ packageProductDependencies = (
+ 046845029FE9235B46B84104 /* BrazeKit */,
+ 2C4994F9E91F986F0629979F /* BrazeLocation */,
+ );
+ productName = "Location-iOS";
+ productReference = EE631F5EEEEB707468BF265A /* Location.app */;
+ productType = "com.apple.product-type.application";
+ };
+ B64E1C1C2CDBA52874450596 /* PushNotifications */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 35795D9DBF2411B548D5563D /* Build configuration list for PBXNativeTarget "PushNotifications" */;
+ buildPhases = (
+ 4D9E50A78216959662CAD320 /* Sources */,
+ 0AB603E26C615FD7EAD6D550 /* Resources */,
+ 4049520CA36B4E21D2DCFCC1 /* Frameworks */,
+ 75C027D366D7264EE07F1AC3 /* Embed App Extensions */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 66C7DD376098B1684E2BD062 /* PBXTargetDependency */,
+ 385684E74F484291678D97E2 /* PBXTargetDependency */,
+ );
+ name = PushNotifications;
+ packageProductDependencies = (
+ F4168F1485105BAAD54B813C /* BrazeKit */,
+ );
+ productName = PushNotifications;
+ productReference = 8D441B5B5424C3E129B2DA54 /* PushNotifications.app */;
+ productType = "com.apple.product-type.application";
+ };
+ BE02E0C55FAEA6294D129A38 /* ContentCards-Custom-UI-tvOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 675C55871E9EBBD8A4279B5C /* Build configuration list for PBXNativeTarget "ContentCards-Custom-UI-tvOS" */;
+ buildPhases = (
+ 172685DE8A39EF99A470A7BD /* Sources */,
+ 2E3C6DE1806B99A424DECB0F /* Resources */,
+ EFAF41E4C424F1D471C539B5 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "ContentCards-Custom-UI-tvOS";
+ packageProductDependencies = (
+ F173FCAB52D0340802119A34 /* BrazeKit */,
+ );
+ productName = "ContentCards-Custom-UI-tvOS";
+ productReference = 16F703E30F0CDB139F4DBC8E /* ContentCards-Custom-UI.app */;
+ productType = "com.apple.product-type.application";
+ };
+ DEE99E05C6F822DC78AEE272 /* ContentCards */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = DAC0A7E698E628D993F35934 /* Build configuration list for PBXNativeTarget "ContentCards" */;
+ buildPhases = (
+ 6089EE24E3EFFEC175CB9A6A /* Sources */,
+ 1F3BD016FE47788CA94B7A4A /* Resources */,
+ 6E70CCCD8CEE5D68B1E92800 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = ContentCards;
+ packageProductDependencies = (
+ 89598718421C181B57346379 /* BrazeKit */,
+ 26C11D75220DCD8456AEAA39 /* BrazeUI */,
+ 0D08CDAB0AE57DFC38F9B590 /* SDWebImage */,
+ );
+ productName = ContentCards;
+ productReference = B7F06535E19BAEA9F5B73F86 /* ContentCards.app */;
+ productType = "com.apple.product-type.application";
+ };
+ E59DB4201FEAE1A212979375 /* PushNotificationsContentExtension */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 538A7D3F62B432A07C91FD40 /* Build configuration list for PBXNativeTarget "PushNotificationsContentExtension" */;
+ buildPhases = (
+ ACB52B0CE581070F5BA1A8E7 /* Sources */,
+ 4E1BD2E76D5B08698C2D0853 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = PushNotificationsContentExtension;
+ packageProductDependencies = (
+ 5133F5A2D91882A4AE649D4D /* BrazePushStory */,
+ );
+ productName = PushNotificationsContentExtension;
+ productReference = A7B092ACAEC915379923328F /* PushNotificationsContentExtension.appex */;
+ productType = "com.apple.product-type.app-extension";
+ };
+ FD2447C0C6527F1CB2BEC9A6 /* InAppMessages-Custom-UI-iOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = EBB530AA4E1F5AF1FD5D5B58 /* Build configuration list for PBXNativeTarget "InAppMessages-Custom-UI-iOS" */;
+ buildPhases = (
+ 1A26619C466A145AC378E755 /* Sources */,
+ 2524C2C4AECF5FA40FF674F8 /* Resources */,
+ 9D55980B7C6BF6E4EEC94491 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "InAppMessages-Custom-UI-iOS";
+ packageProductDependencies = (
+ F68192C4A0D4928F78762878 /* BrazeKit */,
+ );
+ productName = "InAppMessages-Custom-UI-iOS";
+ productReference = FF31C634A18224DB9ED02834 /* InAppMessages-Custom-UI.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ D0C505F98E2813EFE5D58816 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 1200;
+ TargetAttributes = {
+ };
+ };
+ buildConfigurationList = 121E4DAF0EB7FA3A0B03C3C0 /* Build configuration list for PBXProject "Examples-SwiftPM" */;
+ compatibilityVersion = "Xcode 11.0";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ Base,
+ en,
+ );
+ mainGroup = D8CC2266D736859D7DD9A8FF;
+ packageReferences = (
+ 9928D5150C45879A982BA1C6 /* XCRemoteSwiftPackageReference "SDWebImage" */,
+ );
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 4B98C28FD93E5AD15DE94535 /* Analytics-iOS */,
+ 3AA5E6D1B97103DC27376A6D /* Analytics-tvOS */,
+ DEE99E05C6F822DC78AEE272 /* ContentCards */,
+ 960C133F6A6AD264A11DD8D9 /* ContentCards-Custom-UI-iOS */,
+ BE02E0C55FAEA6294D129A38 /* ContentCards-Custom-UI-tvOS */,
+ 5BE2DFC918DF0CC5E69FE387 /* InAppMessages */,
+ FD2447C0C6527F1CB2BEC9A6 /* InAppMessages-Custom-UI-iOS */,
+ 6EC91F0D0FFF467CD90FB0D3 /* InAppMessages-Custom-UI-tvOS */,
+ 9B3876462D904A1496AF569D /* Location-iOS */,
+ 9292D3D6E47059505F536422 /* Location-tvOS */,
+ B64E1C1C2CDBA52874450596 /* PushNotifications */,
+ E59DB4201FEAE1A212979375 /* PushNotificationsContentExtension */,
+ 842A3D91E0A246B872DA9846 /* PushNotificationsServiceExtension */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 01F1E28DC32E6EFA39BE54C8 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 51E6A2F0C6E2C992A51F5F20 /* Assets.xcassets in Resources */,
+ D0FB8791620F800C7485E52B /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 0AB603E26C615FD7EAD6D550 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CD7221C36FFBC58EB536C550 /* Assets.xcassets in Resources */,
+ C871120C2B04423F52FA3E92 /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 1555F7408F765567E3544A08 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2D4560AC04CE0BEC2BB8749B /* Assets.xcassets in Resources */,
+ 23FF6692F5A6D268DC355315 /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 1B55699C3892866CC2E3380D /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4BC9D0026B4908271DF68F19 /* Assets.xcassets in Resources */,
+ C412D2A3E605123FE5CBFAB2 /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 1F3BD016FE47788CA94B7A4A /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 241F4F1F41D820C55156841D /* Assets.xcassets in Resources */,
+ AD0FB326BFA4C3E7A64469FA /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 2524C2C4AECF5FA40FF674F8 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 9EC27A7D337A4DF0A2F94484 /* Assets.xcassets in Resources */,
+ F658BE141364C2F62F7866D1 /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 2E3C6DE1806B99A424DECB0F /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 14174CD7F71ACF6F4F3E3808 /* Assets.xcassets in Resources */,
+ 3B90DD85782F3701AD557A6A /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 3D8D07DBB7AF1C865DA26D8E /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8EC99177B84C2FD480B24D33 /* Assets.xcassets in Resources */,
+ 80D345EAA814805B7B762A4E /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 664A25CB9C7D704EEBC5573D /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 59DE5747C69E47CB456FDA44 /* Assets.xcassets in Resources */,
+ 2E68CB6DC13AC6CB1441D20B /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 69FB3C575524EEDC0F2FC486 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 3B3CDE3FA9E39EE3140F5421 /* Assets.xcassets in Resources */,
+ 1A810C7DA64E86D3A828A920 /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ FDCF284FAF6DD56D949E0F0F /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F95AE350417AB5ED6CEDECCB /* Assets.xcassets in Resources */,
+ 89CC79B20BACB82640928264 /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 0F4E3ECA66B0F7D180D317DF /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ AE9B5583963142DD6C7E2B7F /* NotificationService.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 172685DE8A39EF99A470A7BD /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 99DA0F0635AE21C1096495B9 /* AppDelegate.m in Sources */,
+ 01B00D06564F5BC3CC2CDD91 /* CardsInfoViewController.m in Sources */,
+ DD69D41758F99D463763675A /* Credentials.m in Sources */,
+ B17B4317A4822F6631A83E7B /* Readme.m in Sources */,
+ 17B09479DD77FD4EEFFF95E8 /* ReadmeViewController.m in Sources */,
+ 60A6EE4C2AF712684F1045C5 /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 1A26619C466A145AC378E755 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 69765CD7313717A7FF7B4C30 /* AppDelegate.m in Sources */,
+ F85EF5BC8A69B68633529B36 /* Credentials.m in Sources */,
+ 9D70D60D63C3590056AE7BE9 /* CustomInAppMessagePresenter.m in Sources */,
+ BA93CBED2945FD7B06611823 /* InAppMessageInfoViewController.m in Sources */,
+ 8A8EC9A9DB4F12593F3BA68F /* Readme.m in Sources */,
+ 6E358B236135C54CF185EEDC /* ReadmeViewController.m in Sources */,
+ 2F8F5E0C5161968068CC2A05 /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 2A4DDD3E0061EBB62528F184 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 06F87FDA5F0E0E87D405F0BB /* AppDelegate.m in Sources */,
+ 18ED90A49FD6D7527CB90B7E /* Credentials.m in Sources */,
+ 7F8916648BED7D17A1F5F6D4 /* Readme.m in Sources */,
+ 8992304A2D2955D1BA1A6F32 /* ReadmeViewController.m in Sources */,
+ 7CCE66927CDCF27343C8A19F /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 4D9E50A78216959662CAD320 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CBE072256EDCC746C7BC2D29 /* AppDelegate.m in Sources */,
+ EF5ED1AD6790AA461DC0B2C6 /* Credentials.m in Sources */,
+ 28C5F7A47286B0D4233CFD93 /* Readme.m in Sources */,
+ D0680AB119405ED4AD4AB35A /* ReadmeViewController.m in Sources */,
+ DF5F3076246E4D156FA5A3F8 /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 6089EE24E3EFFEC175CB9A6A /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EA8ED23E897565712389CE3F /* AppDelegate.m in Sources */,
+ ED42AFACDCE40F3510BCCB65 /* BRZGIFViewProvider+SDWebImage.m in Sources */,
+ 75D4A5808678A333BC37FD62 /* Credentials.m in Sources */,
+ 693EE86FDDA758DF36715F51 /* Readme.m in Sources */,
+ 0EA9500525189479BEEA2579 /* ReadmeViewController.m in Sources */,
+ FF9046579962F0EBB98DB78C /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 629101DE070207860B0FF0B5 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 3CF570CEA985E07B3DBFBBBE /* AppDelegate.m in Sources */,
+ DB84622E0C40467BD20C3779 /* BRZGIFViewProvider+SDWebImage.m in Sources */,
+ 78D5F4892287E2A080AFD065 /* Credentials.m in Sources */,
+ B1EA445BF1E43473B3F7A9EF /* Readme.m in Sources */,
+ DE22594DD1123178B1CC7771 /* ReadmeViewController.m in Sources */,
+ 0F7C946151DE727574B396A6 /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ ACB52B0CE581070F5BA1A8E7 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4484E207BCFD002822F2BB7D /* NotificationViewController.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B0576C5CB7B8374AB804BA17 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2EB145FE4832264DD7ACC3F3 /* AppDelegate.m in Sources */,
+ 0E4B45AF1E749BA1333419FA /* AuthenticationManager.m in Sources */,
+ A725268792A6C2039D9C402B /* CheckoutViewController.m in Sources */,
+ 140EBDD7D126C0DB7E24563C /* Credentials.m in Sources */,
+ 0D0836D2DE975E4BF0F3D051 /* Readme.m in Sources */,
+ 335CAD4EA24AFBE63B9199B9 /* ReadmeViewController.m in Sources */,
+ 4EFDEFD372D670CB56731D3E /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ BDD30223625DA51AFB115FE3 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B596113707879825CDA4F233 /* AppDelegate.m in Sources */,
+ DFB6A101BCD151F5B9651D82 /* AuthenticationManager.m in Sources */,
+ EEDF56D9E060B1301014A6B0 /* CheckoutViewController.m in Sources */,
+ BD7243FA7D8B321F7E1B5BBF /* Credentials.m in Sources */,
+ 5C506223F8E16936EFF1ECAA /* Readme.m in Sources */,
+ 85EBAD10002EFE00116C0892 /* ReadmeViewController.m in Sources */,
+ D2A2CF406EE7D523247B45DD /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ DADCD7F86B712F9D6A7C1EB7 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D24015C9E60BC0AB214C4F83 /* AppDelegate.m in Sources */,
+ 6859B8749DCA922A8E670008 /* Credentials.m in Sources */,
+ 35D55D4145464F3D006D4019 /* Readme.m in Sources */,
+ B4AC1050912335DCAFDA50DC /* ReadmeViewController.m in Sources */,
+ 4D223F6F99924DC08BF93EE6 /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E2EFE22428A2F3EEA61751F5 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E7996808D67A3A1A043A0731 /* AppDelegate.m in Sources */,
+ A4BD0CF594F83266F2C9DFB1 /* CardsInfoViewController.m in Sources */,
+ 99EF7BD971D6D5849078F00F /* Credentials.m in Sources */,
+ D02EBC8DF2A796ED2C9CEFC0 /* Readme.m in Sources */,
+ B8FC11110451BE51D3352A0D /* ReadmeViewController.m in Sources */,
+ 55343C252FC045A6B70D521D /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ ED315B5B4830F964E3577CD9 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2A160FCCE45E4690E694D46A /* AppDelegate.m in Sources */,
+ 07DD9E6B75B3C3E0B7B93FF9 /* Credentials.m in Sources */,
+ 4B2B9B16A40D85A3093F1C41 /* CustomInAppMessagePresenter.m in Sources */,
+ ADBC780DCB0B446D08B01BD7 /* InAppMessageInfoViewController.m in Sources */,
+ 1A93472F1D5EF8BE86567BE6 /* Readme.m in Sources */,
+ 627920814F95860FB73D560F /* ReadmeViewController.m in Sources */,
+ 432AF81580216BC7FECF3E0A /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 385684E74F484291678D97E2 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E59DB4201FEAE1A212979375 /* PushNotificationsContentExtension */;
+ targetProxy = E63F56BE4C659BB9547002CB /* PBXContainerItemProxy */;
+ };
+ 66C7DD376098B1684E2BD062 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 842A3D91E0A246B872DA9846 /* PushNotificationsServiceExtension */;
+ targetProxy = 401588D076F789179E1A0954 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 415A55D2760CB84A0CC3A13B /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 142C43EBD6AA34841D26163C /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+ 5F65978FE19A988D7A5454A3 /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 34BD000896FB64DC78BBF177 /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 0226A27891A69D569C8744B7 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_ENTITLEMENTS = Sources/PushNotifications/PushNotifications.entitlements;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/PushNotifications/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications;
+ PRODUCT_NAME = PushNotifications;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ 04F3025123A8C0FDDB374DAA /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ INFOPLIST_FILE = Sources/Location/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Location-tvOS";
+ PRODUCT_NAME = Location;
+ SDKROOT = appletvos;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Debug;
+ };
+ 2F370EA03C55814B29C4BB55 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/Location/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Location-iOS";
+ PRODUCT_NAME = Location;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 31E178BAE5C8192F784A345A /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/Analytics/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Analytics-iOS";
+ PRODUCT_NAME = Analytics;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 338E775FC51FCA458B2B4AFB /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/ContentCards/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.ContentCards;
+ PRODUCT_NAME = ContentCards;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 35E8D78DF517B11959723F4D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "DEBUG=1",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TVOS_DEPLOYMENT_TARGET = 11.0;
+ };
+ name = Debug;
+ };
+ 4C1CEEB16B22B01668229861 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/ContentCards/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.ContentCards;
+ PRODUCT_NAME = ContentCards;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ 56FADC974A57962ED605AB39 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/InAppMessages/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.InAppMessages;
+ PRODUCT_NAME = InAppMessages;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 582C70DAA75E87B5B1B59BCC /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ SWIFT_VERSION = 5.0;
+ TVOS_DEPLOYMENT_TARGET = 11.0;
+ };
+ name = Release;
+ };
+ 650A8DC9E70B7FE040122B24 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/Analytics/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Analytics-iOS";
+ PRODUCT_NAME = Analytics;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ 6B390CBFB31F1AAE4B90AE70 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ INFOPLIST_FILE = "Sources/ContentCards-Custom-UI/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.ContentCards-Custom-UI-tvOS";
+ PRODUCT_NAME = "ContentCards-Custom-UI";
+ SDKROOT = appletvos;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Debug;
+ };
+ 6B3B491381885F5C52DC3552 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = "Sources/ContentCards-Custom-UI/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.ContentCards-Custom-UI-iOS";
+ PRODUCT_NAME = "ContentCards-Custom-UI";
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ 71303405F07C56DBF2524662 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = "Sources/InAppMessages-Custom-UI/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.InAppMessages-Custom-UI-iOS";
+ PRODUCT_NAME = "InAppMessages-Custom-UI";
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ 765C7F79F40719BB865D4941 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ INFOPLIST_FILE = Sources/Analytics/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Analytics-tvOS";
+ PRODUCT_NAME = Analytics;
+ SDKROOT = appletvos;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Debug;
+ };
+ 8C57CF25A4A9E9D075CEAF3E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ INFOPLIST_FILE = Sources/Location/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Location-tvOS";
+ PRODUCT_NAME = Location;
+ SDKROOT = appletvos;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Release;
+ };
+ 8F56A8E8C7781F27275F365C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ INFOPLIST_FILE = "Sources/InAppMessages-Custom-UI/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.InAppMessages-Custom-UI-tvOS";
+ PRODUCT_NAME = "InAppMessages-Custom-UI";
+ SDKROOT = appletvos;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Debug;
+ };
+ 95A967CAE2757BFC04407771 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ INFOPLIST_FILE = "Sources/ContentCards-Custom-UI/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.ContentCards-Custom-UI-tvOS";
+ PRODUCT_NAME = "ContentCards-Custom-UI";
+ SDKROOT = appletvos;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Release;
+ };
+ 97B315CB44E7F16916F9865E /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = "Sources/InAppMessages-Custom-UI/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.InAppMessages-Custom-UI-iOS";
+ PRODUCT_NAME = "InAppMessages-Custom-UI";
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 991EFD7B0772C9A99C44BCF4 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ INFOPLIST_FILE = "Sources/InAppMessages-Custom-UI/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.InAppMessages-Custom-UI-tvOS";
+ PRODUCT_NAME = "InAppMessages-Custom-UI";
+ SDKROOT = appletvos;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Release;
+ };
+ 9E13FBC998B0A5499C68208A /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INFOPLIST_FILE = Sources/PushNotificationsServiceExtension/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@executable_path/../../Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications.PushNotificationsServiceExtension;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ B9FD2D94FC2BF1DFA9DDA644 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_ENTITLEMENTS = Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements;
+ INFOPLIST_FILE = Sources/PushNotificationsContentExtension/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@executable_path/../../Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications.PushNotificationsContentExtension;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ BD14E68755890E23128DAB7A /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ INFOPLIST_FILE = Sources/Analytics/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Analytics-tvOS";
+ PRODUCT_NAME = Analytics;
+ SDKROOT = appletvos;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Release;
+ };
+ BE47B129D3210EFFB3B5C0E3 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_ENTITLEMENTS = Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements;
+ INFOPLIST_FILE = Sources/PushNotificationsContentExtension/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@executable_path/../../Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications.PushNotificationsContentExtension;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ C13597180247AEC71E86CD9C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = "Sources/ContentCards-Custom-UI/Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.ContentCards-Custom-UI-iOS";
+ PRODUCT_NAME = "ContentCards-Custom-UI";
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ DB1B706F4301DC478A0A4D4B /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_ENTITLEMENTS = Sources/PushNotifications/PushNotifications.entitlements;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/PushNotifications/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications;
+ PRODUCT_NAME = PushNotifications;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ F3C477DD3FBDBF3AB5B2FA92 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/InAppMessages/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.InAppMessages;
+ PRODUCT_NAME = InAppMessages;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ F83B82D7A7E5DB678B6196A6 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INFOPLIST_FILE = Sources/PushNotificationsServiceExtension/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@executable_path/../../Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications.PushNotificationsServiceExtension;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ FF5221A5B39619377D55A14C /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ INFOPLIST_FILE = Sources/Location/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Location-iOS";
+ PRODUCT_NAME = Location;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 121E4DAF0EB7FA3A0B03C3C0 /* Build configuration list for PBXProject "Examples-SwiftPM" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 35E8D78DF517B11959723F4D /* Debug */,
+ 582C70DAA75E87B5B1B59BCC /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ 264E98511670D6BD7B0E64D2 /* Build configuration list for PBXNativeTarget "Analytics-iOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 31E178BAE5C8192F784A345A /* Debug */,
+ 650A8DC9E70B7FE040122B24 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ 340804EFAD862F854E93596B /* Build configuration list for PBXNativeTarget "Location-tvOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 04F3025123A8C0FDDB374DAA /* Debug */,
+ 8C57CF25A4A9E9D075CEAF3E /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ 35795D9DBF2411B548D5563D /* Build configuration list for PBXNativeTarget "PushNotifications" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ DB1B706F4301DC478A0A4D4B /* Debug */,
+ 0226A27891A69D569C8744B7 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ 52115E4788F114BD9F51C612 /* Build configuration list for PBXNativeTarget "ContentCards-Custom-UI-iOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C13597180247AEC71E86CD9C /* Debug */,
+ 6B3B491381885F5C52DC3552 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ 538A7D3F62B432A07C91FD40 /* Build configuration list for PBXNativeTarget "PushNotificationsContentExtension" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ BE47B129D3210EFFB3B5C0E3 /* Debug */,
+ B9FD2D94FC2BF1DFA9DDA644 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ 5FD7F38C2E047474FF2AE862 /* Build configuration list for PBXNativeTarget "InAppMessages-Custom-UI-tvOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8F56A8E8C7781F27275F365C /* Debug */,
+ 991EFD7B0772C9A99C44BCF4 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ 675C55871E9EBBD8A4279B5C /* Build configuration list for PBXNativeTarget "ContentCards-Custom-UI-tvOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 6B390CBFB31F1AAE4B90AE70 /* Debug */,
+ 95A967CAE2757BFC04407771 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ 9D5AEEE5B58C1044A4BA612B /* Build configuration list for PBXNativeTarget "Location-iOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 2F370EA03C55814B29C4BB55 /* Debug */,
+ FF5221A5B39619377D55A14C /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ DAC0A7E698E628D993F35934 /* Build configuration list for PBXNativeTarget "ContentCards" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 338E775FC51FCA458B2B4AFB /* Debug */,
+ 4C1CEEB16B22B01668229861 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ E00B5C25BE5714D67E69A3EF /* Build configuration list for PBXNativeTarget "Analytics-tvOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 765C7F79F40719BB865D4941 /* Debug */,
+ BD14E68755890E23128DAB7A /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ EBB530AA4E1F5AF1FD5D5B58 /* Build configuration list for PBXNativeTarget "InAppMessages-Custom-UI-iOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 97B315CB44E7F16916F9865E /* Debug */,
+ 71303405F07C56DBF2524662 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ F76B079D8771880EE7A2C01D /* Build configuration list for PBXNativeTarget "InAppMessages" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 56FADC974A57962ED605AB39 /* Debug */,
+ F3C477DD3FBDBF3AB5B2FA92 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+ FB6122990820F57E6DB4A7D6 /* Build configuration list for PBXNativeTarget "PushNotificationsServiceExtension" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F83B82D7A7E5DB678B6196A6 /* Debug */,
+ 9E13FBC998B0A5499C68208A /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Debug;
+ };
+/* End XCConfigurationList section */
+
+/* Begin XCRemoteSwiftPackageReference section */
+ 9928D5150C45879A982BA1C6 /* XCRemoteSwiftPackageReference "SDWebImage" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/SDWebImage/SDWebImage";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 5.12.5;
+ };
+ };
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+ 046845029FE9235B46B84104 /* BrazeKit */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = BrazeKit;
+ };
+ 09701E67CAE64FCE46458059 /* BrazeKit */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = BrazeKit;
+ };
+ 0BF370808D2F5C21870331A0 /* SDWebImage */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 9928D5150C45879A982BA1C6 /* XCRemoteSwiftPackageReference "SDWebImage" */;
+ productName = SDWebImage;
+ };
+ 0D08CDAB0AE57DFC38F9B590 /* SDWebImage */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 9928D5150C45879A982BA1C6 /* XCRemoteSwiftPackageReference "SDWebImage" */;
+ productName = SDWebImage;
+ };
+ 17D80570112755DC2EEEF450 /* BrazeKit */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = BrazeKit;
+ };
+ 26C11D75220DCD8456AEAA39 /* BrazeUI */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = BrazeUI;
+ };
+ 2C4994F9E91F986F0629979F /* BrazeLocation */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = BrazeLocation;
+ };
+ 47F3E12B1114B00B4CB70C60 /* BrazeNotificationService */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = BrazeNotificationService;
+ };
+ 5133F5A2D91882A4AE649D4D /* BrazePushStory */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = BrazePushStory;
+ };
+ 74D6487EFD8114F6B61637AB /* BrazeKit */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = BrazeKit;
+ };
+ 7793FD8C8DE601EC38DD8DD7 /* BrazeKit */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = BrazeKit;
+ };
+ 80661DB9711EFD43546E249C /* BrazeKit */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = BrazeKit;
+ };
+ 89598718421C181B57346379 /* BrazeKit */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = BrazeKit;
+ };
+ 9AF0AF048F752A5C62317470 /* BrazeUI */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = BrazeUI;
+ };
+ 9F5A50D1AF8D80AC6C465155 /* BrazeKit */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = BrazeKit;
+ };
+ A2D57BF9CEBB2DC10A5B3AE6 /* BrazeLocation */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = BrazeLocation;
+ };
+ F173FCAB52D0340802119A34 /* BrazeKit */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = BrazeKit;
+ };
+ F4168F1485105BAAD54B813C /* BrazeKit */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = BrazeKit;
+ };
+ F68192C4A0D4928F78762878 /* BrazeKit */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = BrazeKit;
+ };
+/* End XCSwiftPackageProductDependency section */
+ };
+ rootObject = D0C505F98E2813EFE5D58816 /* Project object */;
+}
diff --git a/Examples/Examples-SwiftPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/ObjC/Examples-SwiftPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata
similarity index 100%
rename from Examples/Examples-SwiftPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata
rename to Examples/ObjC/Examples-SwiftPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata
diff --git a/Examples/Package.swift b/Examples/ObjC/Package.swift
similarity index 100%
rename from Examples/Package.swift
rename to Examples/ObjC/Package.swift
diff --git a/Examples/Podfile b/Examples/ObjC/Podfile
similarity index 100%
rename from Examples/Podfile
rename to Examples/ObjC/Podfile
diff --git a/Examples/ObjC/Sources/Analytics/AppDelegate.h b/Examples/ObjC/Sources/Analytics/AppDelegate.h
new file mode 100644
index 0000000000..39f6d4eb6e
--- /dev/null
+++ b/Examples/ObjC/Sources/Analytics/AppDelegate.h
@@ -0,0 +1,11 @@
+@import UIKit;
+@import BrazeKit;
+
+extern NSString *const brazeApiKey;
+extern NSString *const brazeEndpoint;
+
+@interface AppDelegate : UIResponder
+
+@property(class, strong, nonatomic) Braze *braze;
+
+@end
diff --git a/Examples/ObjC/Sources/Analytics/AppDelegate.m b/Examples/ObjC/Sources/Analytics/AppDelegate.m
new file mode 100644
index 0000000000..2f461c55ce
--- /dev/null
+++ b/Examples/ObjC/Sources/Analytics/AppDelegate.m
@@ -0,0 +1,35 @@
+#import "AppDelegate.h"
+
+@import BrazeKit;
+
+@implementation AppDelegate
+
+#pragma mark - Lifecycle
+
+- (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ // Setup Braze
+ BRZConfiguration *configuration =
+ [[BRZConfiguration alloc] initWithApiKey:brazeApiKey
+ endpoint:brazeEndpoint];
+ configuration.logger.level = BRZLoggerLevelInfo;
+ Braze *braze = [[Braze alloc] initWithConfiguration:configuration];
+ AppDelegate.braze = braze;
+
+ [self.window makeKeyAndVisible];
+ return YES;
+}
+
+#pragma mark - AppDelegate.braze
+
+static Braze *_braze = nil;
+
++ (Braze *)braze {
+ return _braze;
+}
+
++ (void)setBraze:(Braze *)braze {
+ _braze = braze;
+}
+
+@end
diff --git a/Examples/ObjC/Sources/Analytics/AuthenticationManager.h b/Examples/ObjC/Sources/Analytics/AuthenticationManager.h
new file mode 100644
index 0000000000..74db8f8851
--- /dev/null
+++ b/Examples/ObjC/Sources/Analytics/AuthenticationManager.h
@@ -0,0 +1,23 @@
+@import Foundation;
+
+NS_ASSUME_NONNULL_BEGIN
+
+#pragma mark - User
+
+@interface User : NSObject
+
+@property(copy, nonatomic) NSString *identifier;
+@property(copy, nonatomic) NSString *email;
+@property(strong, nonatomic) NSDate *birthday;
+
+@end
+
+#pragma mark - AuthenticationManager
+
+@interface AuthenticationManager : NSObject
+
+- (void)userDidLogin:(User *)user;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Examples/ObjC/Sources/Analytics/AuthenticationManager.m b/Examples/ObjC/Sources/Analytics/AuthenticationManager.m
new file mode 100644
index 0000000000..5438873804
--- /dev/null
+++ b/Examples/ObjC/Sources/Analytics/AuthenticationManager.m
@@ -0,0 +1,22 @@
+#import "AuthenticationManager.h"
+#import "AppDelegate.h"
+
+#pragma mark - User
+
+@implementation User
+@end
+
+#pragma mark - AuthenticationManager
+
+@implementation AuthenticationManager
+
+- (void)userDidLogin:(User *)user {
+ [AppDelegate.braze changeUser:user.identifier];
+ BRZUser *brazeUser = AppDelegate.braze.user;
+ [brazeUser setEmail:user.email];
+ [brazeUser setDateOfBirth:user.birthday];
+ [brazeUser setCustomAttributeWithKey:@"last_login_date"
+ dateValue:[NSDate date]];
+}
+
+@end
diff --git a/Examples/ObjC/Sources/Analytics/CheckoutViewController.h b/Examples/ObjC/Sources/Analytics/CheckoutViewController.h
new file mode 100644
index 0000000000..1f5cf3fb6c
--- /dev/null
+++ b/Examples/ObjC/Sources/Analytics/CheckoutViewController.h
@@ -0,0 +1,17 @@
+@import UIKit;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface CheckoutViewController : UIViewController
+
+/// The internal checkout identifier
+@property(copy, nonatomic) NSString *checkoutId;
+
+/// The list of identifiers for the products to checkout
+@property(strong, nonatomic) NSArray *productIds;
+
+- (void)userDidPurchaseProduct:(NSString *)productId;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Examples/ObjC/Sources/Analytics/CheckoutViewController.m b/Examples/ObjC/Sources/Analytics/CheckoutViewController.m
new file mode 100644
index 0000000000..ff7bf8fdea
--- /dev/null
+++ b/Examples/ObjC/Sources/Analytics/CheckoutViewController.m
@@ -0,0 +1,34 @@
+#import "CheckoutViewController.h"
+#import "AppDelegate.h"
+
+@interface CheckoutViewController ()
+
+- (double)priceForProduct:(NSString *)productId;
+
+@end
+
+@implementation CheckoutViewController
+
+- (void)viewDidAppear:(BOOL)animated {
+ [super viewDidAppear:animated];
+ [AppDelegate.braze logCustomEvent:@"open_checkout_controller"
+ properties:@{
+ @"checkout_id" : self.checkoutId,
+ @"product_ids" : self.productIds,
+ }];
+}
+
+- (void)userDidPurchaseProduct:(NSString *)productId {
+ double price = [self priceForProduct:productId];
+ [AppDelegate.braze logPurchase:productId
+ currency:@"USD"
+ price:price
+ properties:@{@"checkout_id" : self.checkoutId}];
+}
+
+- (double)priceForProduct:(NSString *)productId {
+ NSArray *prices = @[ @0.5, @8.0, @14.99, @0, @999.999 ];
+ return prices[arc4random_uniform((uint32_t)prices.count)].doubleValue;
+}
+
+@end
diff --git a/Examples/Sources/Analytics/Info.plist b/Examples/ObjC/Sources/Analytics/Info.plist
similarity index 100%
rename from Examples/Sources/Analytics/Info.plist
rename to Examples/ObjC/Sources/Analytics/Info.plist
diff --git a/Examples/ObjC/Sources/Analytics/Readme.m b/Examples/ObjC/Sources/Analytics/Readme.m
new file mode 100644
index 0000000000..26f49ec436
--- /dev/null
+++ b/Examples/ObjC/Sources/Analytics/Readme.m
@@ -0,0 +1,102 @@
+#import "AuthenticationManager.h"
+#import "CheckoutViewController.h"
+#import "ReadmeAction.h"
+#import "ReadmeViewController.h"
+
+#pragma mark - Internal
+
+static AuthenticationManager *_authenticationManager;
+
+AuthenticationManager *authenticationManager(void) {
+ if (!_authenticationManager) {
+ _authenticationManager = [[AuthenticationManager alloc] init];
+ }
+ return _authenticationManager;
+}
+
+UINavigationController *createCheckoutNavigationController(void) {
+ NSArray *productIds = @[
+ [NSUUID UUID].UUIDString,
+ [NSUUID UUID].UUIDString,
+ [NSUUID UUID].UUIDString,
+ ];
+
+ CheckoutViewController *checkoutViewController =
+ [[CheckoutViewController alloc] init];
+ checkoutViewController.checkoutId = [NSUUID UUID].UUIDString;
+ checkoutViewController.productIds = productIds;
+ checkoutViewController.title = @"CheckoutViewController";
+ checkoutViewController.view.backgroundColor = UIColor.whiteColor;
+
+ UINavigationController *navigationController = [[UINavigationController alloc]
+ initWithRootViewController:checkoutViewController];
+
+ return navigationController;
+}
+
+void authenticateUser(void) {
+ User *user = [[User alloc] init];
+ user.identifier = [NSUUID UUID].UUIDString;
+ user.email = @"user@example.com";
+ user.birthday = [NSDate dateWithTimeIntervalSince1970:0];
+ [authenticationManager() userDidLogin:user];
+}
+
+void presentCheckout(ReadmeViewController *viewController) {
+ UINavigationController *navigationController =
+ createCheckoutNavigationController();
+ [viewController presentViewController:navigationController
+ animated:YES
+ completion:nil];
+}
+
+void presentCheckoutAndPurchase(ReadmeViewController *viewController) {
+ UINavigationController *navigationController =
+ createCheckoutNavigationController();
+ CheckoutViewController *checkoutViewController =
+ navigationController.viewControllers.firstObject;
+ [viewController
+ presentViewController:navigationController
+ animated:YES
+ completion:^{
+ [checkoutViewController
+ userDidPurchaseProduct:[NSUUID UUID].UUIDString];
+ }];
+}
+
+#pragma mark - Readme
+
+NSString *const readme =
+ @"This sample presents how to use the analytics features of the SDK.\n"
+ @"\n"
+ @"See files:\n"
+ @"- AppDelegate.{h,m}\n"
+ @" - Configure Braze\n"
+ @"- AuthenticationManager.m\n"
+ @" - Identify the user\n"
+ @"- CheckoutViewController.m\n"
+ @" - Log custom events\n"
+ @" - Log purchases";
+
+NSInteger const actionsCount = 3;
+
+ReadmeAction const actions[] = {{@"Authenticate user",
+ @"Identify the user on Braze",
+ ^(ReadmeViewController *_Nonnull _){
+ authenticateUser();
+}
+}
+, {@"Present checkout", @"Log \"open_checkout_controller\" custom event",
+ ^(ReadmeViewController *_Nonnull viewController){
+ presentCheckout(viewController);
+}
+}
+, {@"Present checkout and purchase a product",
+ @"Log \"open_checkout_controller\" custom event and a purchase",
+ ^(ReadmeViewController *_Nonnull viewController){
+ presentCheckoutAndPurchase(viewController);
+}
+}
+,
+}
+;
diff --git a/Examples/Sources/Common/Assets.xcassets/AccentColor.colorset/Contents.json b/Examples/ObjC/Sources/Common/Assets.xcassets/AccentColor.colorset/Contents.json
similarity index 100%
rename from Examples/Sources/Common/Assets.xcassets/AccentColor.colorset/Contents.json
rename to Examples/ObjC/Sources/Common/Assets.xcassets/AccentColor.colorset/Contents.json
diff --git a/Examples/Sources/Common/Assets.xcassets/AppIcon.appiconset/Contents.json b/Examples/ObjC/Sources/Common/Assets.xcassets/AppIcon.appiconset/Contents.json
similarity index 100%
rename from Examples/Sources/Common/Assets.xcassets/AppIcon.appiconset/Contents.json
rename to Examples/ObjC/Sources/Common/Assets.xcassets/AppIcon.appiconset/Contents.json
diff --git a/Examples/Sources/Common/Assets.xcassets/Contents.json b/Examples/ObjC/Sources/Common/Assets.xcassets/Contents.json
similarity index 100%
rename from Examples/Sources/Common/Assets.xcassets/Contents.json
rename to Examples/ObjC/Sources/Common/Assets.xcassets/Contents.json
diff --git a/Examples/ObjC/Sources/Common/Credentials.m b/Examples/ObjC/Sources/Common/Credentials.m
new file mode 100644
index 0000000000..36077aa7a3
--- /dev/null
+++ b/Examples/ObjC/Sources/Common/Credentials.m
@@ -0,0 +1,7 @@
+@import Foundation;
+
+#warning Replace with your Braze api key
+NSString *const brazeApiKey = @"BRAZE_API_KEY";
+
+#warning Replace with your Braze endpoint
+NSString *const brazeEndpoint = @"BRAZE_ENDPOINT";
diff --git a/Examples/ObjC/Sources/Common/ReadmeAction.h b/Examples/ObjC/Sources/Common/ReadmeAction.h
new file mode 100644
index 0000000000..f71f48353d
--- /dev/null
+++ b/Examples/ObjC/Sources/Common/ReadmeAction.h
@@ -0,0 +1,9 @@
+@import Foundation;
+
+@class ReadmeViewController;
+
+typedef struct ReadmeAction {
+ NSString *title;
+ NSString *subtitle;
+ void (^action)(ReadmeViewController *);
+} ReadmeAction;
diff --git a/Examples/ObjC/Sources/Common/ReadmeViewController.h b/Examples/ObjC/Sources/Common/ReadmeViewController.h
new file mode 100644
index 0000000000..66e1cfe1de
--- /dev/null
+++ b/Examples/ObjC/Sources/Common/ReadmeViewController.h
@@ -0,0 +1,9 @@
+@import UIKit;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ReadmeViewController : UITableViewController
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Examples/ObjC/Sources/Common/ReadmeViewController.m b/Examples/ObjC/Sources/Common/ReadmeViewController.m
new file mode 100644
index 0000000000..2f21ed7daa
--- /dev/null
+++ b/Examples/ObjC/Sources/Common/ReadmeViewController.m
@@ -0,0 +1,142 @@
+#import "ReadmeViewController.h"
+#import "AppDelegate.h"
+#import "ReadmeAction.h"
+
+extern NSString *const readme;
+extern ReadmeAction const actions[];
+extern NSInteger const actionsCount;
+
+@interface ReadmeViewController ()
+
+@property(strong, nonatomic) UITextView *readmeTextView;
+
+@end
+
+@implementation ReadmeViewController
+
+- (instancetype)init {
+ self = [super initWithStyle:UITableViewStyleGrouped];
+ if (self) {
+
+ // Set title
+ self.title = [NSBundle.mainBundle
+ objectForInfoDictionaryKey:(NSString *)kCFBundleNameKey];
+
+ // Set readme text
+ self.readmeTextView.text =
+ [NSString stringWithFormat:@"# Readme\n\n%@", readme];
+ self.tableView.tableHeaderView = self.readmeTextView;
+ }
+ return self;
+}
+
+#pragma mark - Layout
+
+- (void)viewWillLayoutSubviews {
+ [super viewWillLayoutSubviews];
+
+ CGSize size = [self.readmeTextView
+ systemLayoutSizeFittingSize:(CGSize){self.tableView.bounds.size.width,
+ 1000}];
+ if (self.readmeTextView.frame.size.height != size.height) {
+ CGRect frame = self.readmeTextView.frame;
+ frame.size.height = size.height;
+ self.readmeTextView.frame = frame;
+ }
+}
+
+#pragma mark - UITableViewDataSource
+
+- (NSInteger)tableView:(UITableView *)tableView
+ numberOfRowsInSection:(NSInteger)section {
+ return actionsCount;
+}
+
+- (NSString *)tableView:(UITableView *)tableView
+ titleForHeaderInSection:(NSInteger)section {
+ return @"Actions";
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView
+ cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+ NSString *const identifier = @"cellIdentifier";
+ UITableViewCell *cell =
+ [tableView dequeueReusableCellWithIdentifier:identifier];
+ if (!cell) {
+ cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
+ reuseIdentifier:identifier];
+ }
+ cell.textLabel.text = actions[indexPath.row].title;
+ cell.detailTextLabel.text = actions[indexPath.row].subtitle;
+ return cell;
+}
+
+#pragma mark - UITableViewDelegate
+
+- (void)tableView:(UITableView *)tableView
+ didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+ void (^action)(ReadmeViewController *) = actions[indexPath.row].action;
+ action(self);
+ [tableView deselectRowAtIndexPath:indexPath animated:true];
+}
+
+#pragma mark - Lazy Properties Instanciation
+
+- (UITextView *)readmeTextView {
+ if (!_readmeTextView) {
+ UITextView *textView = [[UITextView alloc] init];
+ textView.backgroundColor = UIColor.clearColor;
+ [textView setScrollEnabled:NO];
+
+#if TARGET_OS_IOS
+ [textView setEditable:NO];
+ textView.textContainerInset = UIEdgeInsetsMake(16, 16, 0, 16);
+ if (@available(iOS 13.0, *)) {
+ textView.font = [UIFont monospacedSystemFontOfSize:12
+ weight:UIFontWeightRegular];
+ }
+#elif TARGET_OS_TV
+ textView.textContainerInset = UIEdgeInsetsMake(0, 16 * 6, 16 * 4, 16 * 6);
+ if (@available(tvOS 13.0, *)) {
+ textView.font = [UIFont monospacedSystemFontOfSize:30
+ weight:UIFontWeightRegular];
+ }
+#endif
+
+ _readmeTextView = textView;
+ }
+ return _readmeTextView;
+}
+
+@end
+
+#pragma mark - AutoReadme
+
+static NSString *const _window;
+
+@implementation AppDelegate (AutoWindow)
+
++ (UIWindow *)_auto_window {
+ static dispatch_once_t once;
+ static UIWindow *window;
+ dispatch_once(&once, ^{
+ ReadmeViewController *readmeViewController =
+ [[ReadmeViewController alloc] init];
+ UINavigationController *navigationController =
+ [[UINavigationController alloc]
+ initWithRootViewController:readmeViewController];
+ window = [[UIWindow alloc] init];
+ window.rootViewController = navigationController;
+ });
+ return window;
+}
+
+- (UIWindow *)window {
+ return [AppDelegate _auto_window];
+}
+
+- (void)setWindow:(UIWindow *)window {
+ // noop
+}
+
+@end
diff --git a/Examples/Sources/Common/iOS/Base.lproj/LaunchScreen.storyboard b/Examples/ObjC/Sources/Common/iOS/Base.lproj/LaunchScreen.storyboard
similarity index 100%
rename from Examples/Sources/Common/iOS/Base.lproj/LaunchScreen.storyboard
rename to Examples/ObjC/Sources/Common/iOS/Base.lproj/LaunchScreen.storyboard
diff --git a/Examples/ObjC/Sources/Common/main.m b/Examples/ObjC/Sources/Common/main.m
new file mode 100644
index 0000000000..efc8505ecb
--- /dev/null
+++ b/Examples/ObjC/Sources/Common/main.m
@@ -0,0 +1,11 @@
+#import "AppDelegate.h"
+
+@import UIKit;
+
+int main(int argc, char *argv[]) {
+ NSString *appDelegateClassName;
+ @autoreleasepool {
+ appDelegateClassName = NSStringFromClass([AppDelegate class]);
+ }
+ return UIApplicationMain(argc, argv, nil, appDelegateClassName);
+}
diff --git a/Examples/Sources/Common/tvOS/Base.lproj/LaunchScreen.storyboard b/Examples/ObjC/Sources/Common/tvOS/Base.lproj/LaunchScreen.storyboard
similarity index 100%
rename from Examples/Sources/Common/tvOS/Base.lproj/LaunchScreen.storyboard
rename to Examples/ObjC/Sources/Common/tvOS/Base.lproj/LaunchScreen.storyboard
diff --git a/Examples/ObjC/Sources/ContentCards-Custom-UI/AppDelegate.h b/Examples/ObjC/Sources/ContentCards-Custom-UI/AppDelegate.h
new file mode 100644
index 0000000000..194100359e
--- /dev/null
+++ b/Examples/ObjC/Sources/ContentCards-Custom-UI/AppDelegate.h
@@ -0,0 +1,17 @@
+@import UIKit;
+@import BrazeKit;
+
+extern NSString *const brazeApiKey;
+extern NSString *const brazeEndpoint;
+
+@interface AppDelegate : UIResponder
+
+@property(class, strong, nonatomic) Braze *braze;
+
+- (void)printCurrentContentCards;
+- (void)refreshContentCards;
+- (void)subscribeToContentCardsUpdates;
+- (void)cancelContentCardsUpdatesSubscription;
+- (void)presentContentCardsInfoViewController;
+
+@end
diff --git a/Examples/ObjC/Sources/ContentCards-Custom-UI/AppDelegate.m b/Examples/ObjC/Sources/ContentCards-Custom-UI/AppDelegate.m
new file mode 100644
index 0000000000..9c202c982d
--- /dev/null
+++ b/Examples/ObjC/Sources/ContentCards-Custom-UI/AppDelegate.m
@@ -0,0 +1,110 @@
+#import "AppDelegate.h"
+#import "CardsInfoViewController.h"
+
+@import BrazeKit;
+
+@interface AppDelegate ()
+
+// The subscription needs to be retained to be active.
+@property(strong, nonatomic) BRZCancellable *cardsSubscription;
+
+@end
+
+@implementation AppDelegate
+
+#pragma mark - Lifecycle
+
+- (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ // Setup Braze
+ BRZConfiguration *configuration =
+ [[BRZConfiguration alloc] initWithApiKey:brazeApiKey
+ endpoint:brazeEndpoint];
+ configuration.logger.level = BRZLoggerLevelInfo;
+ Braze *braze = [[Braze alloc] initWithConfiguration:configuration];
+ AppDelegate.braze = braze;
+
+ [self.window makeKeyAndVisible];
+ return YES;
+}
+
+#pragma mark - AppDelegate.braze
+
+static Braze *_braze = nil;
+
++ (Braze *)braze {
+ return _braze;
+}
+
++ (void)setBraze:(Braze *)braze {
+ _braze = braze;
+}
+
+#pragma mark - Displaying Content Cards
+
+- (void)printCurrentContentCards {
+ // Print all the cards
+ NSLog(@"%@", AppDelegate.braze.contentCards.cards);
+
+ BRZContentCardRaw *cardRaw = AppDelegate.braze.contentCards.cards.firstObject;
+ if (cardRaw == nil) {
+ return;
+ }
+
+ // Access the `extras` dictionary / `url`:
+
+ NSLog(@"extras: %@", cardRaw.extras);
+ NSLog(@"url: %@", cardRaw.url);
+
+ // Access the `title` / `image`
+
+ if (cardRaw.title != nil) {
+ NSLog(@"title: %@", cardRaw.title);
+ }
+
+ if (cardRaw.image != nil) {
+ NSLog(@"image: %@", cardRaw.image);
+ }
+
+ // A wrapper / compatibility representation of the card is accessible via
+ // `-json`.
+ NSData *jsonData = [cardRaw json];
+ NSString *jsonString = [[NSString alloc] initWithData:jsonData
+ encoding:NSUTF8StringEncoding];
+ if (jsonString != nil) {
+ NSLog(@"%@", jsonString);
+ }
+}
+
+- (void)refreshContentCards {
+ [AppDelegate.braze.contentCards
+ requestRefreshWithCompletion:^(
+ NSArray *_Nullable cards,
+ NSError *_Nullable error) {
+ NSLog(@"cards: %@", cards);
+ NSLog(@"error: %@", error);
+ }];
+}
+
+- (void)subscribeToContentCardsUpdates {
+ self.cardsSubscription = [AppDelegate.braze.contentCards
+ subscribeToUpdates:^(NSArray *_Nonnull cards) {
+ NSLog(@"cards: %@", cards);
+ }];
+}
+
+- (void)cancelContentCardsUpdatesSubscription {
+ [self.cardsSubscription cancel];
+}
+
+- (void)presentContentCardsInfoViewController {
+ CardsInfoViewController *viewController = [[CardsInfoViewController alloc]
+ initWithCards:AppDelegate.braze.contentCards.cards];
+ UINavigationController *navigationController = [[UINavigationController alloc]
+ initWithRootViewController:viewController];
+ [self.window.rootViewController presentViewController:navigationController
+ animated:YES
+ completion:nil];
+}
+
+@end
diff --git a/Examples/ObjC/Sources/ContentCards-Custom-UI/CardsInfoViewController.h b/Examples/ObjC/Sources/ContentCards-Custom-UI/CardsInfoViewController.h
new file mode 100644
index 0000000000..f3fdfa4f4d
--- /dev/null
+++ b/Examples/ObjC/Sources/ContentCards-Custom-UI/CardsInfoViewController.h
@@ -0,0 +1,9 @@
+@import UIKit;
+
+@class BRZContentCardRaw;
+
+@interface CardsInfoViewController : UITableViewController
+
+- (instancetype)initWithCards:(NSArray *)cards;
+
+@end
diff --git a/Examples/ObjC/Sources/ContentCards-Custom-UI/CardsInfoViewController.m b/Examples/ObjC/Sources/ContentCards-Custom-UI/CardsInfoViewController.m
new file mode 100644
index 0000000000..c310086793
--- /dev/null
+++ b/Examples/ObjC/Sources/ContentCards-Custom-UI/CardsInfoViewController.m
@@ -0,0 +1,200 @@
+#import "CardsInfoViewController.h"
+
+@import UIKit;
+@import BrazeKit;
+
+#pragma mark - Field / Section
+
+@interface Field : NSObject
+
+@property(copy, nonatomic) NSString *name;
+@property(strong, nonatomic) id value;
+@property(assign, nonatomic) NSInteger indentation;
+
++ (instancetype)fieldWithName:(NSString *)name value:(id)value;
++ (instancetype)fieldWithName:(NSString *)name
+ value:(id)value
+ indentation:(NSInteger)indentation;
+
+@end
+
+@interface Section : NSObject
+
+@property(copy, nonatomic) NSString *name;
+@property(strong, nonatomic) NSArray *fields;
+
+@end
+
+#pragma mark - CardsInfoViewController
+
+@interface CardsInfoViewController ()
+
+@property(strong, nonatomic) NSArray *sections;
+
++ (Section *)cardSectionFromCard:(BRZContentCardRaw *)card
+ atIndex:(NSInteger)index;
+
+@end
+
+@implementation CardsInfoViewController
+
+- (instancetype)initWithCards:(NSArray *)cards {
+ self = [super initWithStyle:UITableViewStyleGrouped];
+ if (self) {
+ NSMutableArray *sections = [NSMutableArray array];
+ for (NSInteger i = 0; i < cards.count; ++i) {
+ BRZContentCardRaw *card = cards[i];
+ [sections addObject:[CardsInfoViewController cardSectionFromCard:card
+ atIndex:i]];
+ }
+ self.sections = [sections copy];
+
+ self.title = @"Content Cards Info";
+
+ UIBarButtonItem *doneButton = [[UIBarButtonItem alloc]
+ initWithBarButtonSystemItem:UIBarButtonSystemItemDone
+ target:self
+ action:@selector(dismissModal)];
+ [self.navigationItem setRightBarButtonItem:doneButton];
+
+ self.tableView.rowHeight = UITableViewAutomaticDimension;
+ self.tableView.estimatedRowHeight = 44.0;
+ }
+ return self;
+}
+
+- (void)dismissModal {
+ [self dismissViewControllerAnimated:YES completion:nil];
+}
+
+#pragma mark - UITableViewDataSource
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
+ return self.sections.count;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView
+ numberOfRowsInSection:(NSInteger)section {
+ return self.sections[section].fields.count;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView
+ cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+ UITableViewCell *cell =
+ [tableView dequeueReusableCellWithIdentifier:@"cellIdentifier"];
+ if (cell == nil) {
+ cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
+ reuseIdentifier:@"cellIdentifier"];
+ }
+
+ Field *field = self.sections[indexPath.section].fields[indexPath.row];
+ cell.textLabel.text = field.name;
+ cell.detailTextLabel.text = [NSString stringWithFormat:@"%@", field.value];
+ cell.indentationLevel = field.indentation;
+
+ cell.textLabel.numberOfLines = 0;
+ if (@available(iOS 13.0, tvOS 13.0, *)) {
+ cell.textLabel.font =
+ [UIFont monospacedSystemFontOfSize:13 weight:UIFontWeightRegular];
+ cell.detailTextLabel.font =
+ [UIFont monospacedSystemFontOfSize:13 weight:UIFontWeightRegular];
+ }
+
+ return cell;
+}
+
+#pragma mark - UITableViewDelegate
+
+- (NSString *)tableView:(UITableView *)tableView
+ titleForHeaderInSection:(NSInteger)section {
+ return self.sections[section].name;
+}
+
++ (Section *)cardSectionFromCard:(BRZContentCardRaw *)card
+ atIndex:(NSInteger)index {
+ NSMutableArray *fields = [NSMutableArray array];
+
+ switch (card.type) {
+ case BRZContentCardRawTypeClassic:
+ [fields addObject:[Field fieldWithName:@"type" value:@"classic"]];
+ break;
+ case BRZContentCardRawTypeBanner:
+ [fields addObject:[Field fieldWithName:@"type" value:@"banner"]];
+ break;
+ case BRZContentCardRawTypeCaptionedImage:
+ [fields addObject:[Field fieldWithName:@"type" value:@"captionedImage"]];
+ break;
+ case BRZContentCardRawTypeControl:
+ [fields addObject:[Field fieldWithName:@"type" value:@"control"]];
+ break;
+ default:
+ break;
+ }
+
+ [fields addObject:[Field fieldWithName:@"id" value:card.identifier]];
+ [fields addObject:[Field fieldWithName:@"image" value:card.image]];
+ [fields addObject:[Field fieldWithName:@"imageAspectRation"
+ value:@(card.imageAspectRatio)]];
+ [fields addObject:[Field fieldWithName:@"title" value:card.title]];
+ [fields addObject:[Field fieldWithName:@"description"
+ value:card.cardDescription]];
+ [fields addObject:[Field fieldWithName:@"domain" value:card.domain]];
+ [fields addObject:[Field fieldWithName:@"url" value:card.url]];
+ [fields addObject:[Field fieldWithName:@"useWebView"
+ value:@(card.useWebView)]];
+ [fields addObject:[Field fieldWithName:@"viewed" value:@(card.viewed)]];
+ [fields addObject:[Field fieldWithName:@"dismissible"
+ value:@(card.dismissible)]];
+ [fields addObject:[Field fieldWithName:@"removed" value:@(card.removed)]];
+ [fields addObject:[Field fieldWithName:@"pinned" value:@(card.pinned)]];
+ [fields addObject:[Field fieldWithName:@"clicked" value:@(card.clicked)]];
+ [fields addObject:[Field fieldWithName:@"test" value:@(card.test)]];
+ [fields addObject:[Field fieldWithName:@"createdAt" value:@(card.createdAt)]];
+ [fields addObject:[Field fieldWithName:@"expiresAt" value:@(card.expiresAt)]];
+
+ NSData *extrasData = [NSJSONSerialization dataWithJSONObject:card.extras
+ options:0
+ error:nil];
+ NSString *extrasString = [[NSString alloc] initWithData:extrasData
+ encoding:NSUTF8StringEncoding];
+ [fields addObject:[Field fieldWithName:@"extras" value:@""]];
+ [fields addObject:[Field fieldWithName:extrasString value:@"" indentation:1]];
+
+ Section *section = [[Section alloc] init];
+ section.name = [NSString stringWithFormat:@"Card %ld", index];
+ section.fields = [fields copy];
+
+ return section;
+}
+
+@end
+
+#pragma mark - Field / Section Implementation
+
+@implementation Field
+
+- (instancetype)initWithName:(NSString *)name value:(id)value {
+ self = [super init];
+ if (self) {
+ self.name = name;
+ self.value = value;
+ }
+ return self;
+}
+
++ (instancetype)fieldWithName:(NSString *)name value:(id)value {
+ return [[Field alloc] initWithName:name value:value];
+}
+
++ (instancetype)fieldWithName:(NSString *)name
+ value:(id)value
+ indentation:(NSInteger)indentation {
+ Field *field = [Field fieldWithName:name value:value];
+ field.indentation = indentation;
+ return field;
+}
+
+@end
+
+@implementation Section
+@end
diff --git a/Examples/Sources/ContentCards-Custom-UI/Info.plist b/Examples/ObjC/Sources/ContentCards-Custom-UI/Info.plist
similarity index 100%
rename from Examples/Sources/ContentCards-Custom-UI/Info.plist
rename to Examples/ObjC/Sources/ContentCards-Custom-UI/Info.plist
diff --git a/Examples/ObjC/Sources/ContentCards-Custom-UI/Readme.m b/Examples/ObjC/Sources/ContentCards-Custom-UI/Readme.m
new file mode 100644
index 0000000000..00380ffdc4
--- /dev/null
+++ b/Examples/ObjC/Sources/ContentCards-Custom-UI/Readme.m
@@ -0,0 +1,75 @@
+#import "AppDelegate.h"
+#import "ReadmeAction.h"
+#import "ReadmeViewController.h"
+
+#pragma mark - Internal
+
+void printCurrentContentCards(ReadmeViewController *viewController) {
+ [(AppDelegate *)
+ UIApplication.sharedApplication.delegate printCurrentContentCards];
+}
+
+void refreshContentCards(ReadmeViewController *viewController) {
+ [(AppDelegate *)UIApplication.sharedApplication.delegate refreshContentCards];
+}
+
+void subscribeToContentCardsUpdates(ReadmeViewController *viewController) {
+ [(AppDelegate *)UIApplication.sharedApplication
+ .delegate subscribeToContentCardsUpdates];
+}
+
+void cancelContentCardsUpdatesSubscription(
+ ReadmeViewController *viewController) {
+ [(AppDelegate *)UIApplication.sharedApplication
+ .delegate cancelContentCardsUpdatesSubscription];
+}
+
+void presentContentCardsInfoViewController(
+ ReadmeViewController *viewController) {
+ [(AppDelegate *)UIApplication.sharedApplication
+ .delegate presentContentCardsInfoViewController];
+}
+
+#pragma mark - Readme
+
+NSString *const readme = @"This sample demonstrates how to implement your own "
+ @"custom Content Cards UI:\n"
+ @"\n"
+ @"- AppDelegate.{h,m}:\n"
+ @" - Content cards API usage\n"
+ @" - Content cards custom UI presentation\n"
+ @"- CardsInfoViewController.{h,m}\n"
+ @" - UIViewController subclass presenting the "
+ @"content cards data in a table view";
+
+NSInteger const actionsCount = 5;
+
+ReadmeAction const actions[] = {
+ {@"Print current Content Cards", @"",
+ ^(ReadmeViewController *_Nonnull viewController){
+ printCurrentContentCards(viewController);
+}
+}
+, {@"Refresh Content Cards", @"",
+ ^(ReadmeViewController *_Nonnull viewController){
+ refreshContentCards(viewController);
+}
+}
+, {@"Subscribe to Content Cards updates", @"",
+ ^(ReadmeViewController *_Nonnull viewController){
+ subscribeToContentCardsUpdates(viewController);
+}
+}
+, {@"Cancel Content Cards updates subscription", @"",
+ ^(ReadmeViewController *_Nonnull viewController){
+ cancelContentCardsUpdatesSubscription(viewController);
+}
+}
+, {
+ @"Present Content Cards Info view controller", @"",
+ ^(ReadmeViewController *_Nonnull viewController) {
+ presentContentCardsInfoViewController(viewController);
+ }
+}
+}
+;
diff --git a/Examples/ObjC/Sources/ContentCards/AppDelegate.h b/Examples/ObjC/Sources/ContentCards/AppDelegate.h
new file mode 100644
index 0000000000..17572ed179
--- /dev/null
+++ b/Examples/ObjC/Sources/ContentCards/AppDelegate.h
@@ -0,0 +1,15 @@
+@import UIKit;
+@import BrazeKit;
+
+extern NSString *const brazeApiKey;
+extern NSString *const brazeEndpoint;
+
+@interface AppDelegate : UIResponder
+
+@property(class, strong, nonatomic) Braze *braze;
+
+- (void)pushContentCardsViewController;
+- (void)presentModalContentCardsViewController;
+- (void)presentModalContentCardsViewControllerCustomized;
+
+@end
diff --git a/Examples/ObjC/Sources/ContentCards/AppDelegate.m b/Examples/ObjC/Sources/ContentCards/AppDelegate.m
new file mode 100644
index 0000000000..7150637739
--- /dev/null
+++ b/Examples/ObjC/Sources/ContentCards/AppDelegate.m
@@ -0,0 +1,101 @@
+#import "AppDelegate.h"
+#import "BRZGIFViewProvider+SDWebImage.h"
+
+@import BrazeKit;
+@import BrazeUI;
+
+@interface AppDelegate ()
+@end
+
+@implementation AppDelegate
+
+#pragma mark - Lifecycle
+
+- (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ // Setup Braze
+ BRZConfiguration *configuration =
+ [[BRZConfiguration alloc] initWithApiKey:brazeApiKey
+ endpoint:brazeEndpoint];
+ configuration.logger.level = BRZLoggerLevelInfo;
+ Braze *braze = [[Braze alloc] initWithConfiguration:configuration];
+ AppDelegate.braze = braze;
+
+ // - GIF support
+ BRZGIFViewProvider.shared = [BRZGIFViewProvider sdWebImage];
+
+ [self.window makeKeyAndVisible];
+ return YES;
+}
+
+#pragma mark - AppDelegate.braze
+
+static Braze *_braze = nil;
+
++ (Braze *)braze {
+ return _braze;
+}
+
++ (void)setBraze:(Braze *)braze {
+ _braze = braze;
+}
+
+#pragma mark - Displaying Content Cards
+
+- (void)pushContentCardsViewController {
+ UINavigationController *navigationController =
+ (UINavigationController *)self.window.rootViewController;
+
+ // Create a content card view controller that can be pushed onto a navigation
+ // stack.
+ BRZContentCardUIViewController *viewController =
+ [[BRZContentCardUIViewController alloc] initWithBraze:AppDelegate.braze];
+ // Set the delegate
+ viewController.delegate = self;
+ // Push it onto the navigation stack
+ [navigationController pushViewController:viewController animated:YES];
+}
+
+- (void)presentModalContentCardsViewController {
+ UINavigationController *navigationController =
+ (UINavigationController *)self.window.rootViewController;
+
+ // Create a content card modal view controller that can be presented modally.
+ BRZContentCardUIModalViewController *modalViewController =
+ [[BRZContentCardUIModalViewController alloc]
+ initWithBraze:AppDelegate.braze];
+ // Set the delegate
+ modalViewController.viewController.delegate = self;
+ // Present modally
+ [navigationController presentViewController:modalViewController
+ animated:YES
+ completion:nil];
+}
+
+- (void)presentModalContentCardsViewControllerCustomized {
+ UIAlertController *alert = [UIAlertController
+ alertControllerWithTitle:@"Not Supported"
+ message:
+ @"Customization via attributes is not supported "
+ @"using the "
+ @"Objective-C API. See our Swift Examples project "
+ @"for details about customizing the Content Cards"
+ preferredStyle:UIAlertControllerStyleAlert];
+ [alert addAction:[UIAlertAction actionWithTitle:@"OK"
+ style:UIAlertActionStyleCancel
+ handler:nil]];
+ [self.window.rootViewController presentViewController:alert
+ animated:YES
+ completion:nil];
+}
+
+#pragma mark - Content Cards delegate
+
+- (BOOL)contentCardController:(BRZContentCardUIViewController *)controller
+ shouldProcess:(NSURL *)url
+ card:(BRZContentCardRaw *)card {
+ // Intercept the content card click action here
+ return YES;
+}
+
+@end
diff --git a/Examples/ObjC/Sources/ContentCards/BRZGIFViewProvider+SDWebImage.h b/Examples/ObjC/Sources/ContentCards/BRZGIFViewProvider+SDWebImage.h
new file mode 100644
index 0000000000..a0307bacf1
--- /dev/null
+++ b/Examples/ObjC/Sources/ContentCards/BRZGIFViewProvider+SDWebImage.h
@@ -0,0 +1,11 @@
+@import Foundation;
+@import BrazeUI;
+
+@interface BRZGIFViewProvider (SDWebImage)
+
+/// A GIF view provider using
+/// [SDWebImage](https://github.com/SDWebImage/SDWebImage) as a rendering
+/// library.
++ (BRZGIFViewProvider *)sdWebImage;
+
+@end
diff --git a/Examples/ObjC/Sources/ContentCards/BRZGIFViewProvider+SDWebImage.m b/Examples/ObjC/Sources/ContentCards/BRZGIFViewProvider+SDWebImage.m
new file mode 100644
index 0000000000..35b102a1c8
--- /dev/null
+++ b/Examples/ObjC/Sources/ContentCards/BRZGIFViewProvider+SDWebImage.m
@@ -0,0 +1,40 @@
+#import "BRZGIFViewProvider+SDWebImage.h"
+#import
+#import
+
+@interface BRZGIFViewProvider (SDWebImage)
+
++ (UIImage *)imageForURL:(NSURL *)url;
+
+@end
+
+@implementation BRZGIFViewProvider (SDWebImage)
+
++ (BRZGIFViewProvider *)sdWebImage {
+ return [BRZGIFViewProvider
+ providerWithView:^UIView *_Nonnull(NSURL *_Nullable url) {
+ UIImage *image = [BRZGIFViewProvider imageForURL:url];
+ SDAnimatedImageView *view =
+ [[SDAnimatedImageView alloc] initWithImage:image];
+ return view;
+ }
+ updateView:^(UIView *_Nonnull view, NSURL *_Nullable url) {
+ if ([view isKindOfClass:[SDAnimatedImageView class]]) {
+ ((SDAnimatedImageView *)(view)).image =
+ [BRZGIFViewProvider imageForURL:url];
+ }
+ }];
+}
+
++ (UIImage *)imageForURL:(NSURL *)url {
+ if (url == nil) {
+ return nil;
+ }
+ if ([url.pathExtension isEqualToString:@"gif"]) {
+ return [SDAnimatedImage imageWithContentsOfFile:url.path];
+ } else {
+ return [UIImage imageWithContentsOfFile:url.path];
+ }
+}
+
+@end
diff --git a/Examples/Sources/ContentCards/Info.plist b/Examples/ObjC/Sources/ContentCards/Info.plist
similarity index 100%
rename from Examples/Sources/ContentCards/Info.plist
rename to Examples/ObjC/Sources/ContentCards/Info.plist
diff --git a/Examples/ObjC/Sources/ContentCards/Readme.m b/Examples/ObjC/Sources/ContentCards/Readme.m
new file mode 100644
index 0000000000..80cdb1374e
--- /dev/null
+++ b/Examples/ObjC/Sources/ContentCards/Readme.m
@@ -0,0 +1,55 @@
+#import "AppDelegate.h"
+#import "ReadmeAction.h"
+#import "ReadmeViewController.h"
+
+#pragma mark - Internal
+
+void pushContentCardsViewController(ReadmeViewController *viewController) {
+ [(AppDelegate *)UIApplication.sharedApplication
+ .delegate pushContentCardsViewController];
+}
+
+void presentModalContentCardsViewController(
+ ReadmeViewController *viewController) {
+ [(AppDelegate *)UIApplication.sharedApplication
+ .delegate presentModalContentCardsViewController];
+}
+
+void presentModalContentCardsViewControllerCustomized(
+ ReadmeViewController *viewController) {
+ [(AppDelegate *)UIApplication.sharedApplication
+ .delegate presentModalContentCardsViewControllerCustomized];
+}
+
+#pragma mark - Readme
+
+NSString *const readme =
+ @"This sample presents how to use the Braze provided content cards UI:\n"
+ @"\n"
+ @"- AppDelegate.{h,m}:\n"
+ @" - Content cards UI presentation\n"
+ @" - Content cards UI delegate\n"
+ @"- BRZGIFViewProvider+SDWebImage.{h,m}\n"
+ @" - Use SDWebImage to provide GIF support to the Braze UI components";
+
+NSInteger const actionsCount = 3;
+
+ReadmeAction const actions[] = {
+ {@"Push content cards view controller", @"",
+ ^(ReadmeViewController *_Nonnull viewController){
+ pushContentCardsViewController(viewController);
+}
+}
+, {@"Present modal content cards view controller", @"",
+ ^(ReadmeViewController *_Nonnull viewController){
+ presentModalContentCardsViewController(viewController);
+}
+}
+, {
+ @"Present modal content cards view controller", @"(customized)",
+ ^(ReadmeViewController *_Nonnull viewController) {
+ presentModalContentCardsViewControllerCustomized(viewController);
+ }
+}
+}
+;
diff --git a/Examples/ObjC/Sources/InAppMessages-Custom-UI/AppDelegate.h b/Examples/ObjC/Sources/InAppMessages-Custom-UI/AppDelegate.h
new file mode 100644
index 0000000000..39f6d4eb6e
--- /dev/null
+++ b/Examples/ObjC/Sources/InAppMessages-Custom-UI/AppDelegate.h
@@ -0,0 +1,11 @@
+@import UIKit;
+@import BrazeKit;
+
+extern NSString *const brazeApiKey;
+extern NSString *const brazeEndpoint;
+
+@interface AppDelegate : UIResponder
+
+@property(class, strong, nonatomic) Braze *braze;
+
+@end
diff --git a/Examples/ObjC/Sources/InAppMessages-Custom-UI/AppDelegate.m b/Examples/ObjC/Sources/InAppMessages-Custom-UI/AppDelegate.m
new file mode 100644
index 0000000000..728d8efa13
--- /dev/null
+++ b/Examples/ObjC/Sources/InAppMessages-Custom-UI/AppDelegate.m
@@ -0,0 +1,43 @@
+#import "AppDelegate.h"
+#import "CustomInAppMessagePresenter.h"
+
+@import BrazeKit;
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+#pragma mark - Lifecycle
+
+- (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ // Setup Braze
+ BRZConfiguration *configuration =
+ [[BRZConfiguration alloc] initWithApiKey:brazeApiKey
+ endpoint:brazeEndpoint];
+ configuration.logger.level = BRZLoggerLevelInfo;
+ Braze *braze = [[Braze alloc] initWithConfiguration:configuration];
+ AppDelegate.braze = braze;
+
+ // Setup the custom In-App Message presenter
+ braze.inAppMessagePresenter = [[CustomInAppMessagePresenter alloc] init];
+
+ [self.window makeKeyAndVisible];
+ return YES;
+}
+
+#pragma mark - AppDelegate.braze
+
+static Braze *_braze = nil;
+
++ (Braze *)braze {
+ return _braze;
+}
+
++ (void)setBraze:(Braze *)braze {
+ _braze = braze;
+}
+
+@end
diff --git a/Examples/ObjC/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.h b/Examples/ObjC/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.h
new file mode 100644
index 0000000000..161c1f9b75
--- /dev/null
+++ b/Examples/ObjC/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.h
@@ -0,0 +1,6 @@
+@import Foundation;
+@import BrazeKit;
+
+@interface CustomInAppMessagePresenter : NSObject
+
+@end
diff --git a/Examples/ObjC/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.m b/Examples/ObjC/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.m
new file mode 100644
index 0000000000..e275add51b
--- /dev/null
+++ b/Examples/ObjC/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.m
@@ -0,0 +1,46 @@
+#import "CustomInAppMessagePresenter.h"
+#import "AppDelegate.h"
+#import "InAppMessageInfoViewController.h"
+
+@implementation CustomInAppMessagePresenter
+
+- (void)presentMessage:(BRZInAppMessageRaw *)message {
+
+ // BRZInAppMessageRaw is a compatibility representation of the In-App Message
+ // type.
+
+ // You can access the `extras` dictionary / `url`:
+
+ NSLog(@"extras: %@", message.extras);
+ NSLog(@"url: %@", message.url);
+
+ // You can access message specific values.
+ // - The value of `slideFrom` is irrelevant for non-slideup in-app messages.
+ // - The value of `header` is irrelevant for non-modal/non-full in-app
+ // messages.
+
+ NSLog(@"slideFrom: %@", @(message.slideFrom));
+ NSLog(@"header: %@", message.header);
+
+ // A wrapper / compatibility representation of the in-app message is
+ // accessible via `-json`
+ NSData *jsonData = [message json];
+ NSString *jsonString = [[NSString alloc] initWithData:jsonData
+ encoding:NSUTF8StringEncoding];
+ if (jsonString != nil) {
+ NSLog(@"%@", jsonString);
+ }
+
+ // Here, we present a custom view controller for the message
+
+ InAppMessageInfoViewController *viewController =
+ [[InAppMessageInfoViewController alloc] initWithMessage:message];
+ UINavigationController *navigationController = [[UINavigationController alloc]
+ initWithRootViewController:viewController];
+ [UIApplication.sharedApplication.delegate.window.rootViewController
+ presentViewController:navigationController
+ animated:YES
+ completion:nil];
+}
+
+@end
diff --git a/Examples/ObjC/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.h b/Examples/ObjC/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.h
new file mode 100644
index 0000000000..1e703f716d
--- /dev/null
+++ b/Examples/ObjC/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.h
@@ -0,0 +1,9 @@
+@import UIKit;
+
+@class BRZInAppMessageRaw;
+
+@interface InAppMessageInfoViewController : UITableViewController
+
+- (instancetype)initWithMessage:(BRZInAppMessageRaw *)message;
+
+@end
diff --git a/Examples/ObjC/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.m b/Examples/ObjC/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.m
new file mode 100644
index 0000000000..2561eab214
--- /dev/null
+++ b/Examples/ObjC/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.m
@@ -0,0 +1,282 @@
+#import "InAppMessageInfoViewController.h"
+
+@import UIKit;
+@import BrazeKit;
+
+#pragma mark - Field / Section
+
+@interface Field : NSObject
+
+@property(copy, nonatomic) NSString *name;
+@property(strong, nonatomic) id value;
+@property(assign, nonatomic) NSInteger indentation;
+
++ (instancetype)fieldWithName:(NSString *)name value:(id)value;
++ (instancetype)fieldWithName:(NSString *)name
+ value:(id)value
+ indentation:(NSInteger)indentation;
+
+@end
+
+@interface Section : NSObject
+
+@property(copy, nonatomic) NSString *name;
+@property(strong, nonatomic) NSArray *fields;
+
+@end
+
+#pragma mark - InAppMessageInfoViewController
+
+@interface InAppMessageInfoViewController ()
+
+@property(strong, nonatomic) NSArray *sections;
+
++ (NSArray *)messageSectionsFromMessage:
+ (BRZInAppMessageRaw *)message;
+
+@end
+
+@implementation InAppMessageInfoViewController
+
+- (instancetype)initWithMessage:(BRZInAppMessageRaw *)message {
+ self = [super initWithStyle:UITableViewStyleGrouped];
+ if (self) {
+ self.sections =
+ [InAppMessageInfoViewController messageSectionsFromMessage:message];
+
+ self.title = @"In-App Message Info";
+
+ UIBarButtonItem *doneButton = [[UIBarButtonItem alloc]
+ initWithBarButtonSystemItem:UIBarButtonSystemItemDone
+ target:self
+ action:@selector(dismissModal)];
+ [self.navigationItem setRightBarButtonItem:doneButton];
+
+ self.tableView.rowHeight = UITableViewAutomaticDimension;
+ self.tableView.estimatedRowHeight = 44.0;
+ }
+ return self;
+}
+
+- (void)dismissModal {
+ [self dismissViewControllerAnimated:YES completion:nil];
+}
+
+#pragma mark - UITableViewDataSource
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
+ return self.sections.count;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView
+ numberOfRowsInSection:(NSInteger)section {
+ return self.sections[section].fields.count;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView
+ cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+ UITableViewCell *cell =
+ [tableView dequeueReusableCellWithIdentifier:@"cellIdentifier"];
+ if (cell == nil) {
+ cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
+ reuseIdentifier:@"cellIdentifier"];
+ }
+
+ Field *field = self.sections[indexPath.section].fields[indexPath.row];
+ cell.textLabel.text = field.name;
+ cell.detailTextLabel.text = [NSString stringWithFormat:@"%@", field.value];
+ cell.indentationLevel = field.indentation;
+
+ cell.textLabel.numberOfLines = 0;
+ if (@available(iOS 13.0, tvOS 13.0, *)) {
+ cell.textLabel.font =
+ [UIFont monospacedSystemFontOfSize:13 weight:UIFontWeightRegular];
+ cell.detailTextLabel.font =
+ [UIFont monospacedSystemFontOfSize:13 weight:UIFontWeightRegular];
+ }
+
+ return cell;
+}
+
+#pragma mark - UITableViewDelegate
+
+- (NSString *)tableView:(UITableView *)tableView
+ titleForHeaderInSection:(NSInteger)section {
+ return self.sections[section].name;
+}
+
+#pragma mark - Helpers
+
++ (NSArray *)messageSectionsFromMessage:
+ (BRZInAppMessageRaw *)message {
+ NSMutableArray *fields = [NSMutableArray array];
+
+ switch (message.type) {
+ case BRZInAppMessageRawTypeSlideup:
+ [fields addObject:[Field fieldWithName:@"type" value:@"slideup"]];
+ break;
+ case BRZInAppMessageRawTypeModal:
+ [fields addObject:[Field fieldWithName:@"type" value:@"modal"]];
+ break;
+ case BRZInAppMessageRawTypeFull:
+ [fields addObject:[Field fieldWithName:@"type" value:@"full"]];
+ break;
+ case BRZInAppMessageRawTypeHtmlFull:
+ [fields addObject:[Field fieldWithName:@"type" value:@"htmlFull"]];
+ break;
+ case BRZInAppMessageRawTypeHtml:
+ [fields addObject:[Field fieldWithName:@"type" value:@"html"]];
+ break;
+ default:
+ break;
+ }
+
+ switch (message.clickAction) {
+ case BRZInAppMessageRawClickActionNone:
+ [fields addObject:[Field fieldWithName:@"clickAction" value:@"none"]];
+ break;
+ case BRZInAppMessageRawClickActionNewsFeed:
+ [fields addObject:[Field fieldWithName:@"clickAction" value:@"newsFeed"]];
+ break;
+ case BRZInAppMessageRawClickActionURL:
+ [fields addObject:[Field fieldWithName:@"clickAction" value:@"uri"]];
+ break;
+ default:
+ break;
+ }
+
+ [fields addObject:[Field fieldWithName:@"uri" value:message.url]];
+ [fields addObject:[Field fieldWithName:@"useWebView"
+ value:@(message.useWebView)]];
+
+ switch (message.messageClose) {
+ case BRZInAppMessageRawCloseSwipe:
+ [fields addObject:[Field fieldWithName:@"messageClose" value:@"swipe"]];
+ break;
+ case BRZInAppMessageRawCloseAutoDismiss:
+ [fields addObject:[Field fieldWithName:@"messageClose"
+ value:@"autoDismiss"]];
+ break;
+ default:
+ break;
+ }
+
+ switch (message.orientation) {
+ case BRZInAppMessageRawOrientationAny:
+ [fields addObject:[Field fieldWithName:@"orientation" value:@"any"]];
+ break;
+ case BRZInAppMessageRawOrientationPortrait:
+ [fields addObject:[Field fieldWithName:@"orientation" value:@"portrait"]];
+ break;
+ case BRZInAppMessageRawOrientationLandscape:
+ [fields addObject:[Field fieldWithName:@"orientation" value:@"landscape"]];
+ break;
+ default:
+ break;
+ }
+
+ [fields addObject:[Field fieldWithName:@"message" value:message.message]];
+ [fields addObject:[Field fieldWithName:@"header" value:message.header]];
+ [fields addObject:[Field fieldWithName:@"messageTextAlignment"
+ value:@(message.messageTextAlignment)]];
+ [fields addObject:[Field fieldWithName:@"headerTextAlignment"
+ value:@(message.headerTextAlignment)]];
+ [fields addObject:[Field fieldWithName:@"imageUri" value:message.imageURL]];
+ [fields addObject:[Field fieldWithName:@"icon" value:message.icon]];
+ [fields addObject:[Field fieldWithName:@"duration"
+ value:@(message.duration)]];
+ [fields addObject:[Field fieldWithName:@"themes" value:message.themes]];
+ [fields addObject:[Field fieldWithName:@"textColor"
+ value:message.textColor]];
+ [fields addObject:[Field fieldWithName:@"headerTextColor"
+ value:message.headerTextColor]];
+ [fields addObject:[Field fieldWithName:@"iconColor"
+ value:message.iconColor]];
+ [fields addObject:[Field fieldWithName:@"iconBackgroundColor"
+ value:message.iconBackgroundColor]];
+ [fields addObject:[Field fieldWithName:@"backgroundColor"
+ value:message.backgroundColor]];
+ [fields addObject:[Field fieldWithName:@"frameColor"
+ value:message.frameColor]];
+ [fields addObject:[Field fieldWithName:@"closeButtonColor"
+ value:message.closeButtonColor]];
+ [fields addObject:[Field fieldWithName:@"buttons" value:message.buttons]];
+
+ switch (message.imageStyle) {
+ case BRZInAppMessageRawImageStyleTop:
+ [fields addObject:[Field fieldWithName:@"imageStyle" value:@"top"]];
+ break;
+ case BRZInAppMessageRawImageStyleGraphic:
+ [fields addObject:[Field fieldWithName:@"imageStyle" value:@"graphic"]];
+ break;
+ default:
+ break;
+ }
+
+ switch (message.slideFrom) {
+ case BRZInAppMessageRawSlideFromTop:
+ [fields addObject:[Field fieldWithName:@"slideFrom" value:@"top"]];
+ break;
+ case BRZInAppMessageRawSlideFromBottom:
+ [fields addObject:[Field fieldWithName:@"slideFrom" value:@"bottom"]];
+ break;
+ default:
+ break;
+ }
+
+ [fields addObject:[Field fieldWithName:@"animateIn"
+ value:@(message.animateIn)]];
+ [fields addObject:[Field fieldWithName:@"animateOut"
+ value:@(message.animateOut)]];
+
+ NSData *extrasData = [NSJSONSerialization dataWithJSONObject:message.extras
+ options:0
+ error:nil];
+ NSString *extrasString = [[NSString alloc] initWithData:extrasData
+ encoding:NSUTF8StringEncoding];
+ [fields addObject:[Field fieldWithName:@"extras" value:@""]];
+ [fields addObject:[Field fieldWithName:extrasString value:@"" indentation:1]];
+
+ [fields addObject:[Field fieldWithName:@"baseURL" value:message.baseURL]];
+ [fields addObject:[Field fieldWithName:@"assetURLs" value:message.assetURLs]];
+ [fields addObject:[Field fieldWithName:@"isControl"
+ value:@(message.isControl)]];
+
+ Section *section = [[Section alloc] init];
+ section.name = @"message";
+ section.fields = [fields copy];
+
+ return @[ section ];
+}
+
+@end
+
+#pragma mark - Field / Section Implementation
+
+@implementation Field
+
+- (instancetype)initWithName:(NSString *)name value:(id)value {
+ self = [super init];
+ if (self) {
+ self.name = name;
+ self.value = value;
+ }
+ return self;
+}
+
++ (instancetype)fieldWithName:(NSString *)name value:(id)value {
+ return [[Field alloc] initWithName:name value:value];
+}
+
++ (instancetype)fieldWithName:(NSString *)name
+ value:(id)value
+ indentation:(NSInteger)indentation {
+ Field *field = [Field fieldWithName:name value:value];
+ field.indentation = indentation;
+ return field;
+}
+
+@end
+
+@implementation Section
+@end
diff --git a/Examples/Sources/InAppMessages-Custom-UI/Info.plist b/Examples/ObjC/Sources/InAppMessages-Custom-UI/Info.plist
similarity index 100%
rename from Examples/Sources/InAppMessages-Custom-UI/Info.plist
rename to Examples/ObjC/Sources/InAppMessages-Custom-UI/Info.plist
diff --git a/Examples/ObjC/Sources/InAppMessages-Custom-UI/Readme.m b/Examples/ObjC/Sources/InAppMessages-Custom-UI/Readme.m
new file mode 100644
index 0000000000..54f719e3a8
--- /dev/null
+++ b/Examples/ObjC/Sources/InAppMessages-Custom-UI/Readme.m
@@ -0,0 +1,61 @@
+#import "AppDelegate.h"
+#import "ReadmeAction.h"
+#import "ReadmeViewController.h"
+
+#pragma mark - Internal
+
+void localSlideup(ReadmeViewController *viewController) {
+ BRZInAppMessageRaw *slideup = [[BRZInAppMessageRaw alloc] init];
+ slideup.type = BRZInAppMessageRawTypeSlideup;
+ slideup.clickAction = BRZInAppMessageRawClickActionURL;
+ slideup.url = [NSURL URLWithString:@"https://example.com"];
+ slideup.useWebView = YES;
+ slideup.extras = @{@"key1" : @"value1", @"key2" : @"value2"};
+ slideup.icon = @"";
+ slideup.message = @"Local slideup in-app message";
+
+ [AppDelegate.braze.inAppMessagePresenter presentMessage:slideup];
+}
+
+void localModal(ReadmeViewController *viewController) {
+ BRZInAppMessageRaw *modal = [[BRZInAppMessageRaw alloc] init];
+ modal.type = BRZInAppMessageRawTypeModal;
+ modal.clickAction = BRZInAppMessageRawClickActionURL;
+ modal.url = [NSURL URLWithString:@"https://example.com"];
+ modal.useWebView = YES;
+ modal.extras = @{@"key1" : @"value1", @"key2" : @"value2"};
+ modal.icon = @"";
+ modal.header = @"Header text";
+ modal.message = @"Local modal in-app message";
+
+ [AppDelegate.braze.inAppMessagePresenter presentMessage:modal];
+}
+
+#pragma mark - Readme
+
+NSString *const readme =
+ @"This sample presents how to implement your own custom In-App Message "
+ @"UI:\n"
+ @"\n"
+ @"- AppDelegate.{h,m}:\n"
+ @" - Sets the custom in-app message presenter\n"
+ @"- CustomInAppMessagePresenter.{h,m}\n"
+ @" - Explains how to use the `BRZInAppMessageRaw` data model and present "
+ @"the message in a custom view controller.";
+
+NSInteger const actionsCount = 2;
+
+ReadmeAction const actions[] = {
+ {@"Present local slideup in-app message", @"",
+ ^(ReadmeViewController *_Nonnull viewController){
+ localSlideup(viewController);
+}
+}
+, {
+ @"Present local modal in-app message", @"",
+ ^(ReadmeViewController *_Nonnull viewController) {
+ localModal(viewController);
+ }
+}
+}
+;
diff --git a/Examples/ObjC/Sources/InAppMessages/AppDelegate.h b/Examples/ObjC/Sources/InAppMessages/AppDelegate.h
new file mode 100644
index 0000000000..39f6d4eb6e
--- /dev/null
+++ b/Examples/ObjC/Sources/InAppMessages/AppDelegate.h
@@ -0,0 +1,11 @@
+@import UIKit;
+@import BrazeKit;
+
+extern NSString *const brazeApiKey;
+extern NSString *const brazeEndpoint;
+
+@interface AppDelegate : UIResponder
+
+@property(class, strong, nonatomic) Braze *braze;
+
+@end
diff --git a/Examples/ObjC/Sources/InAppMessages/AppDelegate.m b/Examples/ObjC/Sources/InAppMessages/AppDelegate.m
new file mode 100644
index 0000000000..be5198de67
--- /dev/null
+++ b/Examples/ObjC/Sources/InAppMessages/AppDelegate.m
@@ -0,0 +1,67 @@
+#import "AppDelegate.h"
+#import "BRZGIFViewProvider+SDWebImage.h"
+
+@import BrazeKit;
+@import BrazeUI;
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+#pragma mark - Lifecycle
+
+- (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ // Setup Braze
+ BRZConfiguration *configuration =
+ [[BRZConfiguration alloc] initWithApiKey:brazeApiKey
+ endpoint:brazeEndpoint];
+ configuration.logger.level = BRZLoggerLevelInfo;
+ Braze *braze = [[Braze alloc] initWithConfiguration:configuration];
+ AppDelegate.braze = braze;
+
+ // - GIF support
+ BRZGIFViewProvider.shared = [BRZGIFViewProvider sdWebImage];
+
+ // - InAppMessageUI
+ BrazeInAppMessageUI *inAppMessageUI = [[BrazeInAppMessageUI alloc] init];
+ inAppMessageUI.delegate = self;
+ braze.inAppMessagePresenter = inAppMessageUI;
+
+ [self.window makeKeyAndVisible];
+ return YES;
+}
+
+#pragma mark - AppDelegate.braze
+
+static Braze *_braze = nil;
+
++ (Braze *)braze {
+ return _braze;
+}
+
++ (void)setBraze:(Braze *)braze {
+ _braze = braze;
+}
+
+#pragma mark - BrazeInAppMessageUIDelegate
+
+- (BOOL)inAppMessage:(BrazeInAppMessageUI *)ui
+ shouldProcess:(enum BRZInAppMessageRawClickAction)clickAction
+ url:(NSURL *)uri
+ buttonId:(NSString *)buttonId
+ message:(BRZInAppMessageRaw *)message
+ view:(UIView *)view {
+ // Intercept the in-app message click action here
+ return YES;
+}
+
+- (void)inAppMessage:(BrazeInAppMessageUI *)ui
+ didPresent:(BRZInAppMessageRaw *)message
+ view:(UIView *)view {
+ // Executed when `message` is presented to the user
+}
+
+@end
diff --git a/Examples/ObjC/Sources/InAppMessages/BRZGIFViewProvider+SDWebImage.h b/Examples/ObjC/Sources/InAppMessages/BRZGIFViewProvider+SDWebImage.h
new file mode 100644
index 0000000000..a0307bacf1
--- /dev/null
+++ b/Examples/ObjC/Sources/InAppMessages/BRZGIFViewProvider+SDWebImage.h
@@ -0,0 +1,11 @@
+@import Foundation;
+@import BrazeUI;
+
+@interface BRZGIFViewProvider (SDWebImage)
+
+/// A GIF view provider using
+/// [SDWebImage](https://github.com/SDWebImage/SDWebImage) as a rendering
+/// library.
++ (BRZGIFViewProvider *)sdWebImage;
+
+@end
diff --git a/Examples/ObjC/Sources/InAppMessages/BRZGIFViewProvider+SDWebImage.m b/Examples/ObjC/Sources/InAppMessages/BRZGIFViewProvider+SDWebImage.m
new file mode 100644
index 0000000000..35b102a1c8
--- /dev/null
+++ b/Examples/ObjC/Sources/InAppMessages/BRZGIFViewProvider+SDWebImage.m
@@ -0,0 +1,40 @@
+#import "BRZGIFViewProvider+SDWebImage.h"
+#import
+#import
+
+@interface BRZGIFViewProvider (SDWebImage)
+
++ (UIImage *)imageForURL:(NSURL *)url;
+
+@end
+
+@implementation BRZGIFViewProvider (SDWebImage)
+
++ (BRZGIFViewProvider *)sdWebImage {
+ return [BRZGIFViewProvider
+ providerWithView:^UIView *_Nonnull(NSURL *_Nullable url) {
+ UIImage *image = [BRZGIFViewProvider imageForURL:url];
+ SDAnimatedImageView *view =
+ [[SDAnimatedImageView alloc] initWithImage:image];
+ return view;
+ }
+ updateView:^(UIView *_Nonnull view, NSURL *_Nullable url) {
+ if ([view isKindOfClass:[SDAnimatedImageView class]]) {
+ ((SDAnimatedImageView *)(view)).image =
+ [BRZGIFViewProvider imageForURL:url];
+ }
+ }];
+}
+
++ (UIImage *)imageForURL:(NSURL *)url {
+ if (url == nil) {
+ return nil;
+ }
+ if ([url.pathExtension isEqualToString:@"gif"]) {
+ return [SDAnimatedImage imageWithContentsOfFile:url.path];
+ } else {
+ return [UIImage imageWithContentsOfFile:url.path];
+ }
+}
+
+@end
diff --git a/Examples/Sources/InAppMessages/Info.plist b/Examples/ObjC/Sources/InAppMessages/Info.plist
similarity index 100%
rename from Examples/Sources/InAppMessages/Info.plist
rename to Examples/ObjC/Sources/InAppMessages/Info.plist
diff --git a/Examples/ObjC/Sources/InAppMessages/Readme.m b/Examples/ObjC/Sources/InAppMessages/Readme.m
new file mode 100644
index 0000000000..b46bb891cd
--- /dev/null
+++ b/Examples/ObjC/Sources/InAppMessages/Readme.m
@@ -0,0 +1,52 @@
+#import "AppDelegate.h"
+#import "ReadmeAction.h"
+#import "ReadmeViewController.h"
+
+@import BrazeKit;
+
+#pragma mark - Internal
+
+void localSlideup(ReadmeViewController *viewController) {
+ BRZInAppMessageRaw *slideup = [[BRZInAppMessageRaw alloc] init];
+ slideup.type = BRZInAppMessageRawTypeSlideup;
+ slideup.icon = @"";
+ slideup.message = @"Local slideup in-app message";
+ [AppDelegate.braze.inAppMessagePresenter presentMessage:slideup];
+}
+
+void localModal(ReadmeViewController *viewController) {
+ BRZInAppMessageRaw *modal = [[BRZInAppMessageRaw alloc] init];
+ modal.type = BRZInAppMessageRawTypeModal;
+ modal.icon = @"";
+ modal.header = @"Header text";
+ modal.message = @"Local modal in-app message";
+ [AppDelegate.braze.inAppMessagePresenter presentMessage:modal];
+}
+
+#pragma mark - Readme
+
+NSString *const readme =
+ @"This sample presents how to use the Braze provided in-app message UI:\n"
+ @"\n"
+ @"- AppDelegate.{h,m}\n"
+ @" - In-app message UI configuration\n"
+ @" - In-app message UI delegate\n"
+ @"- BRZGIFViewProvider+SDWebImage.{h,m}\n"
+ @" - Use SDWebImage to provide GIF support to the Braze UI components";
+
+NSInteger const actionsCount = 2;
+
+ReadmeAction const actions[] = {
+ {@"Present local slideup in-app message", @"",
+ ^(ReadmeViewController *_Nonnull viewController){
+ localSlideup(viewController);
+}
+}
+, {@"Present local modal in-app message", @"",
+ ^(ReadmeViewController *_Nonnull viewController){
+ localModal(viewController);
+}
+}
+,
+}
+;
diff --git a/Examples/ObjC/Sources/Location/AppDelegate.h b/Examples/ObjC/Sources/Location/AppDelegate.h
new file mode 100644
index 0000000000..39f6d4eb6e
--- /dev/null
+++ b/Examples/ObjC/Sources/Location/AppDelegate.h
@@ -0,0 +1,11 @@
+@import UIKit;
+@import BrazeKit;
+
+extern NSString *const brazeApiKey;
+extern NSString *const brazeEndpoint;
+
+@interface AppDelegate : UIResponder
+
+@property(class, strong, nonatomic) Braze *braze;
+
+@end
diff --git a/Examples/ObjC/Sources/Location/AppDelegate.m b/Examples/ObjC/Sources/Location/AppDelegate.m
new file mode 100644
index 0000000000..4a120b09ab
--- /dev/null
+++ b/Examples/ObjC/Sources/Location/AppDelegate.m
@@ -0,0 +1,40 @@
+#import "AppDelegate.h"
+
+@import BrazeKit;
+@import BrazeLocation;
+
+@implementation AppDelegate
+
+#pragma mark - Lifecycle
+
+- (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ // Setup Braze
+ BRZConfiguration *configuration =
+ [[BRZConfiguration alloc] initWithApiKey:brazeApiKey
+ endpoint:brazeEndpoint];
+ configuration.logger.level = BRZLoggerLevelInfo;
+ configuration.location.brazeLocation = [[BrazeLocation alloc] init];
+ configuration.location.automaticLocationCollection = YES;
+ configuration.location.geofencesEnabled = YES;
+ configuration.location.automaticGeofenceRequests = YES;
+ Braze *braze = [[Braze alloc] initWithConfiguration:configuration];
+ AppDelegate.braze = braze;
+
+ [self.window makeKeyAndVisible];
+ return YES;
+}
+
+#pragma mark - AppDelegate.braze
+
+static Braze *_braze = nil;
+
++ (Braze *)braze {
+ return _braze;
+}
+
++ (void)setBraze:(Braze *)braze {
+ _braze = braze;
+}
+
+@end
diff --git a/Examples/Sources/Location/Info.plist b/Examples/ObjC/Sources/Location/Info.plist
similarity index 100%
rename from Examples/Sources/Location/Info.plist
rename to Examples/ObjC/Sources/Location/Info.plist
diff --git a/Examples/ObjC/Sources/Location/Readme.m b/Examples/ObjC/Sources/Location/Readme.m
new file mode 100644
index 0000000000..2297f4e5bf
--- /dev/null
+++ b/Examples/ObjC/Sources/Location/Readme.m
@@ -0,0 +1,69 @@
+#import "ReadmeAction.h"
+
+@import CoreLocation;
+
+#pragma mark - Internal
+
+static CLLocationManager *_locationManager;
+
+CLLocationManager *locationManager(void) {
+ if (!_locationManager) {
+ _locationManager = [[CLLocationManager alloc] init];
+ }
+ return _locationManager;
+}
+
+#if TARGET_OS_IOS
+
+void requestAlwaysAuthorization(ReadmeViewController *viewController) {
+ [locationManager() requestAlwaysAuthorization];
+}
+
+#endif
+
+void requestWhenInUseAuthorization(ReadmeViewController *viewController) {
+ [locationManager() requestWhenInUseAuthorization];
+}
+
+#pragma mark - Readme
+
+NSString *const readme =
+ @"This sample presents a complete BrazeLocation integration.\n"
+ @"\n"
+ @"- AppDelegate.{h,m}:\n"
+ @" - Configure the braze instance with BrazeLocation";
+
+#if TARGET_OS_IOS
+
+NSInteger const actionsCount = 2;
+
+ReadmeAction const actions[] = {
+ {@"Request \"always\" authorization", @"",
+ ^(ReadmeViewController *_Nonnull viewController){
+ requestAlwaysAuthorization(viewController);
+}
+}
+, {@"Request \"when in use\" authorization", @"",
+ ^(ReadmeViewController *_Nonnull viewController){
+ requestWhenInUseAuthorization(viewController);
+}
+}
+,
+}
+;
+
+#elif TARGET_OS_TV
+
+NSInteger const actionsCount = 1;
+
+ReadmeAction const actions[] = {
+ {@"Request \"when in use\" authorization", @"",
+ ^(ReadmeViewController *_Nonnull viewController){
+ requestWhenInUseAuthorization(viewController);
+}
+}
+,
+}
+;
+
+#endif
diff --git a/Examples/ObjC/Sources/PushNotifications/AppDelegate.h b/Examples/ObjC/Sources/PushNotifications/AppDelegate.h
new file mode 100644
index 0000000000..c0ccacfda5
--- /dev/null
+++ b/Examples/ObjC/Sources/PushNotifications/AppDelegate.h
@@ -0,0 +1,13 @@
+@import UIKit;
+@import UserNotifications;
+@import BrazeKit;
+
+extern NSString *const brazeApiKey;
+extern NSString *const brazeEndpoint;
+
+@interface AppDelegate
+ : UIResponder
+
+@property(class, strong, nonatomic) Braze *braze;
+
+@end
diff --git a/Examples/ObjC/Sources/PushNotifications/AppDelegate.m b/Examples/ObjC/Sources/PushNotifications/AppDelegate.m
new file mode 100644
index 0000000000..9d4c769b82
--- /dev/null
+++ b/Examples/ObjC/Sources/PushNotifications/AppDelegate.m
@@ -0,0 +1,114 @@
+#import "AppDelegate.h"
+
+@import BrazeKit;
+
+@implementation AppDelegate
+
+#pragma mark - Lifecycle
+
+- (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ // Setup Braze
+ BRZConfiguration *configuration =
+ [[BRZConfiguration alloc] initWithApiKey:brazeApiKey
+ endpoint:brazeEndpoint];
+ configuration.logger.level = BRZLoggerLevelInfo;
+ configuration.push.appGroup =
+ @"group.com.braze.PushNotifications.PushStories";
+ Braze *braze = [[Braze alloc] initWithConfiguration:configuration];
+ AppDelegate.braze = braze;
+
+ // Push notifications support
+ [application registerForRemoteNotifications];
+ UNUserNotificationCenter *center =
+ UNUserNotificationCenter.currentNotificationCenter;
+ [center setNotificationCategories:BRZNotifications.categories];
+ center.delegate = self;
+ UNAuthorizationOptions options = UNAuthorizationOptionBadge |
+ UNAuthorizationOptionSound |
+ UNAuthorizationOptionAlert;
+ [center requestAuthorizationWithOptions:options
+ completionHandler:^(BOOL granted,
+ NSError *_Nullable error) {
+ NSLog(@"Notification authorization, granted: %d, "
+ @"error: %@)",
+ granted, error);
+ }];
+
+ [self.window makeKeyAndVisible];
+ return YES;
+}
+
+#pragma mark - AppDelegate.braze
+
+static Braze *_braze = nil;
+
++ (Braze *)braze {
+ return _braze;
+}
+
++ (void)setBraze:(Braze *)braze {
+ _braze = braze;
+}
+
+#pragma mark - Push Notification support
+
+// - Register the device token with Braze
+
+- (void)application:(UIApplication *)application
+ didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
+ [AppDelegate.braze.notifications registerDeviceToken:deviceToken];
+}
+
+// - Add support for silent notification
+
+- (void)application:(UIApplication *)application
+ didReceiveRemoteNotification:(NSDictionary *)userInfo
+ fetchCompletionHandler:
+ (void (^)(UIBackgroundFetchResult))completionHandler {
+ BOOL processedByBraze =
+ AppDelegate.braze != nil &&
+ [AppDelegate.braze.notifications
+ handleBackgroundNotificationWithUserInfo:userInfo
+ fetchCompletionHandler:completionHandler];
+ if (processedByBraze) {
+ return;
+ }
+
+ completionHandler(UIBackgroundFetchResultNoData);
+}
+
+// - Add support for push notifications
+
+- (void)userNotificationCenter:(UNUserNotificationCenter *)center
+ didReceiveNotificationResponse:(UNNotificationResponse *)response
+ withCompletionHandler:(void (^)(void))completionHandler {
+ BOOL processedByBraze =
+ AppDelegate.braze != nil &&
+ [AppDelegate.braze.notifications
+ handleUserNotificationWithResponse:response
+ withCompletionHandler:completionHandler];
+ if (processedByBraze) {
+ return;
+ }
+
+ completionHandler();
+}
+
+// - Add support for displaying push notification when the app is currently
+// running in the
+// foreground
+
+- (void)userNotificationCenter:(UNUserNotificationCenter *)center
+ willPresentNotification:(UNNotification *)notification
+ withCompletionHandler:
+ (void (^)(UNNotificationPresentationOptions))completionHandler {
+ if (@available(iOS 14, *)) {
+ completionHandler(UNNotificationPresentationOptionList |
+ UNNotificationPresentationOptionBanner);
+ } else {
+ completionHandler(UNNotificationPresentationOptionAlert);
+ }
+}
+
+@end
diff --git a/Examples/Sources/PushNotifications/Info.plist b/Examples/ObjC/Sources/PushNotifications/Info.plist
similarity index 100%
rename from Examples/Sources/PushNotifications/Info.plist
rename to Examples/ObjC/Sources/PushNotifications/Info.plist
diff --git a/Examples/Sources/PushNotifications/PushNotifications.entitlements b/Examples/ObjC/Sources/PushNotifications/PushNotifications.entitlements
similarity index 100%
rename from Examples/Sources/PushNotifications/PushNotifications.entitlements
rename to Examples/ObjC/Sources/PushNotifications/PushNotifications.entitlements
diff --git a/Examples/ObjC/Sources/PushNotifications/Readme.m b/Examples/ObjC/Sources/PushNotifications/Readme.m
new file mode 100644
index 0000000000..9add716005
--- /dev/null
+++ b/Examples/ObjC/Sources/PushNotifications/Readme.m
@@ -0,0 +1,23 @@
+#import "ReadmeAction.h"
+
+#pragma mark - Readme
+
+NSString *const readme =
+ @"This sample presents a complete push notification integration "
+ @"supporting:\n"
+ @"\n"
+ @"- PushNotifications/AppDelegate.{h,m}:\n"
+ @" - Silent push notifications\n"
+ @" - Foreground push notifications\n"
+ @" - Action buttons\n"
+ @" - Display push notifications when app is already open\n"
+ @"\n"
+ @"- PushNotificationsServiceExtension:\n"
+ @" - Rich push notification support (image, GIF, audio, video)\n"
+ @"\n"
+ @"- PushNotificationsContentExtension:\n"
+ @" - Braze Push Story implementation";
+
+NSInteger const actionsCount = 0;
+
+ReadmeAction const actions[] = {};
diff --git a/Examples/Sources/PushNotificationsContentExtension/Info.plist b/Examples/ObjC/Sources/PushNotificationsContentExtension/Info.plist
similarity index 100%
rename from Examples/Sources/PushNotificationsContentExtension/Info.plist
rename to Examples/ObjC/Sources/PushNotificationsContentExtension/Info.plist
diff --git a/Examples/Sources/PushNotificationsContentExtension/NotificationViewController.swift b/Examples/ObjC/Sources/PushNotificationsContentExtension/NotificationViewController.swift
similarity index 100%
rename from Examples/Sources/PushNotificationsContentExtension/NotificationViewController.swift
rename to Examples/ObjC/Sources/PushNotificationsContentExtension/NotificationViewController.swift
diff --git a/Examples/Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements b/Examples/ObjC/Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements
similarity index 100%
rename from Examples/Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements
rename to Examples/ObjC/Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements
diff --git a/Examples/Sources/PushNotificationsServiceExtension/Info.plist b/Examples/ObjC/Sources/PushNotificationsServiceExtension/Info.plist
similarity index 100%
rename from Examples/Sources/PushNotificationsServiceExtension/Info.plist
rename to Examples/ObjC/Sources/PushNotificationsServiceExtension/Info.plist
diff --git a/Examples/Sources/PushNotificationsServiceExtension/NotificationService.swift b/Examples/ObjC/Sources/PushNotificationsServiceExtension/NotificationService.swift
similarity index 100%
rename from Examples/Sources/PushNotificationsServiceExtension/NotificationService.swift
rename to Examples/ObjC/Sources/PushNotificationsServiceExtension/NotificationService.swift
diff --git a/Examples/README.md b/Examples/README.md
index cf0166a39a..b37a657fc6 100644
--- a/Examples/README.md
+++ b/Examples/README.md
@@ -7,10 +7,12 @@ Follow the instructions below for your preferred package manager to get started.
#### Swift Package Manager
+- Navigates to the `Swift` or `ObjC` directory
- Open `Examples-SwiftPM.xcodeproj`
#### CocoaPods
+- Navigates to the `Swift` or `ObjC` directory
- Run `pod install`
- Open `Examples-CocoaPods.xcworkspace`
@@ -19,40 +21,47 @@ Follow the instructions below for your preferred package manager to get started.
#### Analytics
- iOS, tvOS.
+- Swift, Objective-C.
- Demonstrates how to use the analytics features of the SDK.
- Related tutorial: [Analytics](https://braze-inc.github.io/braze-swift-sdk/tutorials/braze/a3-analytics).
#### ContentCards
- iOS only.
+- Swift, Objective-C.
- Demonstrates how to use the Braze provided Content Cards UI.
- Related tutorial: [Content Cards UI](https://braze-inc.github.io/braze-swift-sdk/tutorials/braze/c2-contentcardsui).
#### ContentCards-Custom-UI
- iOS, tvOS.
+- Swift, Objective-C.
- Demonstrates how to implement your own custom Content Cards UI.
#### InAppMessages
- iOS only.
+- Swift, Objective-C.
- Demonstrates how to use the Braze provided In-App Message UI.
- Related tutorial: [In-App Messages](https://braze-inc.github.io/braze-swift-sdk/tutorials/braze/c1-inappmessageui).
#### InAppMessages-Custom-UI
- iOS, tvOS.
+- Swift, Objective-C.
- Demonstrates how to implement your own custom In-App Message UI.
#### Location
- iOS, tvOS.
+- Swift, Objective-C.
- Presents a complete BrazeLocation integration which enables location tracking and geofence monitoring.
- Related tutorial: [Location and Geofences](https://braze-inc.github.io/braze-swift-sdk/tutorials/braze/d1-brazelocation).
#### PushNotifications
-- iOS, tvOS.
+- iOS only.
+- Swift, Objective-C.
- Presents a complete push notification integration supporting:
- Silent push notifications.
- Foreground push notifications.
@@ -70,11 +79,13 @@ Follow the instructions below for your preferred package manager to get started.
#### PushNotificationsContentExtension
- iOS only.
+- Swift only.
- Braze Push Story implementation.
- Related tutorial: [Push Stories](https://braze-inc.github.io/braze-swift-sdk/tutorials/braze/b3-push-stories).
#### PushNotificationsServiceExtension
- iOS only.
+- Swift only.
- Rich push notification support (image, GIF, audio, video).
- Related tutorial: [Rich Push Notifications](https://braze-inc.github.io/braze-swift-sdk/tutorials/braze/b2-rich-push-notifications).
diff --git a/Examples/Examples-CocoaPods.xcodeproj/project.pbxproj b/Examples/Swift/Examples-CocoaPods.xcodeproj/project.pbxproj
similarity index 99%
rename from Examples/Examples-CocoaPods.xcodeproj/project.pbxproj
rename to Examples/Swift/Examples-CocoaPods.xcodeproj/project.pbxproj
index 3c5e524da8..a505e13a7f 100644
--- a/Examples/Examples-CocoaPods.xcodeproj/project.pbxproj
+++ b/Examples/Swift/Examples-CocoaPods.xcodeproj/project.pbxproj
@@ -1214,7 +1214,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
@@ -1222,7 +1222,7 @@
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
- TVOS_DEPLOYMENT_TARGET = 10.0;
+ TVOS_DEPLOYMENT_TARGET = 11.0;
};
name = Debug;
};
@@ -1421,14 +1421,14 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
- TVOS_DEPLOYMENT_TARGET = 10.0;
+ TVOS_DEPLOYMENT_TARGET = 11.0;
};
name = Release;
};
diff --git a/Examples/Swift/Examples-CocoaPods.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/Swift/Examples-CocoaPods.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000000..919434a625
--- /dev/null
+++ b/Examples/Swift/Examples-CocoaPods.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/Examples/Examples-SwiftPM.xcodeproj/project.pbxproj b/Examples/Swift/Examples-SwiftPM.xcodeproj/project.pbxproj
similarity index 99%
rename from Examples/Examples-SwiftPM.xcodeproj/project.pbxproj
rename to Examples/Swift/Examples-SwiftPM.xcodeproj/project.pbxproj
index 18957ac62d..33a5d8e831 100644
--- a/Examples/Examples-SwiftPM.xcodeproj/project.pbxproj
+++ b/Examples/Swift/Examples-SwiftPM.xcodeproj/project.pbxproj
@@ -156,7 +156,7 @@
16F703E30F0CDB139F4DBC8E /* ContentCards-Custom-UI.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "ContentCards-Custom-UI.app"; sourceTree = BUILT_PRODUCTS_DIR; };
1D680CBC8E96C58FD5F8BA5D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
1F8AD06FAD6F81E92F64DD72 /* CardsInfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardsInfoViewController.swift; sourceTree = ""; };
- 220432BEC0EA7628608EA5BA /* braze-swift-sdk */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "braze-swift-sdk"; path = ..; sourceTree = SOURCE_ROOT; };
+ 220432BEC0EA7628608EA5BA /* braze-swift-sdk */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "braze-swift-sdk"; path = ../..; sourceTree = SOURCE_ROOT; };
34BD000896FB64DC78BBF177 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
4AC100D3BC83C040C950594D /* SDWebImageGIFViewProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDWebImageGIFViewProvider.swift; sourceTree = ""; };
4B0A55E8282ADE8756715B6A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
@@ -1231,7 +1231,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
@@ -1239,7 +1239,7 @@
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
- TVOS_DEPLOYMENT_TARGET = 10.0;
+ TVOS_DEPLOYMENT_TARGET = 11.0;
};
name = Debug;
};
@@ -1322,14 +1322,14 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
- TVOS_DEPLOYMENT_TARGET = 10.0;
+ TVOS_DEPLOYMENT_TARGET = 11.0;
};
name = Release;
};
diff --git a/Examples/Swift/Examples-SwiftPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/Swift/Examples-SwiftPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000000..919434a625
--- /dev/null
+++ b/Examples/Swift/Examples-SwiftPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/Examples/Swift/Package.swift b/Examples/Swift/Package.swift
new file mode 100644
index 0000000000..e92d15f7f9
--- /dev/null
+++ b/Examples/Swift/Package.swift
@@ -0,0 +1,3 @@
+// This Package.swift is intentionally empty. It exists for the sole purpose of preventing Xcode
+// from recursively including the Examples project sources when locally referencing the Braze SDK
+// SwiftPM package.
diff --git a/Examples/Swift/Podfile b/Examples/Swift/Podfile
new file mode 100644
index 0000000000..66dd814301
--- /dev/null
+++ b/Examples/Swift/Podfile
@@ -0,0 +1,78 @@
+source 'https://cdn.cocoapods.org/'
+
+project 'Examples-CocoaPods'
+
+target 'Analytics-iOS' do
+ platform :ios, '10.0'
+ pod 'BrazeKit'
+end
+
+target 'Analytics-tvOS' do
+ platform :tvos, '10.0'
+ pod 'BrazeKit'
+end
+
+target 'InAppMessages' do
+ platform :ios, '11.0'
+ pod 'BrazeKit'
+ pod 'BrazeUI'
+ # SDWebImage is optional. BrazeUI requires a third party library to display GIF images.
+ # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations
+ pod 'SDWebImage', :modular_headers => true
+end
+
+target 'InAppMessages-Custom-UI-iOS' do
+ platform :ios, '10.0'
+ pod 'BrazeKit'
+end
+
+target 'InAppMessages-Custom-UI-tvOS' do
+ platform :tvos, '10.0'
+ pod 'BrazeKit'
+end
+
+target 'ContentCards' do
+ platform :ios, '11.0'
+ pod 'BrazeKit'
+ pod 'BrazeUI'
+ # SDWebImage is optional. BrazeUI requires a third party library to display GIF images.
+ # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations
+ pod 'SDWebImage', :modular_headers => true
+end
+
+target 'ContentCards-Custom-UI-iOS' do
+ platform :ios, '10.0'
+ pod 'BrazeKit'
+end
+
+target 'ContentCards-Custom-UI-tvOS' do
+ platform :tvos, '10.0'
+ pod 'BrazeKit'
+end
+
+target 'Location-iOS' do
+ platform :ios, '10.0'
+ pod 'BrazeKit'
+ pod 'BrazeLocation'
+end
+
+target 'Location-tvOS' do
+ platform :tvos, '10.0'
+ pod 'BrazeKit'
+ pod 'BrazeLocation'
+end
+
+target 'PushNotifications' do
+ platform :ios, '10.0'
+ pod 'BrazeKit'
+end
+
+target 'PushNotificationsServiceExtension' do
+ platform :ios, '10.0'
+ pod 'BrazeNotificationService'
+end
+
+target 'PushNotificationsContentExtension' do
+ platform :ios, '10.0'
+ pod 'BrazePushStory'
+end
diff --git a/Examples/Sources/Analytics/AppDelegate.swift b/Examples/Swift/Sources/Analytics/AppDelegate.swift
similarity index 89%
rename from Examples/Sources/Analytics/AppDelegate.swift
rename to Examples/Swift/Sources/Analytics/AppDelegate.swift
index 7558036354..f3103b2412 100644
--- a/Examples/Sources/Analytics/AppDelegate.swift
+++ b/Examples/Swift/Sources/Analytics/AppDelegate.swift
@@ -13,7 +13,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Setup Braze
- var configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint)
+ let configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint)
configuration.logger.level = .info
let braze = Braze(configuration: configuration)
AppDelegate.braze = braze
diff --git a/Examples/Sources/Analytics/AuthenticationManager.swift b/Examples/Swift/Sources/Analytics/AuthenticationManager.swift
similarity index 100%
rename from Examples/Sources/Analytics/AuthenticationManager.swift
rename to Examples/Swift/Sources/Analytics/AuthenticationManager.swift
diff --git a/Examples/Sources/Analytics/CheckoutViewController.swift b/Examples/Swift/Sources/Analytics/CheckoutViewController.swift
similarity index 100%
rename from Examples/Sources/Analytics/CheckoutViewController.swift
rename to Examples/Swift/Sources/Analytics/CheckoutViewController.swift
diff --git a/Examples/Sources/ContentCards-In-House-UI/Info.plist b/Examples/Swift/Sources/Analytics/Info.plist
similarity index 94%
rename from Examples/Sources/ContentCards-In-House-UI/Info.plist
rename to Examples/Swift/Sources/Analytics/Info.plist
index e8c26c902a..6f095d6800 100644
--- a/Examples/Sources/ContentCards-In-House-UI/Info.plist
+++ b/Examples/Swift/Sources/Analytics/Info.plist
@@ -5,7 +5,7 @@
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
CFBundleDisplayName
- ContentCards-In-House-UI
+ Analytics
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
diff --git a/Examples/Sources/Analytics/Readme.swift b/Examples/Swift/Sources/Analytics/Readme.swift
similarity index 100%
rename from Examples/Sources/Analytics/Readme.swift
rename to Examples/Swift/Sources/Analytics/Readme.swift
diff --git a/Examples/Swift/Sources/Common/Assets.xcassets/AccentColor.colorset/Contents.json b/Examples/Swift/Sources/Common/Assets.xcassets/AccentColor.colorset/Contents.json
new file mode 100644
index 0000000000..eb87897008
--- /dev/null
+++ b/Examples/Swift/Sources/Common/Assets.xcassets/AccentColor.colorset/Contents.json
@@ -0,0 +1,11 @@
+{
+ "colors" : [
+ {
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Examples/Swift/Sources/Common/Assets.xcassets/AppIcon.appiconset/Contents.json b/Examples/Swift/Sources/Common/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000000..9221b9bb1a
--- /dev/null
+++ b/Examples/Swift/Sources/Common/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,98 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "60x60"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "60x60"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "76x76"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "76x76"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "83.5x83.5"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "scale" : "1x",
+ "size" : "1024x1024"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Examples/Swift/Sources/Common/Assets.xcassets/Contents.json b/Examples/Swift/Sources/Common/Assets.xcassets/Contents.json
new file mode 100644
index 0000000000..73c00596a7
--- /dev/null
+++ b/Examples/Swift/Sources/Common/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Examples/Sources/Common/Credentials.swift b/Examples/Swift/Sources/Common/Credentials.swift
similarity index 100%
rename from Examples/Sources/Common/Credentials.swift
rename to Examples/Swift/Sources/Common/Credentials.swift
diff --git a/Examples/Sources/Common/ReadmeViewController.swift b/Examples/Swift/Sources/Common/ReadmeViewController.swift
similarity index 98%
rename from Examples/Sources/Common/ReadmeViewController.swift
rename to Examples/Swift/Sources/Common/ReadmeViewController.swift
index 0ab4fffdaa..ed05508d53 100644
--- a/Examples/Sources/Common/ReadmeViewController.swift
+++ b/Examples/Swift/Sources/Common/ReadmeViewController.swift
@@ -57,7 +57,7 @@ final class ReadmeViewController: UITableViewController {
super.viewWillLayoutSubviews()
let size = readmeTextView.systemLayoutSizeFitting(
- .init(width: tableView.bounds.width, height: 0))
+ .init(width: tableView.bounds.width, height: 1000))
if readmeTextView.frame.height != size.height {
readmeTextView.frame.size.height = size.height
}
diff --git a/Examples/Swift/Sources/Common/iOS/Base.lproj/LaunchScreen.storyboard b/Examples/Swift/Sources/Common/iOS/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 0000000000..865e9329f3
--- /dev/null
+++ b/Examples/Swift/Sources/Common/iOS/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Examples/Swift/Sources/Common/tvOS/Base.lproj/LaunchScreen.storyboard b/Examples/Swift/Sources/Common/tvOS/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 0000000000..660ba53de4
--- /dev/null
+++ b/Examples/Swift/Sources/Common/tvOS/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Examples/Sources/ContentCards-Custom-UI/AppDelegate.swift b/Examples/Swift/Sources/ContentCards-Custom-UI/AppDelegate.swift
similarity index 57%
rename from Examples/Sources/ContentCards-Custom-UI/AppDelegate.swift
rename to Examples/Swift/Sources/ContentCards-Custom-UI/AppDelegate.swift
index dc1852cdf7..8d48125650 100644
--- a/Examples/Sources/ContentCards-Custom-UI/AppDelegate.swift
+++ b/Examples/Swift/Sources/ContentCards-Custom-UI/AppDelegate.swift
@@ -14,7 +14,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Setup Braze
- var configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint)
+ let configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint)
configuration.logger.level = .info
let braze = Braze(configuration: configuration)
AppDelegate.braze = braze
@@ -27,7 +27,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func printCurrentContentCards() {
// Print all the cards
- print(AppDelegate.braze?.contentCards ?? [])
+ print(AppDelegate.braze?.contentCards.cards ?? [])
guard let card = AppDelegate.braze?.contentCards.cards.first else { return }
@@ -35,16 +35,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// the Braze platform.
//
// All `Braze.ContentCard` have a `.data` property that contains common fields.
- // For instance, you can retrieve the `extras` dictionary / `uri` on all content cards:
+ // For instance, you can retrieve the `extras` dictionary / `url` on all content cards:
print("extras:", card.data.extras)
- print("uri:", card.data.clickAction?.uri ?? "none")
+ print("url:", card.data.clickAction?.url ?? "none")
// All `.data` properties are directly accessible on the card itself.
- // For instance, you can access the `extras` dictionary / `uri` omitting the `.data` key path:
+ // For instance, you can access the `extras` dictionary / `url` omitting the `.data` key path:
print("extras:", card.extras)
- print("uri:", card.clickAction?.uri ?? "none")
+ print("url:", card.clickAction?.url ?? "none")
// To access card specific fields, you can switch on the `card` enum:
switch card {
@@ -66,6 +66,60 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
if let image = card.banner?.image {
print("banner - image:", image)
}
+
+ // A wrapper / compatibility representation of the card is accessible via `.json()`
+ if let jsonData = card.json(),
+ let jsonString = String(data: jsonData, encoding: .utf8) {
+ print(jsonString)
+ }
+
+ // A card can always be transformed into a `Braze.ContentCardRaw`, a compatibility
+ // representation of the Content Card type.
+ let cardRaw = Braze.ContentCardRaw(card)
+ print("extras:", cardRaw.extras)
+ print("url:", cardRaw.url ?? "none")
+ }
+
+ func printCurrentContentCardsRaw() {
+ // Convert to `Braze.ContentCardRaw`
+ let rawCards = AppDelegate.braze?.contentCards.cards.map {
+ Braze.ContentCardRaw($0)
+ }
+
+ // Print all the cards
+ print(rawCards ?? [])
+
+ guard let cardRaw = rawCards?.first else { return }
+
+ // Braze.ContentCardRaw is an Objective-C compatible NSObject subclass representing the
+ // content card object, it matches the platform representation of the Content Card.
+ //
+ // All fields are directly accessible on the raw card object.
+
+ print("extras:", cardRaw.extras)
+ print("url:", cardRaw.url ?? "none")
+
+ if let title = cardRaw.title {
+ print("title:", title)
+ }
+
+ if let image = cardRaw.image {
+ print("image:", image)
+ }
+
+ // A wrapper / compatibility representation of the card is accessible via `.json()`
+ if let jsonData = cardRaw.json(),
+ let jsonString = String(data: jsonData, encoding: .utf8) {
+ print(jsonString)
+ }
+
+ // A raw card can be transformed into a `Braze.ContentCard`, the type-safe representation of the
+ // content card object.
+ guard let card = try? Braze.ContentCard(cardRaw) else {
+ return
+ }
+ print("extras:", card.extras)
+ print("url:", card.clickAction?.url ?? "none")
}
func refreshContentCards() {
diff --git a/Examples/Sources/ContentCards-Custom-UI/CardsInfoViewController.swift b/Examples/Swift/Sources/ContentCards-Custom-UI/CardsInfoViewController.swift
similarity index 93%
rename from Examples/Sources/ContentCards-Custom-UI/CardsInfoViewController.swift
rename to Examples/Swift/Sources/ContentCards-Custom-UI/CardsInfoViewController.swift
index e24752581c..64c7141933 100644
--- a/Examples/Sources/ContentCards-Custom-UI/CardsInfoViewController.swift
+++ b/Examples/Swift/Sources/ContentCards-Custom-UI/CardsInfoViewController.swift
@@ -1,5 +1,5 @@
-import BrazeKit
import UIKit
+import BrazeKit
final class CardsInfoViewController: UITableViewController {
@@ -26,8 +26,7 @@ final class CardsInfoViewController: UITableViewController {
sections = cards.enumerated().map { Self.cardSection(from: $1, index: $0) }
super.init(style: .grouped)
title = "Content Cards Info"
- let doneButton = UIBarButtonItem(
- barButtonSystemItem: .done, target: self, action: #selector(dismissModal))
+ let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissModal))
navigationItem.setRightBarButton(doneButton, animated: false)
tableView.rowHeight = UITableView.automaticDimension
@@ -63,8 +62,7 @@ final class CardsInfoViewController: UITableViewController {
_ tableView: UITableView,
cellForRowAt indexPath: IndexPath
) -> UITableViewCell {
- let cell =
- tableView.dequeueReusableCell(withIdentifier: "cellIdentifier")
+ let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier")
?? UITableViewCell(style: .value1, reuseIdentifier: "cellIdentifier")
let field = sections[indexPath.section].fields[indexPath.row]
@@ -162,11 +160,11 @@ final class CardsInfoViewController: UITableViewController {
switch clickAction {
case .none:
header.value = "none"
- case .uri(let uri, let useWebView):
- header.value = "uri"
+ case .url(let url, let useWebView):
+ header.value = "url"
fields = [
- Field(name: "uri", value: uri, indentation: indentation + 1),
- Field(name: "useWebView", value: useWebView, indentation: indentation + 1),
+ Field(name: "url", value: url, indentation: indentation + 1),
+ Field(name: "useWebView", value: useWebView, indentation: indentation + 1)
]
@unknown default:
break
@@ -175,4 +173,5 @@ final class CardsInfoViewController: UITableViewController {
return [header] + fields
}
+
}
diff --git a/Examples/Sources/InAppMessages-In-House-UI/Info.plist b/Examples/Swift/Sources/ContentCards-Custom-UI/Info.plist
similarity index 94%
rename from Examples/Sources/InAppMessages-In-House-UI/Info.plist
rename to Examples/Swift/Sources/ContentCards-Custom-UI/Info.plist
index 59751b10e0..cf7a1812cd 100644
--- a/Examples/Sources/InAppMessages-In-House-UI/Info.plist
+++ b/Examples/Swift/Sources/ContentCards-Custom-UI/Info.plist
@@ -5,7 +5,7 @@
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
CFBundleDisplayName
- InAppMessages-In-House-UI
+ ContentCards-Custom-UI
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
diff --git a/Examples/Sources/ContentCards-Custom-UI/Readme.swift b/Examples/Swift/Sources/ContentCards-Custom-UI/Readme.swift
similarity index 83%
rename from Examples/Sources/ContentCards-Custom-UI/Readme.swift
rename to Examples/Swift/Sources/ContentCards-Custom-UI/Readme.swift
index 7f7e179471..57aa7bd0b4 100644
--- a/Examples/Sources/ContentCards-Custom-UI/Readme.swift
+++ b/Examples/Swift/Sources/ContentCards-Custom-UI/Readme.swift
@@ -3,7 +3,7 @@ import UIKit
let readme =
"""
- This sample demonstrates how to implement your own custom Content Cards UI:
+ This sample presents how to implement your own custom Content Cards UI:
- AppDelegate.swift:
- Content cards API usage
@@ -18,6 +18,11 @@ let actions: [(String, String, (ReadmeViewController) -> Void)] = [
"",
printCurrentContentCards
),
+ (
+ "Print current Content Cards Raw",
+ "",
+ printCurrentContentCardsRaw
+ ),
(
"Refresh Content Cards",
"",
@@ -46,6 +51,10 @@ func printCurrentContentCards(_ viewController: ReadmeViewController) {
(UIApplication.shared.delegate as? AppDelegate)?.printCurrentContentCards()
}
+func printCurrentContentCardsRaw(_ viewController: ReadmeViewController) {
+ (UIApplication.shared.delegate as? AppDelegate)?.printCurrentContentCardsRaw()
+}
+
func refreshContentCards(_ viewController: ReadmeViewController) {
(UIApplication.shared.delegate as? AppDelegate)?.refreshContentCards()
}
@@ -61,3 +70,4 @@ func cancelContentCardsUpdatesSubscription(_ viewController: ReadmeViewControlle
func presentContentCardsInfoViewController(_ viewController: ReadmeViewController) {
(UIApplication.shared.delegate as? AppDelegate)?.presentContentCardsInfoViewController()
}
+
diff --git a/Examples/Sources/ContentCards/AppDelegate.swift b/Examples/Swift/Sources/ContentCards/AppDelegate.swift
similarity index 96%
rename from Examples/Sources/ContentCards/AppDelegate.swift
rename to Examples/Swift/Sources/ContentCards/AppDelegate.swift
index d087a1295d..c236943dc6 100644
--- a/Examples/Sources/ContentCards/AppDelegate.swift
+++ b/Examples/Swift/Sources/ContentCards/AppDelegate.swift
@@ -12,13 +12,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Setup Braze
- var configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint)
+ let configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint)
configuration.logger.level = .info
let braze = Braze(configuration: configuration)
AppDelegate.braze = braze
// - GIF support
- BrazeUI.gifViewProvider = .sdWebImage
+ GIFViewProvider.shared = .sdWebImage
window?.makeKeyAndVisible()
return true
diff --git a/Examples/Swift/Sources/ContentCards/Info.plist b/Examples/Swift/Sources/ContentCards/Info.plist
new file mode 100644
index 0000000000..0c015f1468
--- /dev/null
+++ b/Examples/Swift/Sources/ContentCards/Info.plist
@@ -0,0 +1,26 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ ContentCards
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ UILaunchStoryboardName
+ LaunchScreen
+
+
diff --git a/Examples/Sources/ContentCards/Readme.swift b/Examples/Swift/Sources/ContentCards/Readme.swift
similarity index 100%
rename from Examples/Sources/ContentCards/Readme.swift
rename to Examples/Swift/Sources/ContentCards/Readme.swift
diff --git a/Examples/Sources/ContentCards/SDWebImageGIFViewProvider.swift b/Examples/Swift/Sources/ContentCards/SDWebImageGIFViewProvider.swift
similarity index 100%
rename from Examples/Sources/ContentCards/SDWebImageGIFViewProvider.swift
rename to Examples/Swift/Sources/ContentCards/SDWebImageGIFViewProvider.swift
diff --git a/Examples/Sources/InAppMessages-Custom-UI/AppDelegate.swift b/Examples/Swift/Sources/InAppMessages-Custom-UI/AppDelegate.swift
similarity index 83%
rename from Examples/Sources/InAppMessages-Custom-UI/AppDelegate.swift
rename to Examples/Swift/Sources/InAppMessages-Custom-UI/AppDelegate.swift
index abefe07cda..adca669512 100644
--- a/Examples/Sources/InAppMessages-Custom-UI/AppDelegate.swift
+++ b/Examples/Swift/Sources/InAppMessages-Custom-UI/AppDelegate.swift
@@ -11,12 +11,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Setup Braze
- var configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint)
+ let configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint)
configuration.logger.level = .info
let braze = Braze(configuration: configuration)
AppDelegate.braze = braze
- // Setup our custom In-App Message presenter.
+ // Setup the custom In-App Message presenter.
braze.inAppMessagePresenter = CustomInAppMessagePresenter()
window?.makeKeyAndVisible()
diff --git a/Examples/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.swift b/Examples/Swift/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.swift
similarity index 69%
rename from Examples/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.swift
rename to Examples/Swift/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.swift
index 10cf970b28..e7c05282cd 100644
--- a/Examples/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.swift
+++ b/Examples/Swift/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.swift
@@ -9,16 +9,16 @@ struct CustomInAppMessagePresenter: BrazeInAppMessagePresenter {
// by the Braze platform.
//
// All `Braze.InAppMessage` have a `.data` property that contains common fields.
- // For instance, you can retrieve the `extras` dictionary / `uri` on all in-app messages:
+ // For instance, you can retrieve the `extras` dictionary / `url` on all in-app messages:
print("extras:", message.data.extras)
- print("uri:", message.data.clickAction.uri ?? "none")
+ print("url:", message.data.clickAction.url ?? "none")
// All `.data` properties are directly accessible on the message itself.
- // For instance, you can access the `extras` dictionary / `uri` omitting the `.data` key path:
+ // For instance, you can access the `extras` dictionary / `url` omitting the `.data` key path:
print("extras:", message.extras)
- print("uri:", message.clickAction.uri ?? "none")
+ print("url:", message.clickAction.url ?? "none")
// To access message specific fields, you can switch on the `message` enum:
switch message {
@@ -41,6 +41,18 @@ struct CustomInAppMessagePresenter: BrazeInAppMessagePresenter {
print("full - header:", header)
}
+ // A wrapper / compatibility representation of the in-app message is accessible via `.json()`
+ if let jsonData = message.json(),
+ let jsonString = String(data: jsonData, encoding: .utf8) {
+ print(jsonString)
+ }
+
+ // An message can always be transformed into a `Braze.InAppMessageRaw`, a compatibility
+ // representation of the In-App Message type.
+ let messageRaw = Braze.InAppMessageRaw(message)
+ print("extras:", messageRaw.extras)
+ print("url:", messageRaw.url ?? "none")
+
// Here, we present a custom view controller for the message
let controller = InAppMessageInfoViewController(message: message)
diff --git a/Examples/Sources/InAppMessages-Custom-UI/Extensions.swift b/Examples/Swift/Sources/InAppMessages-Custom-UI/Extensions.swift
similarity index 89%
rename from Examples/Sources/InAppMessages-Custom-UI/Extensions.swift
rename to Examples/Swift/Sources/InAppMessages-Custom-UI/Extensions.swift
index 2d9c717aa2..38e3755223 100644
--- a/Examples/Sources/InAppMessages-Custom-UI/Extensions.swift
+++ b/Examples/Swift/Sources/InAppMessages-Custom-UI/Extensions.swift
@@ -1,5 +1,5 @@
-import BrazeKit
import Foundation
+import BrazeKit
// MARK: - Braze
@@ -27,8 +27,7 @@ extension Encodable {
}
guard let data = try? encoder.encode(self),
- let prettyPrinted = String(data: data, encoding: .utf8)
- else {
+ let prettyPrinted = String(data: data, encoding: .utf8) else {
return "\(self)"
}
@@ -49,8 +48,7 @@ extension Dictionary where Key == String, Value == Any {
}
guard let data = try? JSONSerialization.data(withJSONObject: self, options: options),
- let prettyPrinted = String(data: data, encoding: .utf8)
- else {
+ let prettyPrinted = String(data: data, encoding: .utf8) else {
return "\(self)"
}
diff --git a/Examples/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.swift b/Examples/Swift/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.swift
similarity index 80%
rename from Examples/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.swift
rename to Examples/Swift/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.swift
index 391c7dca10..70f26c68cb 100644
--- a/Examples/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.swift
+++ b/Examples/Swift/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.swift
@@ -1,5 +1,5 @@
-import BrazeKit
import UIKit
+import BrazeKit
final class InAppMessageInfoViewController: UITableViewController {
@@ -26,8 +26,7 @@ final class InAppMessageInfoViewController: UITableViewController {
sections = Self.messageSections(from: message) + Self.dataSections(from: message)
super.init(style: .grouped)
title = "In-App Message Info"
- let doneButton = UIBarButtonItem(
- barButtonSystemItem: .done, target: self, action: #selector(dismissModal))
+ let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissModal))
navigationItem.setRightBarButton(doneButton, animated: false)
tableView.rowHeight = UITableView.automaticDimension
@@ -63,8 +62,7 @@ final class InAppMessageInfoViewController: UITableViewController {
_ tableView: UITableView,
cellForRowAt indexPath: IndexPath
) -> UITableViewCell {
- let cell =
- tableView.dequeueReusableCell(withIdentifier: "cellIdentifier")
+ let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier")
?? UITableViewCell(style: .value1, reuseIdentifier: "cellIdentifier")
let field = sections[indexPath.section].fields[indexPath.row]
@@ -99,38 +97,33 @@ final class InAppMessageInfoViewController: UITableViewController {
var themesSection: Section?
switch message {
case .slideup(let slideup):
- section.fields =
- [
- Field(name: "type", value: "slideup"),
- Field(name: "message", value: slideup.message, indentation: 1),
- Field(name: "slideFrom", value: slideup.slideFrom.rawValue, indentation: 1),
- ] + fields(from: slideup.graphic, indentation: 1)
+ section.fields = [
+ Field(name: "type", value: "slideup"),
+ Field(name: "message", value: slideup.message, indentation: 1),
+ Field(name: "slideFrom", value: slideup.slideFrom.rawValue, indentation: 1)
+ ] + fields(from: slideup.graphic, indentation: 1)
themesSection = self.themesSection(from: slideup.themes)
case .modal(let modal):
- section.fields =
- [
- Field(name: "type", value: "modal"),
- Field(name: "header", value: modal.header, indentation: 1),
- Field(name: "message", value: modal.message, indentation: 1),
- Field(
- name: "headerTextAlignment", value: modal.headerTextAlignment.rawValue, indentation: 1),
- Field(
- name: "messageTextAlignment", value: modal.messageTextAlignment.rawValue, indentation: 1
- ),
- ] + fields(from: modal.graphic, indentation: 1)
+ section.fields = [
+ Field(name: "type", value: "modal"),
+ Field(name: "header", value: modal.header, indentation: 1),
+ Field(name: "message", value: modal.message, indentation: 1),
+ Field(name: "headerTextAlignment", value: modal.headerTextAlignment.rawValue, indentation: 1),
+ Field(name: "messageTextAlignment", value: modal.messageTextAlignment.rawValue, indentation: 1),
+ ] + fields(from: modal.graphic, indentation: 1)
buttonsSection = self.buttonsSection(from: modal.buttons)
themesSection = self.themesSection(from: modal.themes)
case .modalImage(let modalImage):
section.fields = [
Field(name: "type", value: "modalImage"),
- Field(name: "imageUri", value: modalImage.imageUri, indentation: 1),
+ Field(name: "imageURL", value: modalImage.imageURL, indentation: 1),
]
buttonsSection = self.buttonsSection(from: modalImage.buttons)
themesSection = self.themesSection(from: modalImage.themes)
case .full(let full):
section.fields = [
Field(name: "type", value: "full"),
- Field(name: "imageUri", value: full.imageUri, indentation: 1),
+ Field(name: "imageURL", value: full.imageURL, indentation: 1),
Field(name: "header", value: full.header, indentation: 1),
Field(name: "message", value: full.message, indentation: 1),
Field(name: "headerTextAlignment", value: full.headerTextAlignment, indentation: 1),
@@ -141,7 +134,7 @@ final class InAppMessageInfoViewController: UITableViewController {
case .fullImage(let fullImage):
section.fields = [
Field(name: "type", value: "fullImage"),
- Field(name: "imageUri", value: fullImage.imageUri, indentation: 1),
+ Field(name: "imageURL", value: fullImage.imageURL, indentation: 1),
]
buttonsSection = self.buttonsSection(from: fullImage.buttons)
themesSection = self.themesSection(from: fullImage.themes)
@@ -150,10 +143,10 @@ final class InAppMessageInfoViewController: UITableViewController {
Field(name: "type", value: "html"),
Field(name: "message", value: "", indentation: 1),
Field(name: html.message, value: "", indentation: 2),
- Field(name: "baseUrl", value: "", indentation: 1),
- Field(name: html.baseUrl?.absoluteString ?? "none", value: "", indentation: 2),
- Field(name: "assetUrls", value: "", indentation: 1),
- Field(name: html.assetUrls.prettyPrint(), value: "", indentation: 2),
+ Field(name: "baseURL", value: "", indentation: 1),
+ Field(name: html.baseURL?.absoluteString ?? "none", value: "", indentation: 2),
+ Field(name: "assetURLs", value: "", indentation: 1),
+ Field(name: html.assetURLs.prettyPrint(), value: "", indentation: 2),
Field(name: "legacy", value: html.legacy, indentation: 1),
]
case .control:
@@ -177,8 +170,7 @@ final class InAppMessageInfoViewController: UITableViewController {
Field(name: "headerTextColor", value: theme.headerTextColor.hexString, indentation: 1),
Field(name: "closeButtonColor", value: theme.closeButtonColor.hexString, indentation: 1),
Field(name: "iconColor", value: theme.iconColor.hexString, indentation: 1),
- Field(
- name: "iconBackgroundColor", value: theme.iconBackgroundColor.hexString, indentation: 1),
+ Field(name: "iconBackgroundColor", value: theme.iconBackgroundColor.hexString, indentation: 1),
Field(name: "backgroundColor", value: theme.backgroundColor.hexString, indentation: 1),
Field(name: "frameColor", value: theme.frameColor.hexString, indentation: 1),
]
@@ -226,7 +218,7 @@ final class InAppMessageInfoViewController: UITableViewController {
// Extras
section.fields += [
Field(name: "extras", value: ""),
- Field(name: message.extras.prettyPrint(), value: "", indentation: 1),
+ Field(name: message.extras.prettyPrint(), value: "", indentation: 1)
]
return [section]
@@ -246,11 +238,11 @@ final class InAppMessageInfoViewController: UITableViewController {
header.value = "none"
case .newsFeed:
header.value = "newsFeed"
- case .uri(let uri, let useWebView):
- header.value = "uri"
+ case .url(let url, useWebView: let useWebView):
+ header.value = "url"
fields = [
- Field(name: "uri", value: uri, indentation: indentation + 1),
- Field(name: "useWebView", value: useWebView, indentation: indentation + 1),
+ Field(name: "url", value: url, indentation: indentation + 1),
+ Field(name: "useWebView", value: useWebView, indentation: indentation + 1)
]
@unknown default:
break
@@ -295,9 +287,7 @@ final class InAppMessageInfoViewController: UITableViewController {
case .icon(let icon):
header.value = "icon"
fields = [
- Field(
- name: "icon (FontAwesome, may not render correctly here)", value: icon,
- indentation: indentation + 1)
+ Field(name: "icon (FontAwesome, may not render correctly here)", value: icon, indentation: indentation + 1)
]
case .image(let url):
header.value = "image"
@@ -319,11 +309,8 @@ final class InAppMessageInfoViewController: UITableViewController {
fields += [
Field(name: "theme", value: name, indentation: indentation),
Field(name: "textColor", value: theme.textColor.hexString, indentation: indentation + 1),
- Field(
- name: "backgroundColor", value: theme.backgroundColor.hexString,
- indentation: indentation + 1),
- Field(
- name: "borderColor", value: theme.borderColor.hexString, indentation: indentation + 1),
+ Field(name: "backgroundColor", value: theme.backgroundColor.hexString, indentation: indentation + 1),
+ Field(name: "borderColor", value: theme.borderColor.hexString, indentation: indentation + 1),
]
}
@@ -331,3 +318,4 @@ final class InAppMessageInfoViewController: UITableViewController {
}
}
+
diff --git a/Examples/Swift/Sources/InAppMessages-Custom-UI/Info.plist b/Examples/Swift/Sources/InAppMessages-Custom-UI/Info.plist
new file mode 100644
index 0000000000..486c46727c
--- /dev/null
+++ b/Examples/Swift/Sources/InAppMessages-Custom-UI/Info.plist
@@ -0,0 +1,26 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ InAppMessages-Custom-UI
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ UILaunchStoryboardName
+ LaunchScreen
+
+
diff --git a/Examples/Sources/InAppMessages-Custom-UI/Readme.swift b/Examples/Swift/Sources/InAppMessages-Custom-UI/Readme.swift
similarity index 86%
rename from Examples/Sources/InAppMessages-Custom-UI/Readme.swift
rename to Examples/Swift/Sources/InAppMessages-Custom-UI/Readme.swift
index d7f4286bfb..072046cf11 100644
--- a/Examples/Sources/InAppMessages-Custom-UI/Readme.swift
+++ b/Examples/Swift/Sources/InAppMessages-Custom-UI/Readme.swift
@@ -3,7 +3,7 @@ import UIKit
let readme =
"""
- This sample demonstrates how to implement your own custom In-App Message UI:
+ This sample presents how to implement your own custom In-App Message UI:
- AppDelegate.swift:
- Sets the custom in-app message presenter
@@ -30,7 +30,7 @@ func localSlideup(_ viewController: ReadmeViewController) {
let slideup: Braze.InAppMessage = .slideup(
.init(
data: .init(
- clickAction: .uri(URL(string: "https://example.com")!, useWebView: true),
+ clickAction: .url(URL(string: "https://example.com")!, useWebView: true),
extras: ["key1": "value1", "key2": "value2"]
),
graphic: .icon(""),
@@ -44,7 +44,7 @@ func localModal(_ viewController: ReadmeViewController) {
let modal: Braze.InAppMessage = .modal(
.init(
data: .init(
- clickAction: .uri(URL(string: "https://example.com")!, useWebView: true),
+ clickAction: .url(URL(string: "https://example.com")!, useWebView: true),
extras: ["key1": "value1", "key2": "value2"]
),
graphic: .icon(""),
diff --git a/Examples/Sources/InAppMessages/AppDelegate.swift b/Examples/Swift/Sources/InAppMessages/AppDelegate.swift
similarity index 93%
rename from Examples/Sources/InAppMessages/AppDelegate.swift
rename to Examples/Swift/Sources/InAppMessages/AppDelegate.swift
index d9a9484866..368d66c9c7 100644
--- a/Examples/Sources/InAppMessages/AppDelegate.swift
+++ b/Examples/Swift/Sources/InAppMessages/AppDelegate.swift
@@ -12,13 +12,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Setup Braze
- var configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint)
+ let configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint)
configuration.logger.level = .info
let braze = Braze(configuration: configuration)
AppDelegate.braze = braze
// - GIF support
- BrazeUI.gifViewProvider = .sdWebImage
+ GIFViewProvider.shared = .sdWebImage
// - InAppMessage UI
let inAppMessageUI = BrazeInAppMessageUI()
diff --git a/Examples/Swift/Sources/InAppMessages/Info.plist b/Examples/Swift/Sources/InAppMessages/Info.plist
new file mode 100644
index 0000000000..4f97542122
--- /dev/null
+++ b/Examples/Swift/Sources/InAppMessages/Info.plist
@@ -0,0 +1,26 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ InAppMessages
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ UILaunchStoryboardName
+ LaunchScreen
+
+
diff --git a/Examples/Sources/InAppMessages/Readme.swift b/Examples/Swift/Sources/InAppMessages/Readme.swift
similarity index 100%
rename from Examples/Sources/InAppMessages/Readme.swift
rename to Examples/Swift/Sources/InAppMessages/Readme.swift
diff --git a/Examples/Sources/InAppMessages/SDWebImageGIFViewProvider.swift b/Examples/Swift/Sources/InAppMessages/SDWebImageGIFViewProvider.swift
similarity index 100%
rename from Examples/Sources/InAppMessages/SDWebImageGIFViewProvider.swift
rename to Examples/Swift/Sources/InAppMessages/SDWebImageGIFViewProvider.swift
diff --git a/Examples/Sources/Location/AppDelegate.swift b/Examples/Swift/Sources/Location/AppDelegate.swift
similarity index 92%
rename from Examples/Sources/Location/AppDelegate.swift
rename to Examples/Swift/Sources/Location/AppDelegate.swift
index 9f8cb6e23c..a18615cc1c 100644
--- a/Examples/Sources/Location/AppDelegate.swift
+++ b/Examples/Swift/Sources/Location/AppDelegate.swift
@@ -14,7 +14,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Setup Braze
- var configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint)
+ let configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint)
configuration.logger.level = .info
configuration.location.brazeLocation = BrazeLocation()
configuration.location.automaticLocationCollection = true
diff --git a/Examples/Swift/Sources/Location/Info.plist b/Examples/Swift/Sources/Location/Info.plist
new file mode 100644
index 0000000000..71c36b3686
--- /dev/null
+++ b/Examples/Swift/Sources/Location/Info.plist
@@ -0,0 +1,30 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ Location
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ NSLocationAlwaysAndWhenInUseUsageDescription
+ Location Authorization - Always / When in Use
+ NSLocationWhenInUseUsageDescription
+ Location Authorization - When in Use
+ UILaunchStoryboardName
+ LaunchScreen
+
+
diff --git a/Examples/Sources/Location/Readme.swift b/Examples/Swift/Sources/Location/Readme.swift
similarity index 100%
rename from Examples/Sources/Location/Readme.swift
rename to Examples/Swift/Sources/Location/Readme.swift
diff --git a/Examples/Sources/PushNotifications/AppDelegate.swift b/Examples/Swift/Sources/PushNotifications/AppDelegate.swift
similarity index 97%
rename from Examples/Sources/PushNotifications/AppDelegate.swift
rename to Examples/Swift/Sources/PushNotifications/AppDelegate.swift
index 5db5f5a267..8c703d2799 100644
--- a/Examples/Sources/PushNotifications/AppDelegate.swift
+++ b/Examples/Swift/Sources/PushNotifications/AppDelegate.swift
@@ -12,7 +12,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Setup Braze
- var configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint)
+ let configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint)
configuration.logger.level = .info
configuration.push.appGroup = "group.com.braze.PushNotifications.PushStories"
let braze = Braze(configuration: configuration)
diff --git a/Examples/Swift/Sources/PushNotifications/Info.plist b/Examples/Swift/Sources/PushNotifications/Info.plist
new file mode 100644
index 0000000000..d7f8ec8ca2
--- /dev/null
+++ b/Examples/Swift/Sources/PushNotifications/Info.plist
@@ -0,0 +1,30 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ PushNotifications
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ UIBackgroundModes
+
+ remote-notification
+
+ UILaunchStoryboardName
+ LaunchScreen
+
+
diff --git a/Examples/Swift/Sources/PushNotifications/PushNotifications.entitlements b/Examples/Swift/Sources/PushNotifications/PushNotifications.entitlements
new file mode 100644
index 0000000000..9cad402b51
--- /dev/null
+++ b/Examples/Swift/Sources/PushNotifications/PushNotifications.entitlements
@@ -0,0 +1,12 @@
+
+
+
+
+ aps-environment
+ development
+ com.apple.security.application-groups
+
+ group.com.braze.PushNotifications.PushStories
+
+
+
diff --git a/Examples/Sources/PushNotifications/Readme.swift b/Examples/Swift/Sources/PushNotifications/Readme.swift
similarity index 100%
rename from Examples/Sources/PushNotifications/Readme.swift
rename to Examples/Swift/Sources/PushNotifications/Readme.swift
diff --git a/Examples/Swift/Sources/PushNotificationsContentExtension/Info.plist b/Examples/Swift/Sources/PushNotificationsContentExtension/Info.plist
new file mode 100644
index 0000000000..0ef3fe3ffc
--- /dev/null
+++ b/Examples/Swift/Sources/PushNotificationsContentExtension/Info.plist
@@ -0,0 +1,47 @@
+
+
+
+
+ Braze
+
+ AppGroup
+ group.com.braze.PushNotifications.PushStories
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ PushNotificationsContentExtension
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ XPC!
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ NSExtension
+
+ NSExtensionAttributes
+
+ UNNotificationExtensionCategory
+ ab_cat_push_story_v2
+ UNNotificationExtensionDefaultContentHidden
+
+ UNNotificationExtensionInitialContentSizeRatio
+ 0.59999999999999998
+ UNNotificationExtensionUserInteractionEnabled
+
+
+ NSExtensionPointIdentifier
+ com.apple.usernotifications.content-extension
+ NSExtensionPrincipalClass
+ $(PRODUCT_MODULE_NAME).NotificationViewController
+
+
+
diff --git a/Examples/Swift/Sources/PushNotificationsContentExtension/NotificationViewController.swift b/Examples/Swift/Sources/PushNotificationsContentExtension/NotificationViewController.swift
new file mode 100644
index 0000000000..e4d429b3dc
--- /dev/null
+++ b/Examples/Swift/Sources/PushNotificationsContentExtension/NotificationViewController.swift
@@ -0,0 +1,3 @@
+import BrazePushStory
+
+class NotificationViewController: BrazePushStory.NotificationViewController {}
diff --git a/Examples/Swift/Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements b/Examples/Swift/Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements
new file mode 100644
index 0000000000..0f4c7da6cc
--- /dev/null
+++ b/Examples/Swift/Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements
@@ -0,0 +1,10 @@
+
+
+
+
+ com.apple.security.application-groups
+
+ group.com.braze.PushNotifications.PushStories
+
+
+
diff --git a/Examples/Swift/Sources/PushNotificationsServiceExtension/Info.plist b/Examples/Swift/Sources/PushNotificationsServiceExtension/Info.plist
new file mode 100644
index 0000000000..1387b1cc92
--- /dev/null
+++ b/Examples/Swift/Sources/PushNotificationsServiceExtension/Info.plist
@@ -0,0 +1,31 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ PushNotificationsServiceExtension
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ XPC!
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ NSExtension
+
+ NSExtensionPointIdentifier
+ com.apple.usernotifications.service
+ NSExtensionPrincipalClass
+ $(PRODUCT_MODULE_NAME).NotificationService
+
+
+
diff --git a/Examples/Swift/Sources/PushNotificationsServiceExtension/NotificationService.swift b/Examples/Swift/Sources/PushNotificationsServiceExtension/NotificationService.swift
new file mode 100644
index 0000000000..71d7005a43
--- /dev/null
+++ b/Examples/Swift/Sources/PushNotificationsServiceExtension/NotificationService.swift
@@ -0,0 +1,3 @@
+import BrazeNotificationService
+
+class NotificationService: BrazeNotificationService.NotificationService {}
diff --git a/Package.swift b/Package.swift
index 996e880073..630cf08fc5 100644
--- a/Package.swift
+++ b/Package.swift
@@ -26,8 +26,8 @@ let package = Package(
targets: [
.binaryTarget(
name: "BrazeKit",
- url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.4.0/BrazeKit.zip",
- checksum: "384a541e56b6c56ecdf787ab31cd217f89388e98e76c9d05e0d39a6dc85e3b5a"
+ url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.5.0/BrazeKit.zip",
+ checksum: "a20b8922491b014387b09f8284738585a700735b5f48ff88446ba7e3d2422544"
),
.target(
name: "BrazeKitResources",
@@ -42,18 +42,18 @@ let package = Package(
),
.binaryTarget(
name: "BrazeLocation",
- url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.4.0/BrazeLocation.zip",
- checksum: "541c9164a0936c05252cb6f45969a2b46c3e7cfe403a664304a3744f5c3c5a52"
+ url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.5.0/BrazeLocation.zip",
+ checksum: "3c1b18a5854672007684c1f99895c45a7fc47da6f7864db7fe561d6152f566ce"
),
.binaryTarget(
name: "BrazeNotificationService",
- url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.4.0/BrazeNotificationService.zip",
- checksum: "86881788339faa3729dc35f81315c60ccc138d789af831ae7b64d62ccc28cb7d"
+ url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.5.0/BrazeNotificationService.zip",
+ checksum: "1bda7311e0378a43fa78a57e964c953e6b3c06ac3ae57da14b367a5be6d59482"
),
.binaryTarget(
name: "BrazePushStory",
- url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.4.0/BrazePushStory.zip",
- checksum: "074c61f50c662f2eb4dd81562f7ffa5f774207932008e3dfa6a7224a61005816"
+ url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.5.0/BrazePushStory.zip",
+ checksum: "7aae86b1aa94c3fb269717423651a2bebbb0326d9674b027d4d4047e033f89d2"
),
]
)
diff --git a/README.md b/README.md
index 44d652ed28..9290f7f9cf 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# Braze Swift SDK (Early Access)
- [Braze User Guide](https://www.braze.com/docs/user_guide/introduction/ "Braze User Guide")
@@ -31,13 +47,13 @@ The following features are planned for development. To request new Swift SDK fea
-| | iOS | macCatatyst | tvOS |
-| ---------------------------------------------------------------------------------------------------------------------------- | :---: | :---------: | :-----------: |
-| **BrazeKit** _Main SDK library providing support for [analytics] and [push notifications]._ | ✅ | ✅ | ✅1 |
-| **BrazeUI** _Braze-provided user interface library for [In-App Messages] and [Content Cards]._ | ✅ | ✅ | n/a |
-| **BrazeLocation** _Location library providing support for [location analytics and geofence monitoring]._ | ✅ | ✅ | ✅2 |
-| **BrazeNotificationService** _Notification service extension library providing support for [rich push notifications]._ | ✅ | ✅ | n/a |
-| **BrazePushStory** _Notification content extension library providing support for [Push Stories]._ | ✅ | ✅ | n/a |
+| | iOS | tvOS | macCatatyst |
+| --------------------------------------------------------------------------------------------------------------------------- | :---: | :-----------: | :---------: |
+| **BrazeKit** _Main SDK library providing support for [analytics] and [push notifications]._ | ✅ | ✅1 | ✅ |
+| **BrazeUI** _Braze-provided user interface library for [In-App Messages] and [Content Cards]._ | ✅ | n/a | ✅ |
+| **BrazeLocation** _Location library providing support for [location analytics and geofence monitoring]._ | ✅ | ✅2 | ✅ |
+| **BrazeNotificationService** _Notification service extension library providing support for [rich push notifications]._ | ✅ | n/a | ✅ |
+| **BrazePushStory** _Notification content extension library providing support for [Push Stories]._ | ✅ | n/a | ✅ |
1 _Push notifications not supported on tvOS_
2 _Geofence monitoring not supported on tvOS_
diff --git a/Sources/BrazeUI/BrazeUIMocks.swift b/Sources/BrazeUI/BrazeUIMocks.swift
index f06437f706..4f6fdc9194 100644
--- a/Sources/BrazeUI/BrazeUIMocks.swift
+++ b/Sources/BrazeUI/BrazeUIMocks.swift
@@ -78,16 +78,16 @@ import UIKit
}
// Write to temporary cache
- let cacheUrl = try! FileManager.default.url(
+ let cacheURL = try! FileManager.default.url(
for: .cachesDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false
)
- let imageUrl = cacheUrl.appendingPathComponent("\(text).png")
- try! data.write(to: imageUrl)
+ let imageURL = cacheURL.appendingPathComponent("\(text).png")
+ try! data.write(to: imageURL)
- return imageUrl
+ return imageURL
}
}
diff --git a/Sources/BrazeUI/ContentCardUI/ContentCardUIModalViewController+ObjC.swift b/Sources/BrazeUI/ContentCardUI/ContentCardUIModalViewController+ObjC.swift
new file mode 100644
index 0000000000..83cbc3fab0
--- /dev/null
+++ b/Sources/BrazeUI/ContentCardUI/ContentCardUIModalViewController+ObjC.swift
@@ -0,0 +1,123 @@
+import BrazeKit
+import Foundation
+
+extension BrazeContentCardUI.ModalViewController {
+
+ /// Creates and return a table view controller displaying the latest content cards fetched by
+ /// the Braze SDK.
+ ///
+ /// - Parameter braze: The Braze instance.
+ @objc
+ @available(swift, obsoleted: 0.0.1)
+ public convenience init(braze: Braze) {
+ self.init(braze: braze, attributes: .defaults)
+ }
+
+ /// Creates and return a table view controller displaying the latest content cards fetched by
+ /// the Braze SDK.
+ ///
+ /// - Parameters:
+ /// - braze: The Braze instance.
+ /// - title: The navigation bar title.
+ @objc
+ @available(swift, obsoleted: 0.0.1)
+ public convenience init(braze: Braze, title: String) {
+ self.init(braze: braze, attributes: .defaults, title: title)
+ }
+
+ /// Creates and return a table view controller able to display content cards. For most use
+ /// cases, prefer using ``init(braze:attributes:)`` instead.
+ ///
+ /// - Parameters:
+ /// - initialCards: The initial Content Cards displayed.
+ /// - refresh: An optional closure implementing the refresh logic. `nil` disables pull to
+ /// refresh.
+ /// - subscribe: An optional closure implementing the subscription to new cards logic. `nil`
+ /// disables automatic updates.
+ /// - lastUpdate: The last time the content cards were updated.
+ @objc
+ @available(swift, obsoleted: 0.0.1)
+ public convenience init(
+ initialCards: [Braze.ContentCardRaw],
+ refresh: ((@escaping ([Braze.ContentCardRaw]?, Error?) -> Void) -> Void)?,
+ subscribe: ((@escaping ([Braze.ContentCardRaw]) -> Void) -> Braze.Cancellable)?,
+ lastUpdate: Date?
+ ) {
+ self.init(
+ initialCards: initialCards.compactMap { try? .init($0) },
+ refresh: refresh.flatMap { refresh in
+ { completion in
+ refresh { cards, error in
+ switch (cards, error) {
+ case (.some(let cards), nil):
+ completion(.success(cards.compactMap { try? Braze.ContentCard($0) }))
+ case (_, .some(let error)):
+ completion(.failure(error))
+ case (nil, nil):
+ completion(.failure(URLError(.cannotOpenFile)))
+ }
+ }
+ }
+ },
+ subscribe: subscribe.flatMap { subscribe in
+ { update in
+ subscribe { cards in
+ update(cards.compactMap { try? Braze.ContentCard($0) })
+ }
+ }
+ },
+ lastUpdate: lastUpdate,
+ attributes: .defaults,
+ title: ""
+ )
+ }
+
+ /// Creates and return a table view controller able to display content cards. For most use
+ /// cases, prefer using ``init(braze:attributes:)`` instead.
+ ///
+ /// - Parameters:
+ /// - initialCards: The initial Content Cards displayed.
+ /// - refresh: An optional closure implementing the refresh logic. `nil` disables pull to
+ /// refresh.
+ /// - subscribe: An optional closure implementing the subscription to new cards logic. `nil`
+ /// disables automatic updates.
+ /// - lastUpdate: The last time the content cards were updated.
+ /// - title: The navigation bar title.
+ @objc
+ @available(swift, obsoleted: 0.0.1)
+ public convenience init(
+ initialCards: [Braze.ContentCardRaw],
+ refresh: ((@escaping ([Braze.ContentCardRaw]?, Error?) -> Void) -> Void)?,
+ subscribe: ((@escaping ([Braze.ContentCardRaw]) -> Void) -> Braze.Cancellable)?,
+ lastUpdate: Date?,
+ title: String
+ ) {
+ self.init(
+ initialCards: initialCards.compactMap { try? .init($0) },
+ refresh: refresh.flatMap { refresh in
+ { completion in
+ refresh { cards, error in
+ switch (cards, error) {
+ case (.some(let cards), nil):
+ completion(.success(cards.compactMap { try? Braze.ContentCard($0) }))
+ case (_, .some(let error)):
+ completion(.failure(error))
+ case (nil, nil):
+ completion(.failure(URLError(.cannotOpenFile)))
+ }
+ }
+ }
+ },
+ subscribe: subscribe.flatMap { subscribe in
+ { update in
+ subscribe { cards in
+ update(cards.compactMap { try? Braze.ContentCard($0) })
+ }
+ }
+ },
+ lastUpdate: lastUpdate,
+ attributes: .defaults,
+ title: title
+ )
+ }
+}
diff --git a/Sources/BrazeUI/ContentCardUI/ContentCardUIModalViewController.swift b/Sources/BrazeUI/ContentCardUI/ContentCardUIModalViewController.swift
index 4ce3ccfb59..c98f20f1f3 100644
--- a/Sources/BrazeUI/ContentCardUI/ContentCardUIModalViewController.swift
+++ b/Sources/BrazeUI/ContentCardUI/ContentCardUIModalViewController.swift
@@ -5,10 +5,12 @@ extension BrazeContentCardUI {
/// Wraps ``ViewController`` in a `UINavigationController` with a _Done_ button. Use this class
/// for presenting the content cards modally.
+ @objc(BRZContentCardUIModalViewController)
open class ModalViewController: UINavigationController {
// MARK: - Properties
+ @objc
public let viewController: ViewController
// MARK: - Initialization
@@ -20,7 +22,7 @@ extension BrazeContentCardUI {
/// - braze: The Braze instance.
/// - attributes: An attributes struct allowing customization of the table view controller
/// and its cells.
- /// - title: The navigation bar title (default: `""`)
+ /// - title: The navigation bar title (default: `""`).
public init(
braze: Braze,
attributes: ViewController.Attributes = .defaults,
@@ -41,6 +43,7 @@ extension BrazeContentCardUI {
/// refresh.
/// - subscribe: An optional closure implementing the subscription to new cards logic. `nil`
/// disables automatic updates.
+ /// - lastUpdate: The last time the content cards were updated.
/// - attributes: An attributes struct allowing customization of the table view controller
/// and its cells.
/// - title: The navigation bar title (default: `""`)
@@ -48,6 +51,7 @@ extension BrazeContentCardUI {
initialCards: [Braze.ContentCard],
refresh: ((@escaping (Result<[Braze.ContentCard], Error>) -> Void) -> Void)? = nil,
subscribe: ((@escaping ([Braze.ContentCard]) -> Void) -> Braze.Cancellable)? = nil,
+ lastUpdate: Date? = nil,
attributes: ViewController.Attributes = .defaults,
title: String = ""
) {
@@ -55,17 +59,27 @@ extension BrazeContentCardUI {
initialCards: initialCards,
refresh: refresh,
subscribe: subscribe,
+ lastUpdate: lastUpdate,
attributes: attributes
)
viewController.title = title
super.init(rootViewController: viewController)
}
+ /// Does not support interface-builder / storyboards.
@available(*, unavailable)
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
+ /// See ``init(braze:attributes:title:)``.
+ @objc
+ @available(*, unavailable)
+ public init() {
+ // This init exists only to override the ObjC `NSObject.init` and disable it.
+ fatalError("init is not available")
+ }
+
// MARK: - LifeCycle
open override func viewDidLoad() {
diff --git a/Sources/BrazeUI/ContentCardUI/ContentCardUIViewController+ObjC.swift b/Sources/BrazeUI/ContentCardUI/ContentCardUIViewController+ObjC.swift
new file mode 100644
index 0000000000..9e173aa7de
--- /dev/null
+++ b/Sources/BrazeUI/ContentCardUI/ContentCardUIViewController+ObjC.swift
@@ -0,0 +1,77 @@
+import BrazeKit
+import Foundation
+
+extension BrazeContentCardUI.ViewController {
+
+ /// The content cards currently displayed.
+ @objc(cards)
+ @available(swift, obsoleted: 0.0.1)
+ open var _objc_cards: [Braze.ContentCardRaw] {
+ get { cards.map(Braze.ContentCardRaw.init) }
+ set { cards = newValue.compactMap { try? .init($0) } }
+ }
+
+ /// The delegate notified of the content cards UI lifecycle.
+ @objc(delegate)
+ @available(swift, obsoleted: 0.0.1)
+ public weak var _objc_delegate: _OBJC_BrazeContentCardUIViewControllerDelegate? {
+ get { (delegate as? _OBJC_BrazeContentCardUIViewControllerDelegateWrapper)?.delegate }
+ set { delegate = newValue.flatMap(_OBJC_BrazeContentCardUIViewControllerDelegateWrapper.init) }
+ }
+
+ /// Creates and return a table view controller displaying the latest content cards fetched by
+ /// the Braze SDK.
+ ///
+ /// - Parameter braze: The Braze instance.
+ @objc
+ @available(swift, obsoleted: 0.0.1)
+ public convenience init(braze: Braze) {
+ self.init(braze: braze, attributes: .defaults)
+ }
+
+ /// Creates and return a table view controller able to display content cards. For most use
+ /// cases, prefer using ``init(braze:attributes:)`` instead.
+ ///
+ /// - Parameters:
+ /// - initialCards: The initial Content Cards displayed.
+ /// - refresh: An optional closure implementing the refresh logic. `nil` disables pull to
+ /// refresh.
+ /// - subscribe: An optional closure implementing the subscription to new cards logic. `nil`
+ /// disables automatic updates.
+ /// - lastUpdate: The last time the content cards were updated.
+ @objc
+ @available(swift, obsoleted: 0.0.1)
+ public convenience init(
+ initialCards: [Braze.ContentCardRaw],
+ refresh: ((@escaping ([Braze.ContentCardRaw]?, Error?) -> Void) -> Void)? = nil,
+ subscribe: ((@escaping ([Braze.ContentCardRaw]) -> Void) -> Braze.Cancellable)? = nil,
+ lastUpdate: Date? = nil
+ ) {
+ self.init(
+ initialCards: initialCards.compactMap { try? .init($0) },
+ refresh: refresh.flatMap { refresh in
+ { completion in
+ refresh { cards, error in
+ switch (cards, error) {
+ case (.some(let cards), nil):
+ completion(.success(cards.compactMap { try? Braze.ContentCard($0) }))
+ case (_, .some(let error)):
+ completion(.failure(error))
+ case (nil, nil):
+ completion(.failure(URLError(.cannotOpenFile)))
+ }
+ }
+ }
+ },
+ subscribe: subscribe.flatMap { subscribe in
+ { update in
+ subscribe { cards in
+ update(cards.compactMap { try? Braze.ContentCard($0) })
+ }
+ }
+ },
+ lastUpdate: lastUpdate,
+ attributes: .defaults
+ )
+ }
+}
diff --git a/Sources/BrazeUI/ContentCardUI/ContentCardUIViewController.swift b/Sources/BrazeUI/ContentCardUI/ContentCardUIViewController.swift
index 06b51737bb..ab011a7564 100644
--- a/Sources/BrazeUI/ContentCardUI/ContentCardUIViewController.swift
+++ b/Sources/BrazeUI/ContentCardUI/ContentCardUIViewController.swift
@@ -4,6 +4,7 @@ import UIKit
extension BrazeContentCardUI {
/// A view controller which displays Braze Content Cards.
+ @objc(BRZContentCardUIViewController)
open class ViewController: UITableViewController, UITableViewDataSourcePrefetching {
/// The content cards currently displayed.
@@ -159,6 +160,7 @@ extension BrazeContentCardUI {
/// refresh.
/// - subscribe: An optional closure implementing the subscription to new cards logic. `nil`
/// disables automatic updates.
+ /// - lastUpdate: The last time the content cards were updated.
/// - attributes: An attributes struct allowing customization of the table view controller
/// and its cells.
public init(
@@ -182,6 +184,14 @@ extension BrazeContentCardUI {
fatalError("init(coder:) has not been implemented")
}
+ /// See ``init(braze:attributes:)``.
+ @objc
+ @available(*, unavailable)
+ public init() {
+ // This init exists only to override the ObjC `NSObject.init` and disable it.
+ fatalError("init is not available")
+ }
+
// MARK: - LifeCycle
open override func viewDidLoad() {
diff --git a/Sources/BrazeUI/ContentCardUI/ContentCardUIViewControllerDelegate+ObjC.swift b/Sources/BrazeUI/ContentCardUI/ContentCardUIViewControllerDelegate+ObjC.swift
new file mode 100644
index 0000000000..bf7f8b6152
--- /dev/null
+++ b/Sources/BrazeUI/ContentCardUI/ContentCardUIViewControllerDelegate+ObjC.swift
@@ -0,0 +1,66 @@
+import BrazeKit
+import Foundation
+
+@objc(BrazeContentCardUIViewControllerDelegate)
+public protocol _OBJC_BrazeContentCardUIViewControllerDelegate: AnyObject {
+
+ /// Defines whether Braze should process the Content Card click action.
+ ///
+ /// If the method returns `true` (default return value), Braze processes the click action.
+ ///
+ /// - Important: When this method returns `true` and the click action is a url, Braze will
+ /// **still** execute the `BrazeDelegate.braze(_:shouldOpenURL:)` delegate method
+ /// offering a last opportunity to modify or replace Braze url handling behavior.
+ /// If your implementation only needs access to the `url`, use
+ /// `BrazeDelegate.braze(_:shouldOpenURL:)` instead.
+ ///
+ /// - Parameters:
+ /// - controller: The view controller containing the Content Card.
+ /// - url: The url to process.
+ /// - card: The Content Card.
+ /// - Returns: `true` to let Braze process the click action, `false` otherwise
+ @objc(contentCardController:shouldProcess:card:)
+ optional func _objc_contentCard(
+ _ controller: BrazeContentCardUI.ViewController,
+ shouldProcess url: URL,
+ card: Braze.ContentCardRaw
+ ) -> Bool
+
+}
+
+// MARK: - Delegate Wrapper
+
+final class _OBJC_BrazeContentCardUIViewControllerDelegateWrapper:
+ BrazeContentCardUIViewControllerDelegate
+{
+
+ /// Property used as a unique key for the wrapper lifecycle behavior.
+ private static var wrapperKey: Void?
+
+ /// The ObjC content card UI view controller delegate.
+ weak var delegate: _OBJC_BrazeContentCardUIViewControllerDelegate?
+
+ init(_ delegate: _OBJC_BrazeContentCardUIViewControllerDelegate) {
+ self.delegate = delegate
+ objc_setAssociatedObject(delegate, &Self.wrapperKey, self, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+ }
+
+ deinit {
+ if let delegate = delegate {
+ objc_setAssociatedObject(delegate, &Self.wrapperKey, nil, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+ }
+ }
+
+ func contentCard(
+ _ controller: BrazeContentCardUI.ViewController,
+ shouldProcess clickAction: Braze.ContentCard.ClickAction,
+ card: Braze.ContentCard
+ ) -> Bool {
+ switch clickAction {
+ case .url(let url, _):
+ return delegate?._objc_contentCard?(controller, shouldProcess: url, card: .init(card)) ?? true
+ @unknown default:
+ return true
+ }
+ }
+}
diff --git a/Sources/BrazeUI/Dependencies/AsyncImageView.swift b/Sources/BrazeUI/Dependencies/AsyncImageView.swift
index 2ed98ed22f..3243cd76fa 100644
--- a/Sources/BrazeUI/Dependencies/AsyncImageView.swift
+++ b/Sources/BrazeUI/Dependencies/AsyncImageView.swift
@@ -77,7 +77,7 @@ open class AsyncImageView: UIView {
}
public let imageView: UIView = {
- let view = gifViewProvider.view(nil)
+ let view = GIFViewProvider.shared.view(nil)
view.contentMode = .scaleAspectFit
return view
}()
@@ -96,7 +96,7 @@ open class AsyncImageView: UIView {
private func updateImage() {
// Reset
activityIndicator.stopAnimating()
- gifViewProvider.updateView(imageView, nil)
+ GIFViewProvider.shared.updateView(imageView, nil)
retryButton.isHidden = true
switch imageLoad {
@@ -108,7 +108,7 @@ open class AsyncImageView: UIView {
retryButton.isHidden = retry == nil
case .success(let url, let size):
aspectRatio = size.width / size.height
- gifViewProvider.updateView(imageView, url)
+ GIFViewProvider.shared.updateView(imageView, url)
updateImageCornerRadius()
}
}
diff --git a/Sources/BrazeUI/Dependencies/GIFViewProvider+ObjC.swift b/Sources/BrazeUI/Dependencies/GIFViewProvider+ObjC.swift
new file mode 100644
index 0000000000..4839438de4
--- /dev/null
+++ b/Sources/BrazeUI/Dependencies/GIFViewProvider+ObjC.swift
@@ -0,0 +1,85 @@
+import UIKit
+
+/// A type providing methods to create and update views supporting animated GIF images.
+///
+/// Braze does not provide animated GIF support out of the box. Support can be added by wrapping a
+/// third party or your own view in an instance of `GIFViewProvider`.
+///
+/// Sample implementations for popular third party libraries are provided in
+/// .
+///
+/// Adding any of those libraries to your project allows you to enable animated GIF support in
+/// Braze's UI components.
+/// For instance, a project including SDWebImage and using the compatible sample code can do:
+/// ```swift
+/// GIFViewProvider.shared = .sdWebImage
+/// ```
+@objc(BRZGIFViewProvider)
+public final class _OBJC_BRZGIFViewProvider: NSObject {
+
+ /// The GIF view provider used for all BrazeUI components.
+ ///
+ /// By default, Braze displays animated GIFs as static images.
+ /// See ``GIFViewProvider-swift.struct`` for details about how to add support for animated GIFs.
+ @objc
+ public static var shared: _OBJC_BRZGIFViewProvider {
+ get { .init(GIFViewProvider.shared) }
+ set { GIFViewProvider.shared = newValue.gifViewProvider }
+ }
+
+ /// Creates a view able to display static and animated GIF images.
+ /// - Parameters:
+ /// - url: The local file url for the image.
+ @objc
+ public var view: (_ url: URL?) -> UIView {
+ get { gifViewProvider.view }
+ set { gifViewProvider.view = newValue }
+ }
+
+ /// Updates the passed view with a new image at `url`.
+ /// - Parameters:
+ /// - view: The view to update.
+ /// - url: The local file url for the image.
+ @objc
+ public var updateView: (_ view: UIView, _ url: URL?) -> Void {
+ get { gifViewProvider.updateView }
+ set { gifViewProvider.updateView = newValue }
+ }
+
+ var gifViewProvider: GIFViewProvider
+
+ /// Creates a GIF view provider.
+ /// - Parameters:
+ /// - view: See ``view``.
+ /// - updateView: See ``updateView``.
+ @objc
+ public convenience init(
+ view: @escaping (_ url: URL?) -> UIView,
+ updateView: @escaping (_ view: UIView, _ url: URL?) -> Void
+ ) {
+ self.init(.init(view: view, updateView: updateView))
+ }
+
+ init(_ gifViewProvider: GIFViewProvider) {
+ self.gifViewProvider = gifViewProvider
+ }
+
+ /// Creates a GIF view provider.
+ /// - Parameters:
+ /// - view: See ``view``.
+ /// - updateView: See ``updateView``.
+ @objc
+ public static func provider(
+ view: @escaping (_ url: URL?) -> UIView,
+ updateView: @escaping (_ view: UIView, _ url: URL?) -> Void
+ ) -> _OBJC_BRZGIFViewProvider {
+ .init(view: view, updateView: updateView)
+ }
+
+ /// The default, non-animating provider.
+ ///
+ /// This provider does not support animated images and display them as static images.
+ @objc
+ public static let nonAnimating = _OBJC_BRZGIFViewProvider(.nonAnimating)
+
+}
diff --git a/Sources/BrazeUI/Dependencies/GIFViewProvider.swift b/Sources/BrazeUI/Dependencies/GIFViewProvider.swift
index 49c813597c..4166b9bf4c 100644
--- a/Sources/BrazeUI/Dependencies/GIFViewProvider.swift
+++ b/Sources/BrazeUI/Dependencies/GIFViewProvider.swift
@@ -1,11 +1,5 @@
import UIKit
-/// The GIF view provider used for all BrazeUI components.
-///
-/// By default, Braze displays animated GIFs as static images.
-/// See ``GIFViewProvider-swift.struct`` for details about how to add support for animated GIFs.
-public var gifViewProvider: GIFViewProvider = .default
-
/// A type providing methods to create and update views supporting animated GIF images.
///
/// Braze does not provide animated GIF support out of the box. Support can be added by wrapping a
@@ -18,10 +12,16 @@ public var gifViewProvider: GIFViewProvider = .default
/// Braze's UI components.
/// For instance, a project including SDWebImage and using the compatible sample code can do:
/// ```swift
-/// BrazeUI.gifViewProvider = .sdWebImage
+/// GIFViewProvider.shared = .sdWebImage
/// ```
public struct GIFViewProvider {
+ /// The GIF view provider used for all BrazeUI components.
+ ///
+ /// By default, Braze displays animated GIFs as static images.
+ /// See ``GIFViewProvider-swift.struct`` for details about how to add support for animated GIFs.
+ public static var shared: GIFViewProvider = .nonAnimating
+
/// Creates a view able to display static and animated GIF images.
/// - Parameters:
/// - url: The local file url for the image.
@@ -45,10 +45,10 @@ public struct GIFViewProvider {
self.updateView = updateView
}
- /// The default provider.
+ /// The default, non-animating provider.
///
/// This provider does not support animated images and display them as static images.
- public static let `default` = Self(
+ public static let nonAnimating = GIFViewProvider(
view: { UIImageView(image: ($0?.path).flatMap(UIImage.init(contentsOfFile:))) },
updateView: { ($0 as? UIImageView)?.image = ($1?.path).flatMap(UIImage.init(contentsOfFile:)) }
)
diff --git a/Sources/BrazeUI/Deprecations.swift b/Sources/BrazeUI/Deprecations.swift
new file mode 100644
index 0000000000..94c098d757
--- /dev/null
+++ b/Sources/BrazeUI/Deprecations.swift
@@ -0,0 +1,20 @@
+// MARK: - Pre feature-parity
+
+// MARK: 08/25/2022
+
+/// See ``GIFViewProvider-swift.struct/shared``.
+@available(*, deprecated, renamed: "GIFViewProvider.shared")
+public var gifViewProvider: GIFViewProvider {
+ get { GIFViewProvider.shared }
+ set { GIFViewProvider.shared = newValue }
+}
+
+// MARK: 08/26/2022
+
+extension GIFViewProvider {
+
+ /// See ``nonAnimating``.
+ @available(*, deprecated, renamed: "nonAnimating")
+ public static let `default`: GIFViewProvider = .nonAnimating
+
+}
diff --git a/Sources/BrazeUI/InAppMessageUI/InAppMessageExt.swift b/Sources/BrazeUI/InAppMessageUI/InAppMessageExt.swift
index 22fb771d42..4bad1b45c5 100644
--- a/Sources/BrazeUI/InAppMessageUI/InAppMessageExt.swift
+++ b/Sources/BrazeUI/InAppMessageUI/InAppMessageExt.swift
@@ -52,11 +52,6 @@ extension Braze.InAppMessage.Button {
extension Braze.InAppMessage.Color {
- /// The `UIColor` representation of the in-app message color.
- public var uiColor: UIColor {
- UIColor(red: r, green: g, blue: b, alpha: a)
- }
-
/// A 1x1 pt image of the color.
public var image: UIImage {
let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
diff --git a/Sources/BrazeUI/InAppMessageUI/InAppMessageMocks.swift b/Sources/BrazeUI/InAppMessageUI/InAppMessageMocks.swift
index 9bddf09076..7168626b49 100644
--- a/Sources/BrazeUI/InAppMessageUI/InAppMessageMocks.swift
+++ b/Sources/BrazeUI/InAppMessageUI/InAppMessageMocks.swift
@@ -201,7 +201,7 @@ import Foundation
public static let mock = Self(
data: .mock,
- imageUri: .mockImage(width: 600, height: 600),
+ imageURL: .mockImage(width: 600, height: 600),
buttons: [
.mockSecondary,
.mockPrimary,
@@ -210,7 +210,7 @@ import Foundation
public static let mockLargeImage = Self(
data: .mock,
- imageUri: .mockImage(width: 1200, height: 2000),
+ imageURL: .mockImage(width: 1200, height: 2000),
buttons: [
.mockSecondary,
.mockPrimary,
@@ -219,7 +219,7 @@ import Foundation
public static let mockExtraLargeImage = Self(
data: .mock,
- imageUri: .mockImage(width: 1200, height: 4000),
+ imageURL: .mockImage(width: 1200, height: 4000),
buttons: [
.mockSecondary,
.mockPrimary,
@@ -228,13 +228,13 @@ import Foundation
public static let mockNoButtons = Self(
data: .mock,
- imageUri: .mockImage(width: 600, height: 600),
+ imageURL: .mockImage(width: 600, height: 600),
buttons: []
)
public static let mockOneButton = Self(
data: .mock,
- imageUri: .mockImage(width: 600, height: 600),
+ imageURL: .mockImage(width: 600, height: 600),
buttons: [
.mockPrimary
]
@@ -242,7 +242,7 @@ import Foundation
public static let mockThemed = Self(
data: .mock,
- imageUri: .mockImage(width: 600, height: 600),
+ imageURL: .mockImage(width: 600, height: 600),
buttons: [
.mockSecondary,
.mockPrimaryThemed,
@@ -263,7 +263,7 @@ import Foundation
public static let mock = Self(
data: .mock,
- imageUri: .mockImage(width: 1200, height: 1000),
+ imageURL: .mockImage(width: 1200, height: 1000),
header: "Hello world!",
message:
"Cupcake ipsum dolor sit amet topping. Cookie candy chupa chups jujubes pastry soufflé. Danish cake cheesecake liquorice wafer marshmallow macaroon."
@@ -271,7 +271,7 @@ import Foundation
public static let mockOneButton = Self(
data: .mock,
- imageUri: .mockImage(width: 1200, height: 1000),
+ imageURL: .mockImage(width: 1200, height: 1000),
header: "Hello world!",
message:
"Cupcake ipsum dolor sit amet topping. Cookie candy chupa chups jujubes pastry soufflé. Danish cake cheesecake liquorice wafer marshmallow macaroon.",
@@ -282,7 +282,7 @@ import Foundation
public static let mockTwoButtons = Self(
data: .mock,
- imageUri: .mockImage(width: 1200, height: 1000),
+ imageURL: .mockImage(width: 1200, height: 1000),
header: "Hello world!",
message:
"Cupcake ipsum dolor sit amet topping. Cookie candy chupa chups jujubes pastry soufflé. Danish cake cheesecake liquorice wafer marshmallow macaroon.",
@@ -294,7 +294,7 @@ import Foundation
public static let mockLandscape = Self(
data: .mock,
- imageUri: .mockImage(width: 2000, height: 600),
+ imageURL: .mockImage(width: 2000, height: 600),
header: "Hello world!",
message:
"Cupcake ipsum dolor sit amet topping. Cookie candy chupa chups jujubes pastry soufflé. Danish cake cheesecake liquorice wafer marshmallow macaroon."
@@ -302,7 +302,7 @@ import Foundation
public static let mockLandscapeOneButton = Self(
data: .mock,
- imageUri: .mockImage(width: 2000, height: 600),
+ imageURL: .mockImage(width: 2000, height: 600),
header: "Hello world!",
message:
"Cupcake ipsum dolor sit amet topping. Cookie candy chupa chups jujubes pastry soufflé. Danish cake cheesecake liquorice wafer marshmallow macaroon.",
@@ -311,7 +311,7 @@ import Foundation
public static let mockLandscapeTwoButtons = Self(
data: .mock,
- imageUri: .mockImage(width: 2000, height: 600),
+ imageURL: .mockImage(width: 2000, height: 600),
header: "Hello world!",
message:
"Cupcake ipsum dolor sit amet topping. Cookie candy chupa chups jujubes pastry soufflé. Danish cake cheesecake liquorice wafer marshmallow macaroon.",
@@ -323,7 +323,7 @@ import Foundation
public static let mockLeadingAligned = Self(
data: .mock,
- imageUri: .mockImage(width: 1200, height: 1000),
+ imageURL: .mockImage(width: 1200, height: 1000),
header: "Hello world!",
headerTextAlignment: .leading,
message:
@@ -337,7 +337,7 @@ import Foundation
public static let mockLong = Self(
data: .mock,
- imageUri: .mockImage(width: 1200, height: 1000),
+ imageURL: .mockImage(width: 1200, height: 1000),
header: "Hello world!",
message:
"""
@@ -353,7 +353,7 @@ import Foundation
public static let mockThemed = Self(
data: .mock,
- imageUri: .mockImage(width: 1200, height: 1000),
+ imageURL: .mockImage(width: 1200, height: 1000),
header: "Hello world!",
message:
"Cupcake ipsum dolor sit amet topping. Cookie candy chupa chups jujubes pastry soufflé. Danish cake cheesecake liquorice wafer marshmallow macaroon.",
@@ -378,18 +378,18 @@ import Foundation
public static let mock = Self(
data: .mock,
- imageUri: .mockImage(width: 1200, height: 2000)
+ imageURL: .mockImage(width: 1200, height: 2000)
)
public static let mockOneButton = Self(
data: .mock,
- imageUri: .mockImage(width: 1200, height: 2000),
+ imageURL: .mockImage(width: 1200, height: 2000),
buttons: [.mockPrimary]
)
public static let mockTwoButtons = Self(
data: .mock,
- imageUri: .mockImage(width: 1200, height: 2000),
+ imageURL: .mockImage(width: 1200, height: 2000),
buttons: [
.mockSecondary,
.mockPrimary,
@@ -398,18 +398,18 @@ import Foundation
public static let mockLandscape = Self(
data: .mock,
- imageUri: .mockImage(width: 2000, height: 1200)
+ imageURL: .mockImage(width: 2000, height: 1200)
)
public static let mockLandscapeOneButton = Self(
data: .mock,
- imageUri: .mockImage(width: 2000, height: 1200),
+ imageURL: .mockImage(width: 2000, height: 1200),
buttons: [.mockPrimary]
)
public static let mockLandscapeTwoButtons = Self(
data: .mock,
- imageUri: .mockImage(width: 2000, height: 1200),
+ imageURL: .mockImage(width: 2000, height: 1200),
buttons: [
.mockSecondary,
.mockPrimary,
@@ -418,7 +418,7 @@ import Foundation
public static let mockMinRecommendedSize = Self(
data: .mock,
- imageUri: .mockImage(width: 600, height: 1000),
+ imageURL: .mockImage(width: 600, height: 1000),
buttons: [
.mockSecondary,
.mockPrimary,
@@ -429,7 +429,7 @@ import Foundation
public static let mockNonRecommendedSize = Self(
data: .mock,
- imageUri: .mockImage(width: 1200, height: 4000),
+ imageURL: .mockImage(width: 1200, height: 4000),
buttons: [
.mockSecondary,
.mockPrimary,
@@ -438,7 +438,7 @@ import Foundation
public static let mockThemed = Self(
data: .mock,
- imageUri: .mockImage(width: 1200, height: 2000),
+ imageURL: .mockImage(width: 1200, height: 2000),
themes: [
"light": .init(
backgroundColor: 0xFF2D_3436,
@@ -499,7 +499,7 @@ import Foundation
extension Braze.InAppMessage.ClickAction {
- public static let mock = Self.uri(URL(string: "https://example.com")!, useWebView: false)
+ public static let mock = Self.url(URL(string: "https://example.com")!, useWebView: false)
}
diff --git a/Sources/BrazeUI/InAppMessageUI/InAppMessageUI+ObjC.swift b/Sources/BrazeUI/InAppMessageUI/InAppMessageUI+ObjC.swift
new file mode 100644
index 0000000000..5939e79a1e
--- /dev/null
+++ b/Sources/BrazeUI/InAppMessageUI/InAppMessageUI+ObjC.swift
@@ -0,0 +1,37 @@
+import BrazeKit
+import Foundation
+import UIKit
+
+extension BrazeInAppMessageUI {
+
+ /// The currently visible message view.
+ @objc(messageView)
+ @available(swift, obsoleted: 0.0.1)
+ public var _objc_messageView: UIView? { messageView }
+
+ /// The stack of in-app messages awaiting display.
+ ///
+ /// When the conditions to display a message are not met at trigger time, the message is pushed
+ /// onto the stack.
+ @objc(stack)
+ @available(swift, obsoleted: 0.0.1)
+ public var _objc_stack: [Braze.InAppMessageRaw] { stack.map(Braze.InAppMessageRaw.init) }
+
+ /// The object that act as the delegate for the in-app message UI.
+ ///
+ /// The delegate is not retained and must conform to ``BrazeInAppMessageUIDelegate``.
+ @objc(delegate)
+ @available(swift, obsoleted: 0.0.1)
+ public weak var _objc_delegate: _OBJC_BrazeInAppMessageUIDelegate? {
+ get { (delegate as? _OBJC_BrazeInAppMessageUIDelegateWrapper)?.delegate }
+ set { delegate = newValue.flatMap(_OBJC_BrazeInAppMessageUIDelegateWrapper.init) }
+ }
+
+ /// Dismisses the current in-app message view.
+ @objc(dismiss)
+ @available(swift, obsoleted: 0.0.1)
+ public func _objc_dismiss() {
+ dismiss()
+ }
+
+}
diff --git a/Sources/BrazeUI/InAppMessageUI/InAppMessageUI.swift b/Sources/BrazeUI/InAppMessageUI/InAppMessageUI.swift
index 002ac684f9..f88d67d3f8 100644
--- a/Sources/BrazeUI/InAppMessageUI/InAppMessageUI.swift
+++ b/Sources/BrazeUI/InAppMessageUI/InAppMessageUI.swift
@@ -9,8 +9,12 @@ import UIKit
///
/// To add GIF support to the in-app message UI components, set a valid
/// ``gifViewProvider-swift.var``.
-@objc
-open class BrazeInAppMessageUI: NSObject, BrazeInAppMessagePresenter {
+@objc(BrazeInAppMessageUI)
+open class BrazeInAppMessageUI:
+ NSObject,
+ BrazeInAppMessagePresenter,
+ _OBJC_BrazeInAppMessagePresenter
+{
// MARK: - Properties
@@ -71,7 +75,18 @@ open class BrazeInAppMessageUI: NSObject, BrazeInAppMessagePresenter {
}
+ @objc
+ public func present(message: Braze.InAppMessageRaw) {
+ do {
+ let message = try Braze.InAppMessage(message)
+ present(message: message)
+ } catch {
+ logError(for: message.context, error: .rawToTypedConversion(.init(error)))
+ }
+ }
+
/// Presents the next in-app message in the stack if any.
+ @objc
public func presentNext() {
// We use `last` instead of `popLast()` to avoid potentially modifying `stack` from a non
// main thread. The message is removed from the stack in `presentNow`.
@@ -117,7 +132,7 @@ open class BrazeInAppMessageUI: NSObject, BrazeInAppMessagePresenter {
?? createMessageView(
for: context.message,
attributes: context.attributes,
- gifViewProvider: gifViewProvider
+ gifViewProvider: GIFViewProvider.shared
)
guard let messageView = optMessageView else {
message.context?.discard()
@@ -172,20 +187,21 @@ open class BrazeInAppMessageUI: NSObject, BrazeInAppMessagePresenter {
/// Dismisses the current in-app message view.
/// - Parameter completion: Executed once the in-app message view has been dismissed or directly
/// when no in-app message view is currently presented.
+ @objc
public func dismiss(completion: (() -> Void)? = nil) {
messageView?.dismiss(completion: completion) ?? completion?()
}
// MARK: - Utils
- func logError(for message: Braze.InAppMessage, error: Error) {
- message.context?.logError(flattened: error.logDescription) ?? print(error.logDescription)
+ func logError(for context: Braze.InAppMessage.Context?, error: Error) {
+ context?.logError(flattened: error.logDescription) ?? print(error.logDescription)
}
func validateMainThread(for message: Braze.InAppMessage) -> Bool {
guard Thread.isMainThread else {
DispatchQueue.main.sync {
- logError(for: message, error: .noMainThread)
+ logError(for: message.context, error: .noMainThread)
}
return false
}
@@ -200,7 +216,7 @@ open class BrazeInAppMessageUI: NSObject, BrazeInAppMessagePresenter {
}
if Braze.UIUtils.activeRootViewController == nil {
- logError(for: message, error: .noAppRootViewController)
+ logError(for: message.context, error: .noAppRootViewController)
return false
}
@@ -215,7 +231,7 @@ open class BrazeInAppMessageUI: NSObject, BrazeInAppMessagePresenter {
stack.append(message)
}
- logError(for: message, error: .otherMessagePresented(push: push))
+ logError(for: message.context, error: .otherMessagePresented(push: push))
return false
}
return true
@@ -224,7 +240,7 @@ open class BrazeInAppMessageUI: NSObject, BrazeInAppMessagePresenter {
// Always return true, font-awesome missing is not a breaking error
func validateFontAwesome(for message: Braze.InAppMessage) -> Bool {
guard IconView.registerFontAwesomeIfNeeded() else {
- logError(for: message, error: .noFontAwesome)
+ logError(for: message.context, error: .noFontAwesome)
return true
}
return true
@@ -235,7 +251,7 @@ open class BrazeInAppMessageUI: NSObject, BrazeInAppMessagePresenter {
guard message.orientation.supported(by: traits) else {
stack.removeAll { $0 == message }
message.context?.discard()
- logError(for: message, error: .noMatchingOrientation)
+ logError(for: message.context, error: .noMatchingOrientation)
return false
}
return true
@@ -249,14 +265,14 @@ open class BrazeInAppMessageUI: NSObject, BrazeInAppMessagePresenter {
guard context.discarded == false else {
stack.removeAll { $0 == message }
- logError(for: message, error: .messageContextDiscarded)
+ logError(for: message.context, error: .messageContextDiscarded)
return false
}
guard context.valid else {
stack.removeAll { $0 == message }
context.discard()
- logError(for: message, error: .messageContextInvalid)
+ logError(for: message.context, error: .messageContextInvalid)
return false
}
diff --git a/Sources/BrazeUI/InAppMessageUI/InAppMessageUIDelegate+ObjC.swift b/Sources/BrazeUI/InAppMessageUI/InAppMessageUIDelegate+ObjC.swift
new file mode 100644
index 0000000000..d572a88e9d
--- /dev/null
+++ b/Sources/BrazeUI/InAppMessageUI/InAppMessageUIDelegate+ObjC.swift
@@ -0,0 +1,236 @@
+import BrazeKit
+import Foundation
+import UIKit
+
+/// Methods for reacting to the in-app message UI lifecycle.
+@objc(BrazeInAppMessageUIDelegate)
+public protocol _OBJC_BrazeInAppMessageUIDelegate: AnyObject {
+
+ /// Defines whether the in-app message will be displayed now, displayed later, or discarded.
+ ///
+ /// The default implementation returns the display choice
+ /// ``BrazeInAppMessageUI/DisplayChoice/now``.
+ ///
+ /// If there are situations where you would not want the in-app message to appear (such as during
+ /// a full screen game or on a loading screen), you can use this delegate to delay or discard
+ /// pending in-app message messages.
+ ///
+ /// When returning ``BrazeInAppMessageUI/DisplayChoice/later``, the message is put on the top of
+ /// the message ``BrazeInAppMessageUI/stack``. Use ``BrazeInAppMessageUI/presentNext()`` to
+ /// present the next in-app message in the stack.
+ ///
+ /// - Parameters:
+ /// - ui: The in-app message ui instance.
+ /// - message: The message to be presented.
+ /// - Returns: The display choice for `message`. See ``BrazeInAppMessageUI/DisplayChoice`` for
+ /// possible values.
+ @objc(inAppMessage:displayChoiceForMessage:)
+ optional func _objc_inAppMessage(
+ _ ui: BrazeInAppMessageUI,
+ displayChoiceForMessage message: Braze.InAppMessageRaw
+ ) -> _OBJC_BRZInAppMessageUIDisplayChoice
+
+ /// Called before the in-app message presentation and after
+ /// ``inAppMessage(_:prepareWith:)-11fog``.
+ /// - Parameters:
+ /// - ui: The in-app message ui instance.
+ /// - message: The message to be presented.
+ /// - view: The in-app message view.
+ @objc(inAppMessage:willPresent:view:)
+ optional func _objc_inAppMessage(
+ _ ui: BrazeInAppMessageUI,
+ willPresent message: Braze.InAppMessageRaw,
+ view: UIView
+ )
+
+ /// Called once the in-app message is fully visible to the user.
+ /// - Parameters:
+ /// - ui: The in-app message ui instance.
+ /// - message: The message to be presented.
+ /// - view: The in-app message view.
+ @objc(inAppMessage:didPresent:view:)
+ optional func _objc_inAppMessage(
+ _ ui: BrazeInAppMessageUI,
+ didPresent message: Braze.InAppMessageRaw,
+ view: UIView
+ )
+
+ /// Called before any dismissal animation occurs.
+ /// - Parameters:
+ /// - ui: The in-app message ui instance.
+ /// - message: The message to be presented.
+ /// - view: The in-app message view.
+ @objc(inAppMessage:willDismiss:view:)
+ optional func _objc_inAppMessage(
+ _ ui: BrazeInAppMessageUI,
+ willDismiss message: Braze.InAppMessageRaw,
+ view: UIView
+ )
+
+ /// Called after any dismissal animation occurs and the in-app message is fully hidden from the
+ /// user.
+ /// - Parameters:
+ /// - ui: The in-app message ui instance.
+ /// - message: The message to be presented.
+ /// - view: The in-app message view.
+ @objc(inAppMessage:didDismiss:view:)
+ optional func _objc_inAppMessage(
+ _ ui: BrazeInAppMessageUI,
+ didDismiss message: Braze.InAppMessageRaw,
+ view: UIView
+ )
+
+ /// Defines whether Braze should process the message click action.
+ ///
+ /// When returning `true` (default return value), Braze processes the click action.
+ ///
+ /// - Important: When this method returns `true` and the click action is an url, Braze will
+ /// **still** execute the `BrazeDelegate.braze(_:shouldOpenURL:)` delegate method
+ /// offering a last opportunity to modify or replace Braze url handling behavior.
+ /// If your implementation only needs access to the `url`, prefer using
+ /// `BrazeDelegate.braze(_:shouldOpenURL:)` instead.
+ ///
+ /// - Parameters:
+ /// - ui: The in-app message ui instance.
+ /// - clickAction: The click action.
+ /// - url: The click action url when `clickAction` is of type `url`, nil otherwise.
+ /// - buttonId: The optional button identifier.
+ /// - message: The message to be presented.
+ /// - view: The in-app message view.
+ /// - Returns: `true` to let Braze process the click action, `false` otherwise.
+ @objc(inAppMessage:shouldProcess:url:buttonId:message:view:)
+ optional func _objc_inAppMessage(
+ _ ui: BrazeInAppMessageUI,
+ shouldProcess clickAction: Braze.InAppMessageRaw._OBJC_BRZInAppMessageRawClickAction,
+ url: URL?,
+ buttonId: String?,
+ message: Braze.InAppMessageRaw,
+ view: UIView
+ ) -> Bool
+
+}
+
+/// The different display choices supported when receiving an in-app message from the Braze SDK.
+///
+/// See ``BrazeInAppMessageUIDelegate/inAppMessage(_:displayChoiceForMessage:)-1ghly``.
+@objc(BRZInAppMessageUIDisplayChoice)
+public enum _OBJC_BRZInAppMessageUIDisplayChoice: Int {
+
+ /// The in-app message is displayed immediately.
+ case now
+
+ /// The in-app message is **not displayed** and placed on top of the ``BrazeInAppMessageUI/stack``.
+ ///
+ /// Use ``BrazeInAppMessageUI/presentNext()`` to display the message at the top of the stack.
+ case later
+
+ /// The in-app message is discarded.
+ case discard
+
+ init(_ displayChoice: BrazeInAppMessageUI.DisplayChoice) {
+ switch displayChoice {
+ case .now: self = .now
+ case .later: self = .later
+ case .discard: self = .discard
+ }
+ }
+
+ var displayChoice: BrazeInAppMessageUI.DisplayChoice {
+ switch self {
+ case .now: return .now
+ case .later: return .later
+ case .discard: return .discard
+ }
+ }
+
+}
+
+// MARK: - Delegate Wrapper
+
+/// This delegate wraps the ObjC version of the `BrazeInAppMessageUIDelegate` and make it compatible
+/// with the base Swift implementation.
+final class _OBJC_BrazeInAppMessageUIDelegateWrapper: BrazeInAppMessageUIDelegate {
+
+ /// Property used as a unique key for the wrapper lifecycle behavior.
+ private static var wrapperKey: Void?
+
+ /// The ObjC in-app message UI delegate.
+ weak var delegate: _OBJC_BrazeInAppMessageUIDelegate?
+
+ /// Creates and returns a delegate wrapper for the ObjC version of `BrazeInAppMessageUIDelegate`.
+ ///
+ /// The delegate is stored weakly by the ``BrazeUI/BrazeInAppMessageUI`` instance. In order for
+ /// the wrapper to behave like its underlying delegate, it is dynamically attached to the ObjC
+ /// delegate implementation using the ObjC runtime. As long as the underlying delegate is alive,
+ /// this wrapper will remain alive.
+ ///
+ /// - Parameter delegate: The delegate to wrap.
+ init(_ delegate: _OBJC_BrazeInAppMessageUIDelegate) {
+ self.delegate = delegate
+ objc_setAssociatedObject(delegate, &Self.wrapperKey, self, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+ }
+
+ deinit {
+ if let delegate = delegate {
+ objc_setAssociatedObject(delegate, &Self.wrapperKey, nil, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+ }
+ }
+
+ func inAppMessage(
+ _ ui: BrazeInAppMessageUI,
+ displayChoiceForMessage message: Braze.InAppMessage
+ ) -> BrazeInAppMessageUI.DisplayChoice {
+ delegate?._objc_inAppMessage?(ui, displayChoiceForMessage: .init(message)).displayChoice ?? .now
+ }
+
+ func inAppMessage(
+ _ ui: BrazeInAppMessageUI,
+ willPresent message: Braze.InAppMessage,
+ view: InAppMessageView
+ ) {
+ delegate?._objc_inAppMessage?(ui, willPresent: .init(message), view: view)
+ }
+
+ func inAppMessage(
+ _ ui: BrazeInAppMessageUI,
+ didPresent message: Braze.InAppMessage,
+ view: InAppMessageView
+ ) {
+ delegate?._objc_inAppMessage?(ui, didPresent: .init(message), view: view)
+ }
+
+ func inAppMessage(
+ _ ui: BrazeInAppMessageUI,
+ willDismiss message: Braze.InAppMessage,
+ view: InAppMessageView
+ ) {
+ delegate?._objc_inAppMessage?(ui, willDismiss: .init(message), view: view)
+ }
+
+ func inAppMessage(
+ _ ui: BrazeInAppMessageUI,
+ didDismiss message: Braze.InAppMessage,
+ view: InAppMessageView
+ ) {
+ delegate?._objc_inAppMessage?(ui, didDismiss: .init(message), view: view)
+ }
+
+ func inAppMessage(
+ _ ui: BrazeInAppMessageUI,
+ shouldProcess clickAction: Braze.InAppMessage.ClickAction,
+ buttonId: String?,
+ message: Braze.InAppMessage,
+ view: InAppMessageView
+ ) -> Bool {
+ let message = Braze.InAppMessageRaw(message)
+ return delegate?._objc_inAppMessage?(
+ ui,
+ shouldProcess: .init(message.clickAction),
+ url: message.url,
+ buttonId: buttonId,
+ message: message,
+ view: view
+ ) ?? true
+ }
+
+}
diff --git a/Sources/BrazeUI/InAppMessageUI/InAppMessageUIError.swift b/Sources/BrazeUI/InAppMessageUI/InAppMessageUIError.swift
index a8bcff00c9..57481a2e85 100644
--- a/Sources/BrazeUI/InAppMessageUI/InAppMessageUIError.swift
+++ b/Sources/BrazeUI/InAppMessageUI/InAppMessageUIError.swift
@@ -8,6 +8,8 @@ extension BrazeInAppMessageUI {
case noContextProcessClickAction
case invalidBrazeActions
+ case rawToTypedConversion(Braze.ErrorString)
+
case noMainThread
case noMessageView
case noAppRootViewController
@@ -18,7 +20,7 @@ extension BrazeInAppMessageUI {
case messageContextDiscarded
case messageContextInvalid
- case htmlNoBaseUrl
+ case htmlNoBaseURL
case webViewNavigation(Braze.ErrorString)
case webViewScript(Braze.WebViewBridge.ScriptMessageHandler.Error)
case webViewScheme(Braze.WebViewBridge.SchemeHandler.Error)
@@ -42,6 +44,14 @@ extension BrazeInAppMessageUI.Error {
case .invalidBrazeActions:
return "Invalid Braze Actions found in click action. Skipping display."
+ case .rawToTypedConversion(let error):
+ return
+ """
+ Cannot convert raw in-app message to typed in-app message, error:
+ - description: \(error.localizedDescription)
+ - error: \(error)
+ """
+
case .noMainThread:
return
"Unable to present message - BrazeInAppMessageUI apis must be called from the main thread."
@@ -66,7 +76,7 @@ extension BrazeInAppMessageUI.Error {
return
"Unable to present message - message context is invalid. The message has been discarded and removed from the stack."
- case .htmlNoBaseUrl:
+ case .htmlNoBaseURL:
return "Unable to present html in-app message - no base url."
case .webViewNavigation(let error):
return "Unable to load html in web view - \(error.logDescription)"
diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullImageView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullImageView.swift
index e6f111e8a5..eee5bf32b0 100644
--- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullImageView.swift
+++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullImageView.swift
@@ -150,7 +150,7 @@ extension BrazeInAppMessageUI {
public init(
message: Braze.InAppMessage.FullImage,
attributes: Attributes = .defaults,
- gifViewProvider: GIFViewProvider = .default,
+ gifViewProvider: GIFViewProvider = .nonAnimating,
presented: Bool = false
) {
var modalImageAttrs = ModalImageView.Attributes()
@@ -174,7 +174,7 @@ extension BrazeInAppMessageUI {
super.init(
message: .init(
data: message.data,
- imageUri: message.imageUri,
+ imageURL: message.imageURL,
buttons: message.buttons,
themes: message.themes
),
diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullView.swift
index cf3ea78980..1ed5711a0b 100644
--- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullView.swift
+++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullView.swift
@@ -192,7 +192,7 @@ extension BrazeInAppMessageUI {
public init(
message: Braze.InAppMessage.Full,
attributes: Attributes = .defaults,
- gifViewProvider: GIFViewProvider = .default,
+ gifViewProvider: GIFViewProvider = .nonAnimating,
presented: Bool = false
) {
var modalViewAttrs = ModalView.Attributes()
@@ -220,7 +220,7 @@ extension BrazeInAppMessageUI {
super.init(
message: .init(
data: message.data,
- graphic: .image(message.imageUri),
+ graphic: .image(message.imageURL),
header: message.header,
headerTextAlignment: message.headerTextAlignment,
message: message.message,
diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIHtmlView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIHtmlView.swift
index 6c9d38f7fb..e2aad7624c 100644
--- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIHtmlView.swift
+++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIHtmlView.swift
@@ -166,6 +166,7 @@ extension BrazeInAppMessageUI {
yConstraint = webView?.anchors.top.pin()
webView?.anchors.top.equal(anchors.bottom).priority = .defaultHigh
case .auto, .fade:
+ webView?.anchors.center.align()
break
}
}
@@ -266,8 +267,8 @@ extension BrazeInAppMessageUI {
}
open func loadMessage() {
- guard let baseUrl = message.baseUrl else {
- logError(.htmlNoBaseUrl)
+ guard let baseURL = message.baseURL else {
+ logError(.htmlNoBaseURL)
message.animateOut = false
dismiss()
return
@@ -275,17 +276,17 @@ extension BrazeInAppMessageUI {
// Create directory if needed
try? FileManager.default.createDirectory(
- at: baseUrl,
+ at: baseURL,
withIntermediateDirectories: true,
attributes: nil
)
// Write index.html
- let index = baseUrl.appendingPathComponent("index.html")
+ let index = baseURL.appendingPathComponent("index.html")
try? message.message.write(to: index, atomically: true, encoding: .utf8)
// Load
- webView?.loadFileURL(index, allowingReadAccessTo: baseUrl)
+ webView?.loadFileURL(index, allowingReadAccessTo: baseURL)
}
}
diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalImageView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalImageView.swift
index 453ee045c8..77039ce3d5 100644
--- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalImageView.swift
+++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalImageView.swift
@@ -116,7 +116,7 @@ extension BrazeInAppMessageUI {
let gifViewProvider: GIFViewProvider
public lazy var imageView: UIView = {
- let imageView = gifViewProvider.view(message.imageUri)
+ let imageView = gifViewProvider.view(message.imageURL)
imageView.contentMode = .scaleAspectFill
return imageView
}()
@@ -177,7 +177,7 @@ extension BrazeInAppMessageUI {
public init(
message: Braze.InAppMessage.ModalImage,
attributes: Attributes = .defaults,
- gifViewProvider: GIFViewProvider = .default,
+ gifViewProvider: GIFViewProvider = .nonAnimating,
presented: Bool = false
) {
self.message = message
@@ -246,7 +246,7 @@ extension BrazeInAppMessageUI {
frame = CGRect(x: 0, y: 0, width: 500, height: 500)
Constraints {
// ImageView
- if let imageSize = imageSize(url: message.imageUri) {
+ if let imageSize = imageSize(url: message.imageURL) {
let aspectRatio = imageSize.width / imageSize.height
imageAspectRatioConstraint = imageView.anchors.width.equal(
imageView.anchors.height.multiplied(by: aspectRatio)
diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalView.swift
index b46c96970a..d354d7573c 100644
--- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalView.swift
+++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalView.swift
@@ -257,7 +257,7 @@ extension BrazeInAppMessageUI {
public init(
message: Braze.InAppMessage.Modal,
attributes: Attributes = .defaults,
- gifViewProvider: GIFViewProvider = .default,
+ gifViewProvider: GIFViewProvider = .nonAnimating,
presented: Bool = false
) {
self.message = message
diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUISlideupView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUISlideupView.swift
index e6e4b5a78e..3ae27d0ba7 100644
--- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUISlideupView.swift
+++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUISlideupView.swift
@@ -41,6 +41,9 @@ extension BrazeInAppMessageUI {
/// The image size.
public var imageSize = CGSize(width: 50, height: 50)
+ /// The chevron visibility.
+ public var chevronVisibility: ChevronVisibility = .auto
+
/// The content view corner radius.
public var cornerRadius = 15.0
@@ -70,6 +73,19 @@ extension BrazeInAppMessageUI {
}
+ /// Visibility options supported for the chevron.
+ public enum ChevronVisibility {
+
+ /// Visible when the message has a click action, hidden otherwise.
+ case auto
+
+ /// Always hidden.
+ case hidden
+
+ /// Always visible.
+ case visible
+ }
+
/// The view attributes. See ``Attributes-swift.struct``.
public var attributes: Attributes {
didSet { applyAttributes() }
@@ -95,6 +111,11 @@ extension BrazeInAppMessageUI {
// Fonts
messageLabel.font = attributes.font
+ // Chevron
+ chevronView.isHidden =
+ attributes.chevronVisibility == .hidden
+ || (attributes.chevronVisibility == .auto && message.clickAction == .none)
+
// Corner radius
shadowView.layer.cornerRadius = attributes.cornerRadius
contentView.layer.cornerRadius = attributes.cornerRadius
@@ -186,7 +207,7 @@ extension BrazeInAppMessageUI {
public init(
message: Braze.InAppMessage.Slideup,
attributes: Attributes = .defaults,
- gifViewProvider: GIFViewProvider = .default,
+ gifViewProvider: GIFViewProvider = .nonAnimating,
presented: Bool = false
) {
self.message = message
diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageView.swift
index d878948662..dcb0c1be03 100644
--- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageView.swift
+++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageView.swift
@@ -158,7 +158,7 @@ extension InAppMessageView {
public func logError(_ error: BrazeInAppMessageUI.Error) {
controller?.message.context?.logError(flattened: error.logDescription)
- ?? print(error.logDescription)
+ ?? print("[BrazeUI]", error.logDescription)
}
/// The controller currently displaying the in-app message view.
diff --git a/Sources/BrazeUI/InAppMessageUI/Views/Misc/IconView.swift b/Sources/BrazeUI/InAppMessageUI/Views/Misc/IconView.swift
index 534de20922..d09617cb7f 100644
--- a/Sources/BrazeUI/InAppMessageUI/Views/Misc/IconView.swift
+++ b/Sources/BrazeUI/InAppMessageUI/Views/Misc/IconView.swift
@@ -3,9 +3,9 @@ import UIKit
extension BrazeInAppMessageUI {
- /// View displaying a [FontAwesome v4.3] icon.
+ /// View displaying a [FontAwesome v4.3][1] icon.
///
- /// [FontAwesome v4.3]: https://fontawesome.com/v4.7/cheatsheet/
+ /// [1]: https://fontawesome.com/v4.7/cheatsheet/
open class IconView: UIView {
/// FontAwesome symbol to display.