From 13aaf544a7d26314e954bafeb07aba01c3f7a355 Mon Sep 17 00:00:00 2001
From: Loren Posen <loren.posen@iterable.com>
Date: Fri, 1 Aug 2025 14:46:38 -0700
Subject: [PATCH 01/13] refactor: enhance ReactIterableAPI so that the
 functions are accessible from RNIterableAPI.mm

---
 ios/RNIterableAPI/ReactIterableAPI.swift | 461 +++++++++++------------
 1 file changed, 228 insertions(+), 233 deletions(-)

diff --git a/ios/RNIterableAPI/ReactIterableAPI.swift b/ios/RNIterableAPI/ReactIterableAPI.swift
index 4db314f20..155dcdf0b 100644
--- a/ios/RNIterableAPI/ReactIterableAPI.swift
+++ b/ios/RNIterableAPI/ReactIterableAPI.swift
@@ -1,32 +1,30 @@
-//
-//  Created by Tapash Majumder on 3/19/20.
-//  Copyright © 2020 Iterable. All rights reserved.
-//
-
 import Foundation
-
 import IterableSDK
+import React
 
-@objc(ReactIterableAPI)
-class ReactIterableAPI: RCTEventEmitter {
+@objc public protocol ReactIterableAPIDelegate {
+    func sendEvent(withName: String, body: Any?)
+}
+
+@objc public class ReactIterableAPI: RCTEventEmitter {
     deinit {
         NotificationCenter.default.removeObserver(self)
     }
-    
+
     // MARK: - React Native Functions
-    
-    @objc static override func moduleName() -> String! {
+
+    @objc override public class func moduleName() -> String! {
         return "RNIterableAPI"
     }
-    
-    override var methodQueue: DispatchQueue! {
+
+    override open var methodQueue: DispatchQueue! {
         _methodQueue
     }
-    
-    @objc override static func requiresMainQueueSetup() -> Bool {
+
+    @objc override public static func requiresMainQueueSetup() -> Bool {
         false
     }
-    
+
     enum EventName: String, CaseIterable {
         case handleUrlCalled
         case handleCustomActionCalled
@@ -36,55 +34,49 @@ class ReactIterableAPI: RCTEventEmitter {
         case handleAuthSuccessCalled
         case handleAuthFailureCalled
     }
-    
-    override func supportedEvents() -> [String]! {
-        var result = [String]()
-        
-        EventName.allCases.forEach {
-            result.append($0.rawValue)
-        }
-        
-        return result
+
+    @objc public static var supportedEvents: [String] {
+        return EventName.allCases.map(\.rawValue)
     }
-    
-    override func startObserving() {
+
+    override public func startObserving() {
         ITBInfo()
-        
+
         shouldEmit = true
     }
-    
-    override func stopObserving() {
+
+    override public func stopObserving() {
         ITBInfo()
-        
+
         shouldEmit = false
     }
-    
+
     // MARK: - Native SDK Functions
-    
+
     @objc(initializeWithApiKey:config:version:resolver:rejecter:)
-    func initialize(apiKey: String,
-                    config configDict: [AnyHashable: Any],
+    public func initializeWithApiKey(apiKey: String,
+                    config configDict: NSDictionary,
                     version: String,
                     resolver: @escaping RCTPromiseResolveBlock,
                     rejecter: @escaping RCTPromiseRejectBlock) {
         ITBInfo()
-        
+
         initialize(withApiKey: apiKey,
                    config: configDict,
                    version: version,
                    resolver: resolver,
                    rejecter: rejecter)
     }
-    
+
     @objc(initialize2WithApiKey:config:apiEndPointOverride:version:resolver:rejecter:)
-    func initialize2(apiKey: String,
-                     config configDict: [AnyHashable: Any],
+    public func initialize2WithApiKey(apiKey: String,
+                     config configDict: NSDictionary,
                      version: String,
                      apiEndPointOverride: String,
                      resolver: @escaping RCTPromiseResolveBlock,
                      rejecter: @escaping RCTPromiseRejectBlock) {
         ITBInfo()
-        
+
         initialize(withApiKey: apiKey,
                    config: configDict,
                    version: version,
@@ -92,165 +84,166 @@ class ReactIterableAPI: RCTEventEmitter {
                    resolver: resolver,
                    rejecter: rejecter)
     }
-    
+
     @objc(setEmail:)
-    func set(email: String?) {
+    public func setEmail(email: String?) {
         ITBInfo()
-        
+
         IterableAPI.email = email
     }
 
     @objc(setEmail:authToken:)
-    func set(email: String?, authToken: String?) {
+    public func setEmail(email: String?, authToken: String?) {
         ITBInfo()
 
         IterableAPI.setEmail(email, authToken)
     }
-    
+
     @objc(getEmail:rejecter:)
-    func getEmail(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
+    public func getEmail(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
         ITBInfo()
-        
+
         resolver(IterableAPI.email)
     }
-    
+
     @objc(setUserId:)
-    func set(userId: String?) {
+    public func setUserId(userId: String?) {
         ITBInfo()
-        
+
         IterableAPI.userId = userId
     }
 
     @objc(setUserId:authToken:)
-    func set(userId: String?, authToken: String?) {
+    public func setUserId(userId: String?, authToken: String?) {
         ITBInfo()
-        
+
         IterableAPI.setUserId(userId, authToken)
     }
-    
+
     @objc(getUserId:rejecter:)
-    func getUserId(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
+    public func getUserId(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
         ITBInfo()
-        
+
         resolver(IterableAPI.userId)
     }
-    
+
     // MARK: - Iterable API Request Functions
-    
+
     @objc(setInAppShowResponse:)
-    func set(inAppShowResponse number: NSNumber) {
+    public func setInAppShowResponse(inAppShowResponse number: NSNumber) {
         ITBInfo()
-        
+
         self.inAppShowResponse = InAppShowResponse.from(number: number)
-        
+
         inAppHandlerSemaphore.signal()
     }
-    
+
     @objc(disableDeviceForCurrentUser)
-    func disableDeviceForCurrentUser() {
+    public func disableDeviceForCurrentUser() {
         ITBInfo()
-        
+
         IterableAPI.disableDeviceForCurrentUser()
     }
-    
+
     @objc(getLastPushPayload:rejecter:)
-    func getLastPushPayload(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
+    public func getLastPushPayload(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
         ITBInfo()
-        
+
         resolver(IterableAPI.lastPushPayload)
     }
-    
+
     @objc(getAttributionInfo:rejecter:)
-    func getAttributionInfo(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
+    public func getAttributionInfo(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
         ITBInfo()
-        
+
         resolver(IterableAPI.attributionInfo.map(SerializationUtil.encodableToDictionary))
     }
-    
+
     @objc(setAttributionInfo:)
-    func set(attributionInfo dict: [AnyHashable: Any]?) {
+    public func setAttributionInfo(attributionInfo dict: NSDictionary?) {
         ITBInfo()
-        
+
         guard let dict = dict else {
             IterableAPI.attributionInfo = nil
             return
         }
-        
-        IterableAPI.attributionInfo = SerializationUtil.dictionaryToDecodable(dict: dict)
+
+        IterableAPI.attributionInfo = SerializationUtil.dictionaryToDecodable(dict: dict as! [AnyHashable: Any])
     }
-    
+
     @objc(trackPushOpenWithCampaignId:templateId:messageId:appAlreadyRunning:dataFields:)
-    func trackPushOpen(campaignId: NSNumber,
+    public func trackPushOpenWithCampaignId(campaignId: NSNumber,
                        templateId: NSNumber?,
                        messageId: String,
                        appAlreadyRunning: Bool,
-                       dataFields: [AnyHashable: Any]?) {
+                       dataFields: NSDictionary?) {
         ITBInfo()
-        
+        let swiftDict = dataFields as? [AnyHashable: Any]
+
         IterableAPI.track(pushOpen: campaignId,
                           templateId: templateId,
                           messageId: messageId,
                           appAlreadyRunning: appAlreadyRunning,
-                          dataFields: dataFields)
+                          dataFields: swiftDict)
     }
 
     @objc(updateCart:)
-    func updateCart(items: [[AnyHashable: Any]]) {
+    public func updateCart(items: [[AnyHashable: Any]]) { // TODO: make sure this does not break
         ITBInfo()
 
         IterableAPI.updateCart(items: items.compactMap(CommerceItem.from(dict:)))
     }
-    
+
     @objc(trackPurchase:items:dataFields:)
-    func trackPurchase(total: NSNumber,
-                       items: [[AnyHashable: Any]],
-                       dataFields: [AnyHashable: Any]?) {
+    public func trackPurchase(total: NSNumber,
+                       items: [[AnyHashable: Any]], // TODO: make sure this does not break
+                       dataFields: NSDictionary?) {
         ITBInfo()
-        
+
         IterableAPI.track(purchase: total,
                           items: items.compactMap(CommerceItem.from(dict:)),
                           dataFields: dataFields)
     }
-    
+
     @objc(trackInAppOpen:location:)
-    func trackInAppOpen(messageId: String,
+    public func trackInAppOpen(messageId: String,
                         location locationNumber: NSNumber) {
         ITBInfo()
-        
+
         guard let message = IterableAPI.inAppManager.getMessage(withId: messageId) else {
             ITBError("Could not find message with id: \(messageId)")
             return
         }
-        
+
         IterableAPI.track(inAppOpen: message, location: InAppLocation.from(number: locationNumber))
     }
-    
+
     @objc(trackInAppClick:location:clickedUrl:)
-    func trackInAppClick(messageId: String,
+    public func trackInAppClick(messageId: String,
                          location locationNumber: NSNumber,
                          clickedUrl: String) {
         ITBInfo()
-        
+
         guard let message = IterableAPI.inAppManager.getMessage(withId: messageId) else {
             ITBError("Could not find message with id: \(messageId)")
             return
         }
-        
+
         IterableAPI.track(inAppClick: message, location: InAppLocation.from(number: locationNumber), clickedUrl: clickedUrl)
     }
-    
+
     @objc(trackInAppClose:location:source:clickedUrl:)
-    func trackInAppClose(messageId: String,
+    public func trackInAppClose(messageId: String,
                          location locationNumber: NSNumber,
                          source sourceNumber: NSNumber,
                          clickedUrl: String?) {
         ITBInfo()
-        
+
         guard let message = IterableAPI.inAppManager.getMessage(withId: messageId) else {
             ITBError("Could not find message with id: \(messageId)")
             return
         }
-        
+
         if let inAppCloseSource = InAppCloseSource.from(number: sourceNumber) {
             IterableAPI.track(inAppClose: message,
                               location: InAppLocation.from(number: locationNumber),
@@ -262,18 +255,18 @@ class ReactIterableAPI: RCTEventEmitter {
                               clickedUrl: clickedUrl)
         }
     }
-    
+
     @objc(inAppConsume:location:source:)
-    func inAppConsume(messageId: String,
+    public func inAppConsume(messageId: String,
                       location locationNumber: NSNumber,
                       source sourceNumber: NSNumber) {
         ITBInfo()
-        
+
         guard let message = IterableAPI.inAppManager.getMessage(withId: messageId) else {
             ITBError("Could not find message with id: \(messageId)")
             return
         }
-        
+
         if let inAppDeleteSource = InAppDeleteSource.from(number: sourceNumber) {
             IterableAPI.inAppConsume(message: message,
                                      location: InAppLocation.from(number: locationNumber),
@@ -283,108 +276,108 @@ class ReactIterableAPI: RCTEventEmitter {
                                      location: InAppLocation.from(number: locationNumber))
         }
     }
-    
+
     @objc(getHtmlInAppContentForMessage:resolver:rejecter:)
-    func getHtmlInAppContent(messageId: String, resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
+    public func getHtmlInAppContent(messageId: String, resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
         ITBInfo()
-        
+
         guard let message = IterableAPI.inAppManager.getMessage(withId: messageId) else {
             ITBError("Could not find message with id: \(messageId)")
             rejecter("", "Could not find message with id: \(messageId)", nil)
             return
         }
-        
+
         guard let content = message.content as? IterableHtmlInAppContent else {
             ITBError("Could not parse message content as HTML")
             rejecter("", "Could not parse message content as HTML", nil)
             return
         }
-        
+
         resolver(content.toDict())
     }
-    
+
     @objc(trackEvent:dataFields:)
-    func trackEvent(name: String, dataFields: [AnyHashable: Any]?) {
+    public func trackEvent(name: String, dataFields: NSDictionary?) {
         ITBInfo()
-        
-        IterableAPI.track(event: name, dataFields: dataFields)
+
+        IterableAPI.track(event: name, dataFields: dataFields as? [AnyHashable: Any])
     }
-    
+
     @objc(updateUser:mergeNestedObjects:)
-    func updateUser(dataFields: [AnyHashable: Any], mergeNestedObjects: Bool) {
+    public func updateUser(dataFields: NSDictionary, mergeNestedObjects: Bool) {
         ITBInfo()
-        
-        IterableAPI.updateUser(dataFields, mergeNestedObjects: mergeNestedObjects)
+
+        IterableAPI.updateUser(dataFields as? [AnyHashable: Any], mergeNestedObjects: mergeNestedObjects)
     }
-    
+
     @objc(updateEmail:authToken:)
-    func updateEmail(email: String, with authToken: String?) {
+    public func updateEmail(email: String, with authToken: String?) {
         ITBInfo()
-        
+
         if let authToken = authToken {
             IterableAPI.updateEmail(email, withToken: authToken, onSuccess: nil, onFailure: nil)
         } else {
             IterableAPI.updateEmail(email, onSuccess: nil, onFailure: nil)
         }
     }
-    
+
     @objc(handleAppLink:resolver:rejecter:)
-    func handle(appLink: String, resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
+    public func handleAppLink(appLink: String, resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
         ITBInfo()
-        
+
         if let url = URL(string: appLink) {
             resolver(IterableAPI.handle(universalLink: url))
         } else {
             rejecter("", "invalid URL", nil)
         }
     }
-    
+
     // MARK: - SDK In-App Manager Functions
-    
+
     @objc(getInAppMessages:rejecter:)
-    func getInAppMessages(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
+    public func getInAppMessages(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
         ITBInfo()
-        
+
         resolver(IterableAPI.inAppManager.getMessages().map { $0.toDict() })
     }
-    
+
     @objc(getInboxMessages:rejecter:)
-    func getInboxMessages(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
+    public func getInboxMessages(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
         ITBInfo()
-        
+
         resolver(IterableAPI.inAppManager.getInboxMessages().map{ $0.toDict() })
     }
-    
+
     @objc(getUnreadInboxMessagesCount:rejecter:)
-    func getUnreadInboxMessagesCount(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
+    public func getUnreadInboxMessagesCount(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
         ITBInfo()
-        
+
         resolver(IterableAPI.inAppManager.getUnreadInboxMessagesCount())
     }
-    
+
     @objc(showMessage:consume:resolver:rejecter:)
-    func show(messageId: String, consume: Bool, resolver: @escaping RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
+    public func showMessage(messageId: String, consume: Bool, resolver: @escaping RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
         ITBInfo()
-        
+
         guard let message = IterableAPI.inAppManager.getMessage(withId: messageId) else {
             ITBError("Could not find message with id: \(messageId)")
             return
         }
-        
+
         IterableAPI.inAppManager.show(message: message, consume: consume) { (url) in
             resolver(url.map({$0.absoluteString}))
         }
     }
-    
+
     @objc(removeMessage:location:source:)
-    func remove(messageId: String, location locationNumber: NSNumber, source sourceNumber: NSNumber) {
+    public func removeMessage(messageId: String, location locationNumber: NSNumber, source sourceNumber: NSNumber) {
         ITBInfo()
-        
+
         guard let message = IterableAPI.inAppManager.getMessage(withId: messageId) else {
             ITBError("Could not find message with id: \(messageId)")
             return
         }
-        
+
         if let inAppDeleteSource = InAppDeleteSource.from(number: sourceNumber) {
             IterableAPI.inAppManager.remove(message: message,
                                             location: InAppLocation.from(number: locationNumber),
@@ -394,19 +387,19 @@ class ReactIterableAPI: RCTEventEmitter {
                                             location: InAppLocation.from(number: locationNumber))
         }
     }
-    
+
     @objc(updateSubscriptions:unsubscribedChannelIds:unsubscribedMessageTypeIds:subscribedMessageTypeIds:campaignId:templateId:)
-    func updateSubscriptions(emailListIds: [NSNumber]?,
+    public func updateSubscriptions(emailListIds: [NSNumber]?,
                              unsubscribedChannelIds: [NSNumber]?,
                              unsubscribedMessageTypeIds: [NSNumber]?,
                              subscribedMessageTypeIds: [NSNumber]?,
                              campaignId: NSNumber,
                              templateId: NSNumber) {
         ITBInfo()
-        
+
         let finalCampaignId: NSNumber? = campaignId.intValue <= 0 ? nil : campaignId
         let finalTemplateId: NSNumber? = templateId.intValue <= 0 ? nil : templateId
-        
+
         IterableAPI.updateSubscriptions(emailListIds,
                                         unsubscribedChannelIds: unsubscribedChannelIds,
                                         unsubscribedMessageTypeIds: unsubscribedMessageTypeIds,
@@ -414,44 +407,44 @@ class ReactIterableAPI: RCTEventEmitter {
                                         campaignId: finalCampaignId,
                                         templateId: finalTemplateId)
     }
-    
+
     @objc(setReadForMessage:read:)
-    func setRead(for messageId: String, read: Bool) {
+    public func setReadForMessage(for messageId: String, read: Bool) {
         ITBInfo()
-        
+
         guard let message = IterableAPI.inAppManager.getMessage(withId: messageId) else {
             ITBError("Could not find message with id: \(messageId)")
             return
         }
-        
+
         IterableAPI.inAppManager.set(read: read, forMessage: message)
     }
-    
+
     @objc(setAutoDisplayPaused:)
-    func set(autoDisplayPaused: Bool) {
+    public func setAutoDisplayPaused(autoDisplayPaused: Bool) {
         ITBInfo()
-        
+
         DispatchQueue.main.async {
             IterableAPI.inAppManager.isAutoDisplayPaused = autoDisplayPaused
         }
     }
-    
+
     // MARK: - SDK Inbox Session Tracking Functions
-    
+
     @objc(startSession:)
-    func startSession(visibleRows: [[AnyHashable: Any]]) {
+    public func startSession(visibleRows: [[AnyHashable: Any]]) { // TODO: make sure this does not break
         let serializedRows = InboxImpressionTracker.RowInfo.rowInfos(from: visibleRows)
-        
+
         inboxSessionManager.startSession(visibleRows: serializedRows)
     }
-    
+
     @objc(endSession)
-    func endSession() {
+    public func endSession() {
         guard let sessionInfo = inboxSessionManager.endSession() else {
             ITBError("Could not find session info")
             return
         }
-        
+
         let inboxSession = IterableInboxSession(id: sessionInfo.startInfo.id,
                                                 sessionStartTime: sessionInfo.startInfo.startTime,
                                                 sessionEndTime: Date(),
@@ -460,71 +453,73 @@ class ReactIterableAPI: RCTEventEmitter {
                                                 endTotalMessageCount: IterableAPI.inAppManager.getInboxMessages().count,
                                                 endUnreadMessageCount: IterableAPI.inAppManager.getUnreadInboxMessagesCount(),
                                                 impressions: sessionInfo.impressions.map { $0.toIterableInboxImpression() })
-        
+
         IterableAPI.track(inboxSession: inboxSession)
     }
-    
+
     @objc(updateVisibleRows:)
-    func updateVisibleRows(visibleRows: [[AnyHashable: Any]]) {
+    public func updateVisibleRows(visibleRows: [[AnyHashable: Any]]) { // TODO: make sure this does not break
         let serializedRows = InboxImpressionTracker.RowInfo.rowInfos(from: visibleRows)
-        
+
         inboxSessionManager.updateVisibleRows(visibleRows: serializedRows)
     }
-    
+
     // MARK: - SDK Auth Manager Functions
-    
+
     @objc(passAlongAuthToken:)
-    func passAlong(authToken: String?) {
+    public func passAlongAuthToken(authToken: String?) {
         ITBInfo()
-        
+
         passedAuthToken = authToken
-        
+
         authHandlerSemaphore.signal()
     }
-    
+
     // MARK: Private
     private var shouldEmit = false
     private let _methodQueue = DispatchQueue(label: String(describing: ReactIterableAPI.self))
-    
+
     // Handling in-app delegate
     private var inAppShowResponse = InAppShowResponse.show
     private var inAppHandlerSemaphore = DispatchSemaphore(value: 0)
-    
+
     private var passedAuthToken: String?
     private var authHandlerSemaphore = DispatchSemaphore(value: 0)
-    
+
     private let inboxSessionManager = InboxSessionManager()
-    
-    private func initialize(withApiKey apiKey: String,
-                            config configDict: [AnyHashable: Any],
+
+    @objc func initialize(withApiKey apiKey: String,
+                            config configDict: NSDictionary,
                             version: String,
                             apiEndPointOverride: String? = nil,
                             resolver: @escaping RCTPromiseResolveBlock,
                             rejecter: @escaping RCTPromiseRejectBlock) {
         ITBInfo()
-        
+
         let launchOptions = createLaunchOptions()
-        let iterableConfig = IterableConfig.from(dict: configDict)
-        
+        let iterableConfig = IterableConfig.from(
+            dict: configDict as? [AnyHashable : Any]
+        )
+
         if let urlHandlerPresent = configDict["urlHandlerPresent"] as? Bool, urlHandlerPresent == true {
             iterableConfig.urlDelegate = self
         }
-        
+
         if let customActionHandlerPresent = configDict["customActionHandlerPresent"] as? Bool, customActionHandlerPresent == true {
             iterableConfig.customActionDelegate = self
         }
-        
+
         if let inAppHandlerPresent = configDict["inAppHandlerPresent"] as? Bool, inAppHandlerPresent == true {
             iterableConfig.inAppDelegate = self
         }
-        
+
         if let authHandlerPresent = configDict["authHandlerPresent"] as? Bool, authHandlerPresent {
             iterableConfig.authDelegate = self
         }
-        
+
         // connect new inbox in-app payloads to the RN SDK
         NotificationCenter.default.addObserver(self, selector: #selector(receivedIterableInboxChanged), name: Notification.Name.iterableInboxChanged, object: nil)
-        
+
         DispatchQueue.main.async {
             IterableAPI.initialize2(apiKey: apiKey,
                                     launchOptions: launchOptions,
@@ -532,112 +527,112 @@ class ReactIterableAPI: RCTEventEmitter {
                                     apiEndPointOverride: apiEndPointOverride) { result in
                 resolver(result)
             }
-            
+
             IterableAPI.setDeviceAttribute(name: "reactNativeSDKVersion", value: version)
         }
     }
-    
+
     @objc(receivedIterableInboxChanged)
-    private func receivedIterableInboxChanged() {
+    public func receivedIterableInboxChanged() {
         guard shouldEmit else {
             return
         }
-        
-        sendEvent(withName: EventName.receivedIterableInboxChanged.rawValue, body: nil)
+
+        delegate?.sendEvent(withName: EventName.receivedIterableInboxChanged.rawValue, body: nil as Any?)
     }
-    
+
     private func createLaunchOptions() -> [UIApplication.LaunchOptionsKey: Any]? {
-        guard let bridge = bridge else {
+        guard let bridge = self.bridge else {
             return nil
         }
-        
+
         return ReactIterableAPI.createLaunchOptions(bridgeLaunchOptions: bridge.launchOptions)
     }
-    
+
     private static func createLaunchOptions(bridgeLaunchOptions: [AnyHashable: Any]?) -> [UIApplication.LaunchOptionsKey: Any]? {
         guard let bridgeLaunchOptions = bridgeLaunchOptions,
               let remoteNotification = bridgeLaunchOptions[UIApplication.LaunchOptionsKey.remoteNotification.rawValue] else {
             return nil
         }
-        
+
         var result = [UIApplication.LaunchOptionsKey: Any]()
         result[UIApplication.LaunchOptionsKey.remoteNotification] = remoteNotification
-        
+
         return result
     }
 }
 
 extension ReactIterableAPI: IterableURLDelegate {
-    func handle(iterableURL url: URL, inContext context: IterableActionContext) -> Bool {
+    public func handle(iterableURL url: URL, inContext context: IterableActionContext) -> Bool {
         ITBInfo()
-        
+
         guard shouldEmit else {
             return false
         }
-        
+
         let contextDict = ReactIterableAPI.contextToDictionary(context: context)
-        sendEvent(withName: EventName.handleUrlCalled.rawValue,
+        delegate?.sendEvent(withName: EventName.handleUrlCalled.rawValue,
                   body: ["url": url.absoluteString,
-                         "context": contextDict] as [String : Any])
-        
+                         "context": contextDict] as Any?)
+
         return true
     }
-    
+
     private static func contextToDictionary(context: IterableActionContext) -> [AnyHashable: Any] {
         var result = [AnyHashable: Any]()
-        
+
         let actionDict = actionToDictionary(action: context.action)
         result["action"] = actionDict
         result["source"] = context.source.rawValue
-        
+
         return result
     }
-    
+
     private static func actionToDictionary(action: IterableAction) -> [AnyHashable: Any] {
         var actionDict = [AnyHashable: Any]()
-        
+
         actionDict["type"] = action.type
-        
+
         if let data = action.data {
             actionDict["data"] = data
         }
-        
+
         if let userInput = action.userInput {
             actionDict["userInput"] = userInput
         }
-        
+
         return actionDict
     }
 }
 
 extension ReactIterableAPI: IterableCustomActionDelegate {
-    func handle(iterableCustomAction action: IterableAction, inContext context: IterableActionContext) -> Bool {
+    public func handle(iterableCustomAction action: IterableAction, inContext context: IterableActionContext) -> Bool {
         ITBInfo()
-        
+
         let actionDict = ReactIterableAPI.actionToDictionary(action: action)
         let contextDict = ReactIterableAPI.contextToDictionary(context: context)
-        
-        sendEvent(withName: EventName.handleCustomActionCalled.rawValue,
+
+        delegate?.sendEvent(withName: EventName.handleCustomActionCalled.rawValue,
                   body: ["action": actionDict,
                          "context": contextDict])
-        
+
         return true
     }
 }
 
 extension ReactIterableAPI: IterableInAppDelegate {
-    func onNew(message: IterableInAppMessage) -> InAppShowResponse {
+    public func onNew(message: IterableInAppMessage) -> InAppShowResponse {
         ITBInfo()
-        
+
         guard shouldEmit else {
             return .show
         }
-        
-        sendEvent(withName: EventName.handleInAppCalled.rawValue,
+
+        delegate?.sendEvent(withName: EventName.handleInAppCalled.rawValue,
                   body: message.toDict())
-        
+
         let timeoutResult = inAppHandlerSemaphore.wait(timeout: .now() + 2.0)
-        
+
         if timeoutResult == .success {
             ITBInfo("inAppShowResponse: \(inAppShowResponse == .show)")
             return inAppShowResponse
@@ -649,38 +644,38 @@ extension ReactIterableAPI: IterableInAppDelegate {
 }
 
 extension ReactIterableAPI: IterableAuthDelegate {
-    func onAuthTokenRequested(completion: @escaping AuthTokenRetrievalHandler) {
+    public func onAuthTokenRequested(completion: @escaping AuthTokenRetrievalHandler) {
         ITBInfo()
-        
+
         DispatchQueue.global(qos: .userInitiated).async {
-            self.sendEvent(withName: EventName.handleAuthCalled.rawValue,
-                           body: nil)
-            
+            self.delegate?.sendEvent(withName: EventName.handleAuthCalled.rawValue,
+                           body: nil as Any?)
+
             let authTokenRetrievalResult = self.authHandlerSemaphore.wait(timeout: .now() + 30.0)
-            
+
             if authTokenRetrievalResult == .success {
                 ITBInfo("authTokenRetrieval successful")
-                
+
                 DispatchQueue.main.async {
                     completion(self.passedAuthToken)
                 }
-                
-                self.sendEvent(withName: EventName.handleAuthSuccessCalled.rawValue,
-                               body: nil)
+
+                self.delegate?.sendEvent(withName: EventName.handleAuthSuccessCalled.rawValue,
+                               body: nil as Any?)
             } else {
                 ITBInfo("authTokenRetrieval timed out")
-                
+
                 DispatchQueue.main.async {
                     completion(nil)
                 }
-                
-                self.sendEvent(withName: EventName.handleAuthFailureCalled.rawValue,
-                               body: nil)
+
+                self.delegate?.sendEvent(withName: EventName.handleAuthFailureCalled.rawValue,
+                               body: nil as Any?)
             }
         }
     }
-    
-    func onTokenRegistrationFailed(_ reason: String?) {
-        
+
+    public func onTokenRegistrationFailed(_ reason: String?) {
+
     }
 }

From 2c25245266271b5a67d037708b50d574f26d4961 Mon Sep 17 00:00:00 2001
From: Loren Posen <loren.posen@iterable.com>
Date: Fri, 1 Aug 2025 16:08:11 -0700
Subject: [PATCH 02/13] refactor: integrate Swift-based ReactIterableAPI into
 RNIterableAPI for new architecture

---
 ios/RNIterableAPI/RNIterableAPI.h  |  21 +-
 ios/RNIterableAPI/RNIterableAPI.mm | 400 +++++++++++++++++++----------
 2 files changed, 278 insertions(+), 143 deletions(-)

diff --git a/ios/RNIterableAPI/RNIterableAPI.h b/ios/RNIterableAPI/RNIterableAPI.h
index 26bbf81fe..6fa7d0f64 100644
--- a/ios/RNIterableAPI/RNIterableAPI.h
+++ b/ios/RNIterableAPI/RNIterableAPI.h
@@ -1,9 +1,14 @@
-//
-//  RNIterableAPI.h
-//  RNIterableAPI
-//
-//  Created by Loren Posen on 6/11/25.
-//  Copyright © 2025 Iterable. All rights reserved.
-//
-#import <React/RCTBridgeModule.h>
+#import <Foundation/Foundation.h>
+#import <React/RCTEventEmitter.h>
 
+#if RCT_NEW_ARCH_ENABLED
+
+#import <React/RCTUtils.h>
+#import <React/RCTConvert.h>
+#import <React/RCTTurboModuleRegistry.h>
+#import <RNIterableAPISpec/RNIterableAPISpec.h>
+@interface RNIterableAPI : RCTEventEmitter <NativeRNIterableAPISpec>
+
+#endif
+
+@end
diff --git a/ios/RNIterableAPI/RNIterableAPI.mm b/ios/RNIterableAPI/RNIterableAPI.mm
index dc40a6e12..31671d026 100644
--- a/ios/RNIterableAPI/RNIterableAPI.mm
+++ b/ios/RNIterableAPI/RNIterableAPI.mm
@@ -1,139 +1,269 @@
-//
-//  Created by Tapash Majumder on 3/19/20.
-//  Copyright © 2020 Iterable. All rights reserved.
-//
 #import "RNIterableAPI.h"
+#import "RNIterableAPISpec.h"
+#import <IterableSDK/IterableSDK.h> // umbrella (Objective-C) header
+
+// Forward-declare the Swift protocols/enum used in the Swift header.
+@protocol IterableInAppDelegate;
+@protocol IterableCustomActionDelegate;
+@protocol IterableAuthDelegate;
+@protocol IterableURLDelegate;
+typedef NS_ENUM(NSInteger, InAppShowResponse) {
+  show = 0,
+  skip = 1,
+};
+
+#import "Iterable_React_Native_SDK-Swift.h"
+
+@interface RNIterableAPI () <ReactIterableAPIDelegate>
+@end
 
-@interface RCT_EXTERN_REMAP_MODULE(RNIterableAPI, ReactIterableAPI, NSObject)
-
-// MARK: - Native SDK Functions
-
-RCT_EXTERN_METHOD(initializeWithApiKey: (nonnull NSString *) apiKey
-                  config: (nonnull NSDictionary *) config
-                  version: (nonnull NSString *) version
-                  resolver: (RCTPromiseResolveBlock) resolve
-                  rejecter: (RCTPromiseRejectBlock) reject)
-
-RCT_EXTERN_METHOD(initialize2WithApiKey: (nonnull NSString *) apiKey
-                  config: (nonnull NSDictionary *) config
-                  apiEndPointOverride: (nonnull NSString *) apiEndPoint
-                  version: (nonnull NSString *) version
-                  resolver: (RCTPromiseResolveBlock) resolve
-                  rejecter: (RCTPromiseRejectBlock) reject)
-
-RCT_EXTERN_METHOD(setEmail: (NSString *) email
-                  authToken: (NSString *) authToken)
-
-RCT_EXTERN_METHOD(getEmail: (RCTPromiseResolveBlock) resolve
-                  rejecter: (RCTPromiseRejectBlock) reject)
-
-RCT_EXTERN_METHOD(setUserId: (NSString *) userId
-                  authToken: (NSString *) authToken)
-
-RCT_EXTERN_METHOD(getUserId: (RCTPromiseResolveBlock) resolve
-                  rejecter: (RCTPromiseRejectBlock) reject)
-
-// MARK: - Iterable API Request Functions
-
-RCT_EXTERN_METHOD(disableDeviceForCurrentUser)
-
-RCT_EXTERN_METHOD(setInAppShowResponse: (nonnull NSNumber *) inAppShowResponse)
-
-RCT_EXTERN_METHOD(getLastPushPayload: (RCTPromiseResolveBlock) resolve
-                  rejecter: (RCTPromiseRejectBlock) reject)
-
-RCT_EXTERN_METHOD(getAttributionInfo: (RCTPromiseResolveBlock) resolve
-                  rejecter: (RCTPromiseRejectBlock) reject)
-
-RCT_EXTERN_METHOD(setAttributionInfo: (NSDictionary *) attributionInfo)
-
-RCT_EXTERN_METHOD(trackPushOpenWithCampaignId: (nonnull NSNumber *) campaignId
-                  templateId: (nonnull NSNumber *) templateId
-                  messageId: (nonnull NSString *) messageId
-                  appAlreadyRunning: (BOOL) appAlreadyRunning
-                  dataFields: (NSDictionary *) dataFields)
-
-RCT_EXTERN_METHOD(updateCart: (NSArray *) items)
-
-RCT_EXTERN_METHOD(trackPurchase: (nonnull NSNumber *) total
-                  items: (NSArray *) items
-                  dataFields: (NSDictionary *) dataFields)
-
-RCT_EXTERN_METHOD(trackInAppOpen: (NSString *) messageId
-                  location: (nonnull NSNumber *) location)
-
-RCT_EXTERN_METHOD(trackInAppClick: (nonnull NSString *) messageId
-                  location: (nonnull NSNumber *) location
-                  clickedUrl: (nonnull NSString *) clickedUrl)
-
-RCT_EXTERN_METHOD(trackInAppClose: (nonnull NSString *) messageId
-                  location: (nonnull NSNumber *) location
-                  source: (nonnull NSNumber *) source
-                  clickedUrl: (NSString *) clickedUrl)
-
-RCT_EXTERN_METHOD(inAppConsume: (nonnull NSString *) messageId
-                  location: (nonnull NSNumber *) location
-                  source: (nonnull NSNumber *) source)
-
-RCT_EXTERN_METHOD(trackEvent: (nonnull NSString *) name
-                  dataFields: (NSDictionary *) dataFields)
-
-RCT_EXTERN_METHOD(updateUser: (nonnull NSDictionary *) dataFields
-                  mergeNestedObjects: (BOOL) mergeNestedObjects)
-
-RCT_EXTERN_METHOD(updateEmail: (nonnull NSString *) email
-                  authToken: (NSString *) authToken)
-
-RCT_EXTERN_METHOD(handleAppLink: (nonnull NSString *) appLink
-                  resolver: (RCTPromiseResolveBlock) resolve
-                  rejecter: (RCTPromiseRejectBlock) reject)
-
-RCT_EXTERN_METHOD(updateSubscriptions: (NSArray *) emailListIds
-                  unsubscribedChannelIds: (NSArray *) unsubscribedChannelIds
-                  unsubscribedMessageTypeIds: (NSArray *) unsubscribedMessageTypeIds
-                  subscribedMessageTypeIds: (NSArray *) subscribedMessageTypeIds
-                  campaignId: (nonnull NSNumber *) campaignId
-                  templateId: (nonnull NSNumber *) templateId)
-
-// MARK: - SDK In-App Manager Functions
-
-RCT_EXTERN_METHOD(getInAppMessages: (RCTPromiseResolveBlock) resolve
-                  rejecter: (RCTPromiseRejectBlock) reject)
-
-RCT_EXTERN_METHOD(getHtmlInAppContentForMessage: (nonnull NSString *) messageId
-                  resolver: (RCTPromiseResolveBlock) resolve
-                  rejecter: (RCTPromiseRejectBlock) reject)
-
-RCT_EXTERN_METHOD(getInboxMessages: (RCTPromiseResolveBlock) resolve
-                  rejecter: (RCTPromiseRejectBlock) reject)
-
-RCT_EXTERN_METHOD(getUnreadInboxMessagesCount: (RCTPromiseResolveBlock) resolve
-                  rejecter: (RCTPromiseRejectBlock) reject)
-
-RCT_EXTERN_METHOD(showMessage: (nonnull NSString *) messageId
-                  consume: (nonnull BOOL) consume
-                  resolver: (RCTPromiseResolveBlock) resolve
-                  rejecter: (RCTPromiseRejectBlock) reject)
-
-RCT_EXTERN_METHOD(removeMessage: (nonnull NSString *) messageId
-                  location: (nonnull NSNumber *) location
-                  source: (nonnull NSNumber *) source)
-
-RCT_EXTERN_METHOD(setReadForMessage: (nonnull NSString *) messageId
-                  read: (BOOL) read)
-
-RCT_EXTERN_METHOD(setAutoDisplayPaused: (BOOL) paused)
-
-// MARK: - SDK Inbox Session Tracking Functions
-
-RCT_EXTERN_METHOD(startSession: (nonnull NSArray *) visibleRows)
-
-RCT_EXTERN_METHOD(endSession)
-
-RCT_EXTERN_METHOD(updateVisibleRows: (nonnull NSArray *) visibleRows)
-
-// MARK: - SDK Auth Manager Functions
-
-RCT_EXTERN_METHOD(passAlongAuthToken: (NSString *) authToken)
+@implementation RNIterableAPI {
+  ReactIterableAPI *_swiftAPI;
+}
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    _swiftAPI = [ReactIterableAPI new];
+    _swiftAPI.delegate = self;
+  }
+  return self;
+}
+
+RCT_EXPORT_MODULE()
+
+- (NSArray<NSString *> *)supportedEvents {
+  return [ReactIterableAPI supportedEvents];
+}
+
+- (void)sendEventWithName:(NSString *_Nonnull)name result:(double)result {
+  [self sendEventWithName:name body:@(result)];
+}
+
+- (void)startObserving {
+  [(ReactIterableAPI *)_swiftAPI startObserving];
+}
+
+- (void)stopObserving {
+  [(ReactIterableAPI *)_swiftAPI stopObserving];
+}
+
+- (void)initializeWithApiKey:(NSString *)apiKey
+                      config:(NSDictionary *)config
+                     version:(NSString *)version
+                     resolve:(RCTPromiseResolveBlock)resolve
+                      reject:(RCTPromiseRejectBlock)reject {
+  [_swiftAPI initializeWithApiKey:apiKey
+                           config:config
+                          version:version
+                         resolver:resolve
+                         rejecter:reject];
+}
+
+- (void)initialize2WithApiKey:(NSString *)apiKey
+                       config:(NSDictionary *)config
+                      version:(NSString *)version
+          apiEndPointOverride:(NSString *)apiEndPointOverride
+                      resolve:(RCTPromiseResolveBlock)resolve
+                       reject:(RCTPromiseRejectBlock)reject {
+  [_swiftAPI initialize2WithApiKey:apiKey
+                            config:config
+               apiEndPointOverride:apiEndPointOverride
+                           version:version
+                          resolver:resolve
+                          rejecter:reject];
+}
+
+- (void)setEmail:(NSString *_Nullable)email
+       authToken:(NSString *_Nullable)authToken {
+  [_swiftAPI setEmail:email authToken:authToken];
+}
+
+- (void)getEmail:(RCTPromiseResolveBlock)resolve
+          reject:(RCTPromiseRejectBlock)reject {
+  [_swiftAPI getEmail:resolve rejecter:reject];
+}
+
+- (void)setUserId:(NSString *_Nullable)userId
+        authToken:(NSString *_Nullable)authToken {
+  [_swiftAPI setUserId:userId authToken:authToken];
+}
+
+- (void)getUserId:(RCTPromiseResolveBlock)resolve
+           reject:(RCTPromiseRejectBlock)reject {
+  [_swiftAPI getUserId:resolve rejecter:reject];
+}
+
+- (void)setInAppShowResponse:(NSNumber *)inAppShowResponse {
+  [_swiftAPI setInAppShowResponse:inAppShowResponse];
+}
+
+- (void)getInAppMessages:(RCTPromiseResolveBlock)resolve
+                  reject:(RCTPromiseRejectBlock)reject {
+  [_swiftAPI getInAppMessages:resolve rejecter:reject];
+}
+
+- (void)getInboxMessages:(RCTPromiseResolveBlock)resolve
+                  reject:(RCTPromiseRejectBlock)reject {
+  [_swiftAPI getInboxMessages:resolve rejecter:reject];
+}
+
+// NOTE: This is not used anywhere on the JS side.
+- (void)getUnreadInboxMessagesCount:(RCTPromiseResolveBlock)resolve
+                             reject:(RCTPromiseRejectBlock)reject {
+  [_swiftAPI getUnreadInboxMessagesCount:resolve rejecter:reject];
+}
+
+- (void)showMessage:(NSString *)messageId
+            consume:(BOOL)consume
+            resolve:(RCTPromiseResolveBlock)resolve
+             reject:(RCTPromiseRejectBlock)reject {
+  [_swiftAPI showMessage:messageId
+                 consume:consume
+                resolver:resolve
+                rejecter:reject];
+}
+
+- (void)removeMessage:(NSString *)messageId
+             location:(NSNumber *)location
+               source:(NSNumber *)source {
+  [_swiftAPI removeMessage:messageId location:location source:source];
+}
+
+- (void)setReadForMessage:(NSString *)messageId read:(BOOL)read {
+  [_swiftAPI setReadForMessage:messageId read:read];
+}
+
+- (void)setAutoDisplayPaused:(BOOL)autoDisplayPaused {
+  [_swiftAPI setAutoDisplayPaused:autoDisplayPaused];
+}
+
+- (void)trackEvent:(NSString *)name dataFields:(NSDictionary *)dataFields {
+  [_swiftAPI trackEvent:name dataFields:dataFields];
+}
+
+- (void)trackPushOpenWithCampaignId:(NSNumber *)campaignId
+                         templateId:(NSNumber *)templateId
+                          messageId:(NSString *)messageId
+                  appAlreadyRunning:(BOOL)appAlreadyRunning
+                         dataFields:(NSDictionary *)dataFields {
+  [_swiftAPI trackPushOpenWithCampaignId:campaignId
+                              templateId:templateId
+                               messageId:messageId
+                       appAlreadyRunning:appAlreadyRunning
+                              dataFields:dataFields];
+}
+
+- (void)trackInAppOpen:(NSString *)messageId location:(NSNumber *)location {
+  [_swiftAPI trackInAppOpen:messageId location:location];
+}
+
+- (void)trackInAppClick:(NSString *)messageId
+               location:(NSNumber *)location
+             clickedUrl:(NSString *)clickedUrl {
+  [_swiftAPI trackInAppClick:messageId location:location clickedUrl:clickedUrl];
+}
+
+- (void)trackInAppClose:(NSString *)messageId
+               location:(NSNumber *)location
+                 source:(NSNumber *)source
+             clickedUrl:(NSString *)clickedUrl {
+  [_swiftAPI trackInAppClose:messageId
+                    location:location
+                      source:source
+                  clickedUrl:clickedUrl];
+}
+
+- (void)inAppConsume:(NSString *)messageId
+            location:(NSNumber *)location
+              source:(NSNumber *)source {
+  [_swiftAPI inAppConsume:messageId location:location source:source];
+}
+
+- (void)updateCart:(NSArray *)items {
+  [_swiftAPI updateCart:items];
+}
+
+- (void)trackPurchase:(NSNumber *)total
+                items:(NSArray *)items
+           dataFields:(NSDictionary *)dataFields {
+  [_swiftAPI trackPurchase:total items:items dataFields:dataFields];
+}
+
+- (void)updateUser:(NSDictionary *)dataFields
+    mergeNestedObjects:(BOOL)mergeNestedObjects {
+  [_swiftAPI updateUser:dataFields mergeNestedObjects:mergeNestedObjects];
+}
+
+- (void)updateEmail:(NSString *)email authToken:(NSString *)authToken {
+  [_swiftAPI updateEmail:email authToken:authToken];
+}
+
+- (void)getAttributionInfo:(RCTPromiseResolveBlock)resolve
+                    reject:(RCTPromiseRejectBlock)reject {
+  [_swiftAPI getAttributionInfo:resolve rejecter:reject];
+}
+
+- (void)setAttributionInfo:(NSDictionary *)attributionInfo {
+  [_swiftAPI setAttributionInfo:attributionInfo];
+}
+
+- (void)disableDeviceForCurrentUser {
+  [_swiftAPI disableDeviceForCurrentUser];
+}
+
+- (void)getLastPushPayload:(RCTPromiseResolveBlock)resolve
+                    reject:(RCTPromiseRejectBlock)reject {
+  [_swiftAPI getLastPushPayload:resolve rejecter:reject];
+}
+
+- (void)getHtmlInAppContentForMessage:(NSString *)messageId
+                              resolve:(RCTPromiseResolveBlock)resolve
+                               reject:(RCTPromiseRejectBlock)reject {
+  [_swiftAPI getHtmlInAppContentForMessage:messageId
+                                  resolver:resolve
+                                  rejecter:reject];
+}
+
+- (void)handleAppLink:(NSString *)appLink
+              resolve:(RCTPromiseResolveBlock)resolve
+               reject:(RCTPromiseRejectBlock)reject {
+  [_swiftAPI handleAppLink:appLink resolver:resolve rejecter:reject];
+}
+
+- (void)updateSubscriptions:(NSArray *)emailListIds
+        unsubscribedChannelIds:(NSArray *)unsubscribedChannelIds
+    unsubscribedMessageTypeIds:(NSArray *)unsubscribedMessageTypeIds
+      subscribedMessageTypeIds:(NSArray *)subscribedMessageTypeIds
+                    campaignId:(NSNumber *)campaignId
+                    templateId:(NSNumber *)templateId {
+  [_swiftAPI updateSubscriptions:emailListIds
+          unsubscribedChannelIds:unsubscribedChannelIds
+      unsubscribedMessageTypeIds:unsubscribedMessageTypeIds
+        subscribedMessageTypeIds:subscribedMessageTypeIds
+                      campaignId:campaignId
+                      templateId:templateId];
+}
+
+- (void)startSession:(NSArray *)visibleRows {
+  [_swiftAPI startSession:visibleRows];
+}
+
+- (void)endSession {
+  [_swiftAPI endSession];
+}
+
+- (void)updateVisibleRows:(NSArray *)visibleRows {
+  [_swiftAPI updateVisibleRows:visibleRows];
+}
+
+- (void)passAlongAuthToken:(NSString *)authToken {
+  [_swiftAPI passAlongAuthToken:authToken];
+}
+
+- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
+    (const facebook::react::ObjCTurboModule::InitParams &)params {
+  return std::make_shared<facebook::react::NativeRNIterableAPISpecJSI>(params);
+}
 
 @end

From 47a74850a17b60217a38a3901ba96b77ee2d0dba Mon Sep 17 00:00:00 2001
From: Loren Posen <loren.posen@iterable.com>
Date: Sat, 2 Aug 2025 09:39:43 -0700
Subject: [PATCH 03/13] fix: update Podfile to use dynamic linking for
 Iterable-iOS-SDK in RNIterableAPI module

---
 example/ios/Podfile | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/example/ios/Podfile b/example/ios/Podfile
index 833bd46c8..5c0791cf5 100644
--- a/example/ios/Podfile
+++ b/example/ios/Podfile
@@ -13,7 +13,9 @@ prepare_react_native_project!
 linkage = ENV['USE_FRAMEWORKS']
 if linkage != nil
   Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
-  use_frameworks! :linkage => linkage.to_sym
+  # IMPORTANT: New Architecture Issue solution
+  # This is needed to use the Swift code from Iterable-iOS-SDK in the RNIterableAPI module
+  use_frameworks! :linkage => :dynamic
 end
 
 target 'ReactNativeSdkExample' do

From 7ff28f2af40ee3721864cc78a946df360610a8e9 Mon Sep 17 00:00:00 2001
From: Loren Posen <loren.posen@iterable.com>
Date: Sat, 2 Aug 2025 09:42:15 -0700
Subject: [PATCH 04/13] feat: configure code to support new and legacy
 architecture

---
 ios/RNIterableAPI/RNIterableAPI.h        |   6 +
 ios/RNIterableAPI/RNIterableAPI.mm       | 323 ++++++++++++++++++++++-
 ios/RNIterableAPI/ReactIterableAPI.swift | 124 +++------
 3 files changed, 361 insertions(+), 92 deletions(-)

diff --git a/ios/RNIterableAPI/RNIterableAPI.h b/ios/RNIterableAPI/RNIterableAPI.h
index 140584f4f..b7eabdf33 100644
--- a/ios/RNIterableAPI/RNIterableAPI.h
+++ b/ios/RNIterableAPI/RNIterableAPI.h
@@ -7,8 +7,14 @@
   #import <React/RCTConvert.h>
   #import <React/RCTTurboModuleRegistry.h>
   #import <RNIterableAPISpec/RNIterableAPISpec.h>
+
 @interface RNIterableAPI : RCTEventEmitter <NativeRNIterableAPISpec>
 
+#else
+
+  #import <React/RCTBridgeModule.h>
+@interface RNIterableAPI : RCTEventEmitter <RCTBridgeModule>
+
 #endif
 
 @end
diff --git a/ios/RNIterableAPI/RNIterableAPI.mm b/ios/RNIterableAPI/RNIterableAPI.mm
index a54200f1f..dc877ba89 100644
--- a/ios/RNIterableAPI/RNIterableAPI.mm
+++ b/ios/RNIterableAPI/RNIterableAPI.mm
@@ -1,5 +1,9 @@
 #import "RNIterableAPI.h"
-#import "RNIterableAPISpec.h"
+
+#if RCT_NEW_ARCH_ENABLED
+  #import "RNIterableAPISpec.h"
+#endif
+
 #import <IterableSDK/IterableSDK.h> // umbrella (Objective-C) header
 
 // Forward-declare the Swift protocols/enum used in the Swift header.
@@ -24,6 +28,7 @@ @implementation RNIterableAPI {
 - (instancetype)init {
   self = [super init];
   if(self) {
+    // Option 2.B - Instantiate the Calculator and set the delegate
     _swiftAPI = [ReactIterableAPI new];
     _swiftAPI.delegate = self;
   }
@@ -32,6 +37,10 @@ - (instancetype)init {
 
 RCT_EXPORT_MODULE()
 
+// - (NSArray<NSString *> *)supportedEvents {
+//   return [_swiftAPI supportedEvents];
+// }
+
 - (NSArray<NSString *> *)supportedEvents {
   return [ReactIterableAPI supportedEvents];
 }
@@ -40,19 +49,33 @@ - (void)sendEventWithName:(NSString *_Nonnull)name result:(double)result {
   [self sendEventWithName:name body:@(result)];
 }
 
+#if RCT_NEW_ARCH_ENABLED
 - (void)startObserving {
+  NSLog(@"ReactNativeSdk startObserving");
   [(ReactIterableAPI *)_swiftAPI startObserving];
 }
 
 - (void)stopObserving {
+  NSLog(@"ReactNativeSdk stopObserving");
   [(ReactIterableAPI *)_swiftAPI stopObserving];
 }
 
+- (void)hello {
+  NSLog(@"Hello from Objective-C");
+  [(ReactIterableAPI *)_swiftAPI hello];
+}
+
+- (void)testEventDispatch {
+  NSLog(@"***ITBL OBJ-C*** testEventDispatch");
+  [_swiftAPI testEventDispatch];
+}
+
 - (void)initializeWithApiKey:(NSString *)apiKey
                       config:(NSDictionary *)config
                      version:(NSString *)version
                      resolve:(RCTPromiseResolveBlock)resolve
                       reject:(RCTPromiseRejectBlock)reject {
+  NSLog(@"ReactNativeSdk initializeWithApiKey");
   [_swiftAPI initializeWithApiKey:apiKey
                            config:config
                           version:version
@@ -66,6 +89,7 @@ - (void)initialize2WithApiKey:(NSString *)apiKey
           apiEndPointOverride:(NSString *)apiEndPointOverride
                       resolve:(RCTPromiseResolveBlock)resolve
                        reject:(RCTPromiseRejectBlock)reject {
+  NSLog(@"ReactNativeSdk initialize2WithApiKey");
   [_swiftAPI initialize2WithApiKey:apiKey
                             config:config
                apiEndPointOverride:apiEndPointOverride
@@ -76,41 +100,49 @@ - (void)initialize2WithApiKey:(NSString *)apiKey
 
 - (void)setEmail:(NSString *_Nullable)email
        authToken:(NSString *_Nullable)authToken {
+  NSLog(@"ReactNativeSdk setEmail");
   [_swiftAPI setEmail:email authToken:authToken];
 }
 
 - (void)getEmail:(RCTPromiseResolveBlock)resolve
           reject:(RCTPromiseRejectBlock)reject {
+  NSLog(@"ReactNativeSdk getEmail");
   [_swiftAPI getEmail:resolve rejecter:reject];
 }
 
 - (void)setUserId:(NSString *_Nullable)userId
         authToken:(NSString *_Nullable)authToken {
+  NSLog(@"ReactNativeSdk setUserId");
   [_swiftAPI setUserId:userId authToken:authToken];
 }
 
 - (void)getUserId:(RCTPromiseResolveBlock)resolve
            reject:(RCTPromiseRejectBlock)reject {
+  NSLog(@"ReactNativeSdk getUserId");
   [_swiftAPI getUserId:resolve rejecter:reject];
 }
 
 - (void)setInAppShowResponse:(NSNumber *)inAppShowResponse {
+  NSLog(@"ReactNativeSdk setInAppShowResponse");
   [_swiftAPI setInAppShowResponse:inAppShowResponse];
 }
 
 - (void)getInAppMessages:(RCTPromiseResolveBlock)resolve
                   reject:(RCTPromiseRejectBlock)reject {
+  NSLog(@"ReactNativeSdk getInAppMessages");
   [_swiftAPI getInAppMessages:resolve rejecter:reject];
 }
 
 - (void)getInboxMessages:(RCTPromiseResolveBlock)resolve
                   reject:(RCTPromiseRejectBlock)reject {
+  NSLog(@"ReactNativeSdk getInboxMessages");
   [_swiftAPI getInboxMessages:resolve rejecter:reject];
 }
 
 // NOTE: This is not used anywhere on the JS side.
 - (void)getUnreadInboxMessagesCount:(RCTPromiseResolveBlock)resolve
                              reject:(RCTPromiseRejectBlock)reject {
+  NSLog(@"ReactNativeSdk getUnreadInboxMessagesCount");
   [_swiftAPI getUnreadInboxMessagesCount:resolve rejecter:reject];
 }
 
@@ -118,6 +150,7 @@ - (void)showMessage:(NSString *)messageId
             consume:(BOOL)consume
             resolve:(RCTPromiseResolveBlock)resolve
              reject:(RCTPromiseRejectBlock)reject {
+  NSLog(@"ReactNativeSdk showMessage");
   [_swiftAPI showMessage:messageId
                  consume:consume
                 resolver:resolve
@@ -127,18 +160,22 @@ - (void)showMessage:(NSString *)messageId
 - (void)removeMessage:(NSString *)messageId
              location:(NSNumber *)location
                source:(NSNumber *)source {
+  NSLog(@"ReactNativeSdk removeMessage");
   [_swiftAPI removeMessage:messageId location:location source:source];
 }
 
 - (void)setReadForMessage:(NSString *)messageId read:(BOOL)read {
+  NSLog(@"ReactNativeSdk setReadForMessage");
   [_swiftAPI setReadForMessage:messageId read:read];
 }
 
 - (void)setAutoDisplayPaused:(BOOL)autoDisplayPaused {
+  NSLog(@"ReactNativeSdk setAutoDisplayPaused");
   [_swiftAPI setAutoDisplayPaused:autoDisplayPaused];
 }
 
 - (void)trackEvent:(NSString *)name dataFields:(NSDictionary *)dataFields {
+  NSLog(@"ReactNativeSdk trackEvent");
   [_swiftAPI trackEvent:name dataFields:dataFields];
 }
 
@@ -147,6 +184,7 @@ - (void)trackPushOpenWithCampaignId:(NSNumber *)campaignId
                           messageId:(NSString *)messageId
                   appAlreadyRunning:(BOOL)appAlreadyRunning
                          dataFields:(NSDictionary *)dataFields {
+  NSLog(@"ReactNativeSdk trackPushOpenWithCampaignId");
   [_swiftAPI trackPushOpenWithCampaignId:campaignId
                               templateId:templateId
                                messageId:messageId
@@ -155,12 +193,14 @@ - (void)trackPushOpenWithCampaignId:(NSNumber *)campaignId
 }
 
 - (void)trackInAppOpen:(NSString *)messageId location:(NSNumber *)location {
+  NSLog(@"ReactNativeSdk trackInAppOpen");
   [_swiftAPI trackInAppOpen:messageId location:location];
 }
 
 - (void)trackInAppClick:(NSString *)messageId
                location:(NSNumber *)location
              clickedUrl:(NSString *)clickedUrl {
+  NSLog(@"ReactNativeSdk trackInAppClick");
   [_swiftAPI trackInAppClick:messageId location:location clickedUrl:clickedUrl];
 }
 
@@ -168,6 +208,7 @@ - (void)trackInAppClose:(NSString *)messageId
                location:(NSNumber *)location
                  source:(NSNumber *)source
              clickedUrl:(NSString *)clickedUrl {
+  NSLog(@"ReactNativeSdk trackInAppClose");
   [_swiftAPI trackInAppClose:messageId
                     location:location
                       source:source
@@ -177,49 +218,59 @@ - (void)trackInAppClose:(NSString *)messageId
 - (void)inAppConsume:(NSString *)messageId
             location:(NSNumber *)location
               source:(NSNumber *)source {
+  NSLog(@"ReactNativeSdk inAppConsume");
   [_swiftAPI inAppConsume:messageId location:location source:source];
 }
 
 - (void)updateCart:(NSArray *)items {
+  NSLog(@"ReactNativeSdk updateCart");
   [_swiftAPI updateCart:items];
 }
 
 - (void)trackPurchase:(NSNumber *)total
                 items:(NSArray *)items
            dataFields:(NSDictionary *)dataFields {
+  NSLog(@"ReactNativeSdk trackPurchase");
   [_swiftAPI trackPurchase:total items:items dataFields:dataFields];
 }
 
 - (void)updateUser:(NSDictionary *)dataFields
     mergeNestedObjects:(BOOL)mergeNestedObjects {
+  NSLog(@"ReactNativeSdk updateUser");
   [_swiftAPI updateUser:dataFields mergeNestedObjects:mergeNestedObjects];
 }
 
 - (void)updateEmail:(NSString *)email authToken:(NSString *)authToken {
+  NSLog(@"ReactNativeSdk updateEmail");
   [_swiftAPI updateEmail:email authToken:authToken];
 }
 
 - (void)getAttributionInfo:(RCTPromiseResolveBlock)resolve
                     reject:(RCTPromiseRejectBlock)reject {
+  NSLog(@"ReactNativeSdk getAttributionInfo");
   [_swiftAPI getAttributionInfo:resolve rejecter:reject];
 }
 
 - (void)setAttributionInfo:(NSDictionary *)attributionInfo {
+  NSLog(@"ReactNativeSdk setAttributionInfo");
   [_swiftAPI setAttributionInfo:attributionInfo];
 }
 
 - (void)disableDeviceForCurrentUser {
+  NSLog(@"ReactNativeSdk disableDeviceForCurrentUser");
   [_swiftAPI disableDeviceForCurrentUser];
 }
 
 - (void)getLastPushPayload:(RCTPromiseResolveBlock)resolve
                     reject:(RCTPromiseRejectBlock)reject {
+  NSLog(@"ReactNativeSdk getLastPushPayload");
   [_swiftAPI getLastPushPayload:resolve rejecter:reject];
 }
 
 - (void)getHtmlInAppContentForMessage:(NSString *)messageId
                               resolve:(RCTPromiseResolveBlock)resolve
                                reject:(RCTPromiseRejectBlock)reject {
+  NSLog(@"ReactNativeSdk getHtmlInAppContentForMessage");
   [_swiftAPI getHtmlInAppContentForMessage:messageId
                                   resolver:resolve
                                   rejecter:reject];
@@ -228,6 +279,7 @@ - (void)getHtmlInAppContentForMessage:(NSString *)messageId
 - (void)handleAppLink:(NSString *)appLink
               resolve:(RCTPromiseResolveBlock)resolve
                reject:(RCTPromiseRejectBlock)reject {
+  NSLog(@"ReactNativeSdk handleAppLink");
   [_swiftAPI handleAppLink:appLink resolver:resolve rejecter:reject];
 }
 
@@ -237,6 +289,7 @@ - (void)updateSubscriptions:(NSArray *)emailListIds
       subscribedMessageTypeIds:(NSArray *)subscribedMessageTypeIds
                     campaignId:(NSNumber *)campaignId
                     templateId:(NSNumber *)templateId {
+  NSLog(@"ReactNativeSdk updateSubscriptions");
   [_swiftAPI updateSubscriptions:emailListIds
           unsubscribedChannelIds:unsubscribedChannelIds
       unsubscribedMessageTypeIds:unsubscribedMessageTypeIds
@@ -246,18 +299,22 @@ - (void)updateSubscriptions:(NSArray *)emailListIds
 }
 
 - (void)startSession:(NSArray *)visibleRows {
+  NSLog(@"ReactNativeSdk startSession");
   [_swiftAPI startSession:visibleRows];
 }
 
 - (void)endSession {
+  NSLog(@"ReactNativeSdk endSession");
   [_swiftAPI endSession];
 }
 
 - (void)updateVisibleRows:(NSArray *)visibleRows {
+  NSLog(@"ReactNativeSdk updateVisibleRows");
   [_swiftAPI updateVisibleRows:visibleRows];
 }
 
 - (void)passAlongAuthToken:(NSString *)authToken {
+  NSLog(@"ReactNativeSdk passAlongAuthToken");
   [_swiftAPI passAlongAuthToken:authToken];
 }
 
@@ -265,5 +322,269 @@ - (void)passAlongAuthToken:(NSString *)authToken {
     (const facebook::react::ObjCTurboModule::InitParams &)params {
   return std::make_shared<facebook::react::NativeRNIterableAPISpecJSI>(params);
 }
+#else
+
+RCT_EXPORT_METHOD(startObserving) {
+  NSLog(@"ReactNativeSdk startObserving");
+  [(ReactIterableAPI *)_swiftAPI startObserving];
+}
+
+RCT_EXPORT_METHOD(stopObserving) {
+  NSLog(@"ReactNativeSdk stopObserving");
+  [(ReactIterableAPI *)_swiftAPI stopObserving];
+}
+
+RCT_EXPORT_METHOD(hello) {
+  NSLog(@"***ITBL OBJ-C*** hello");
+  [_swiftAPI hello];
+}
+
+RCT_EXPORT_METHOD(testEventDispatch) {
+  NSLog(@"***ITBL OBJ-C*** testEventDispatch");
+  [_swiftAPI testEventDispatch];
+}
+
+RCT_EXPORT_METHOD(
+    initializeWithApiKey : (NSString *)apiKey config : (NSDictionary *)
+        config version : (NSString *)version resolve : (RCTPromiseResolveBlock)
+            resolve reject : (RCTPromiseRejectBlock)reject) {
+  NSLog(@"ReactNativeSdk initializeWithApiKey");
+  [_swiftAPI initializeWithApiKey:apiKey
+                           config:config
+                          version:version
+                         resolver:resolve
+                         rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(
+    initialize2WithApiKey : (NSString *)apiKey config : (NSDictionary *)
+        config version : (NSString *)version apiEndPointOverride : (NSString *)
+            apiEndPointOverride resolve : (RCTPromiseResolveBlock)
+                resolve reject : (RCTPromiseRejectBlock)reject) {
+  NSLog(@"ReactNativeSdk initialize2WithApiKey");
+  [_swiftAPI initialize2WithApiKey:apiKey
+                            config:config
+               apiEndPointOverride:apiEndPointOverride
+                           version:version
+                          resolver:resolve
+                          rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(setEmail : (NSString *_Nullable)
+                      email authToken : (NSString *_Nullable)authToken) {
+  NSLog(@"ReactNativeSdk setEmail");
+  [_swiftAPI setEmail:email authToken:authToken];
+}
+
+RCT_EXPORT_METHOD(getEmail : (RCTPromiseResolveBlock)
+                      resolve reject : (RCTPromiseRejectBlock)reject) {
+  NSLog(@"ReactNativeSdk getEmail");
+  [_swiftAPI getEmail:resolve rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(setUserId : (NSString *_Nullable)
+                      userId authToken : (NSString *_Nullable)authToken) {
+  NSLog(@"ReactNativeSdk setUserId");
+  [_swiftAPI setUserId:userId authToken:authToken];
+}
+
+RCT_EXPORT_METHOD(getUserId : (RCTPromiseResolveBlock)
+                      resolve reject : (RCTPromiseRejectBlock)reject) {
+  NSLog(@"ReactNativeSdk getUserId");
+  [_swiftAPI getUserId:resolve rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(setInAppShowResponse : (NSNumber *)inAppShowResponse) {
+  NSLog(@"ReactNativeSdk setInAppShowResponse");
+  [_swiftAPI setInAppShowResponse:inAppShowResponse];
+}
+
+RCT_EXPORT_METHOD(getInAppMessages : (RCTPromiseResolveBlock)
+                      resolve reject : (RCTPromiseRejectBlock)reject) {
+  NSLog(@"ReactNativeSdk getInAppMessages");
+  [_swiftAPI getInAppMessages:resolve rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(getInboxMessages : (RCTPromiseResolveBlock)
+                      resolve reject : (RCTPromiseRejectBlock)reject) {
+  NSLog(@"ReactNativeSdk getInboxMessages");
+  [_swiftAPI getInboxMessages:resolve rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(getUnreadInboxMessagesCount : (RCTPromiseResolveBlock)
+                      resolve reject : (RCTPromiseRejectBlock)reject) {
+  NSLog(@"ReactNativeSdk getUnreadInboxMessagesCount");
+  [_swiftAPI getUnreadInboxMessagesCount:resolve rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(showMessage : (NSString *)messageId consume : (BOOL)
+                      consume resolve : (RCTPromiseResolveBlock)
+                          resolve reject : (RCTPromiseRejectBlock)reject) {
+  NSLog(@"ReactNativeSdk showMessage");
+  [_swiftAPI showMessage:messageId
+                 consume:consume
+                resolver:resolve
+                rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(removeMessage : (NSString *)messageId location : (NSNumber *)
+                      location source : (NSNumber *)source) {
+  NSLog(@"ReactNativeSdk removeMessage");
+  [_swiftAPI removeMessage:messageId location:location source:source];
+}
+
+RCT_EXPORT_METHOD(setReadForMessage : (NSString *)messageId read : (BOOL)read) {
+  NSLog(@"ReactNativeSdk setReadForMessage");
+  [_swiftAPI setReadForMessage:messageId read:read];
+}
+
+RCT_EXPORT_METHOD(setAutoDisplayPaused : (BOOL)autoDisplayPaused) {
+  NSLog(@"ReactNativeSdk setAutoDisplayPaused");
+  [_swiftAPI setAutoDisplayPaused:autoDisplayPaused];
+}
+
+RCT_EXPORT_METHOD(trackEvent : (NSString *)name dataFields : (NSDictionary *)
+                      dataFields) {
+  NSLog(@"ReactNativeSdk trackEvent");
+  [_swiftAPI trackEvent:name dataFields:dataFields];
+}
+
+RCT_EXPORT_METHOD(
+    trackPushOpenWithCampaignId : (NSNumber *)
+        campaignId templateId : (NSNumber *)templateId messageId : (NSString *)
+            messageId appAlreadyRunning : (BOOL)
+                appAlreadyRunning dataFields : (NSDictionary *)dataFields) {
+  NSLog(@"ReactNativeSdk trackPushOpenWithCampaignId");
+  [_swiftAPI trackPushOpenWithCampaignId:campaignId
+                              templateId:templateId
+                               messageId:messageId
+                       appAlreadyRunning:appAlreadyRunning
+                              dataFields:dataFields];
+}
+
+RCT_EXPORT_METHOD(trackInAppOpen : (NSString *)messageId location : (NSNumber *)
+                      location) {
+  NSLog(@"ReactNativeSdk trackInAppOpen");
+  [_swiftAPI trackInAppOpen:messageId location:location];
+}
+
+RCT_EXPORT_METHOD(trackInAppClick : (NSString *)messageId location : (
+    NSNumber *)location clickedUrl : (NSString *)clickedUrl) {
+  NSLog(@"ReactNativeSdk trackInAppClick");
+  [_swiftAPI trackInAppClick:messageId location:location clickedUrl:clickedUrl];
+}
+
+RCT_EXPORT_METHOD(trackInAppClose : (NSString *)messageId location : (
+    NSNumber *)location source : (NSNumber *)source clickedUrl : (NSString *)
+                      clickedUrl) {
+  NSLog(@"ReactNativeSdk trackInAppClose");
+  [_swiftAPI trackInAppClose:messageId
+                    location:location
+                      source:source
+                  clickedUrl:clickedUrl];
+}
+
+RCT_EXPORT_METHOD(inAppConsume : (NSString *)messageId location : (NSNumber *)
+                      location source : (NSNumber *)source) {
+  NSLog(@"ReactNativeSdk inAppConsume");
+  [_swiftAPI inAppConsume:messageId location:location source:source];
+}
+
+RCT_EXPORT_METHOD(updateCart : (NSArray *)items) {
+  NSLog(@"ReactNativeSdk updateCart");
+  [_swiftAPI updateCart:items];
+}
+
+RCT_EXPORT_METHOD(trackPurchase : (NSNumber *)total items : (NSArray *)
+                      items dataFields : (NSDictionary *)dataFields) {
+  NSLog(@"ReactNativeSdk trackPurchase");
+  [_swiftAPI trackPurchase:total items:items dataFields:dataFields];
+}
+
+RCT_EXPORT_METHOD(updateUser : (NSDictionary *)dataFields mergeNestedObjects : (
+    BOOL)mergeNestedObjects) {
+  NSLog(@"ReactNativeSdk updateUser");
+  [_swiftAPI updateUser:dataFields mergeNestedObjects:mergeNestedObjects];
+}
+RCT_EXPORT_METHOD(updateEmail : (NSString *)email authToken : (NSString *)
+                      authToken) {
+  NSLog(@"ReactNativeSdk updateEmail");
+  [_swiftAPI updateEmail:email authToken:authToken];
+}
+
+RCT_EXPORT_METHOD(getAttributionInfo : (RCTPromiseResolveBlock)
+                      resolve reject : (RCTPromiseRejectBlock)reject) {
+  NSLog(@"ReactNativeSdk getAttributionInfo");
+  [_swiftAPI getAttributionInfo:resolve rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(setAttributionInfo : (NSDictionary *)attributionInfo) {
+  NSLog(@"ReactNativeSdk setAttributionInfo");
+  [_swiftAPI setAttributionInfo:attributionInfo];
+}
+
+RCT_EXPORT_METHOD(disableDeviceForCurrentUser) {
+  NSLog(@"ReactNativeSdk disableDeviceForCurrentUser");
+  [_swiftAPI disableDeviceForCurrentUser];
+}
+
+RCT_EXPORT_METHOD(getLastPushPayload : (RCTPromiseResolveBlock)
+                      resolve reject : (RCTPromiseRejectBlock)reject) {
+  NSLog(@"ReactNativeSdk getLastPushPayload");
+  [_swiftAPI getLastPushPayload:resolve rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(getHtmlInAppContentForMessage : (NSString *)
+                      messageId resolve : (RCTPromiseResolveBlock)
+                          resolve reject : (RCTPromiseRejectBlock)reject) {
+  NSLog(@"ReactNativeSdk getHtmlInAppContentForMessage");
+  [_swiftAPI getHtmlInAppContentForMessage:messageId
+                                  resolver:resolve
+                                  rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(handleAppLink : (NSString *)appLink resolve : (
+    RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) {
+  NSLog(@"ReactNativeSdk handleAppLink");
+  [_swiftAPI handleAppLink:appLink resolver:resolve rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(
+    updateSubscriptions : (NSArray *)emailListIds unsubscribedChannelIds : (
+        NSArray *)
+        unsubscribedChannelIds unsubscribedMessageTypeIds : (NSArray *)
+            unsubscribedMessageTypeIds subscribedMessageTypeIds : (NSArray *)
+                subscribedMessageTypeIds campaignId : (NSNumber *)
+                    campaignId templateId : (NSNumber *)templateId) {
+  NSLog(@"ReactNativeSdk updateSubscriptions");
+  [_swiftAPI updateSubscriptions:emailListIds
+          unsubscribedChannelIds:unsubscribedChannelIds
+      unsubscribedMessageTypeIds:unsubscribedMessageTypeIds
+        subscribedMessageTypeIds:subscribedMessageTypeIds
+                      campaignId:campaignId
+                      templateId:templateId];
+}
+
+RCT_EXPORT_METHOD(startSession : (NSArray *)visibleRows) {
+  NSLog(@"ReactNativeSdk startSession");
+  [_swiftAPI startSession:visibleRows];
+}
+
+RCT_EXPORT_METHOD(endSession) {
+  NSLog(@"ReactNativeSdk endSession");
+  [_swiftAPI endSession];
+}
+
+RCT_EXPORT_METHOD(updateVisibleRows : (NSArray *)visibleRows) {
+  NSLog(@"ReactNativeSdk updateVisibleRows");
+  [_swiftAPI updateVisibleRows:visibleRows];
+}
+
+RCT_EXPORT_METHOD(passAlongAuthToken : (NSString *)authToken) {
+  NSLog(@"ReactNativeSdk passAlongAuthToken");
+  [_swiftAPI passAlongAuthToken:authToken];
+}
+
+#endif
 
 @end
diff --git a/ios/RNIterableAPI/ReactIterableAPI.swift b/ios/RNIterableAPI/ReactIterableAPI.swift
index 73d92a2e8..6efb2c0b4 100644
--- a/ios/RNIterableAPI/ReactIterableAPI.swift
+++ b/ios/RNIterableAPI/ReactIterableAPI.swift
@@ -11,7 +11,7 @@ import React
     NotificationCenter.default.removeObserver(self)
   }
 
-  // MARK: - React Native Functions
+  @objc public weak var delegate: ReactIterableAPIDelegate? = nil
 
   @objc override public class func moduleName() -> String! {
     return "RNIterableAPI"
@@ -21,7 +21,7 @@ import React
     _methodQueue
   }
 
-  @objc override public static func requiresMainQueueSetup() -> Bool {
+  @objc override static public func requiresMainQueueSetup() -> Bool {
     false
   }
 
@@ -33,6 +33,7 @@ import React
     case receivedIterableInboxChanged
     case handleAuthSuccessCalled
     case handleAuthFailureCalled
+    case onTestEventDispatch
   }
 
   @objc public static var supportedEvents: [String] {
@@ -53,6 +54,10 @@ import React
 
   // MARK: - Native SDK Functions
 
+  @objc public func hello() {
+    print("Hello from Swift Again")
+  }
+
   @objc(initializeWithApiKey:config:version:resolver:rejecter:)
   public func initializeWithApiKey(
     apiKey: String,
@@ -61,6 +66,7 @@ import React
     resolver: @escaping RCTPromiseResolveBlock,
     rejecter: @escaping RCTPromiseRejectBlock
   ) {
+    NSLog("initializeWithApiKey called from swift")
     ITBInfo()
 
     initialize(
@@ -94,42 +100,36 @@ import React
   @objc(setEmail:)
   public func setEmail(email: String?) {
     ITBInfo()
-
     IterableAPI.email = email
   }
 
   @objc(setEmail:authToken:)
   public func setEmail(email: String?, authToken: String?) {
     ITBInfo()
-
     IterableAPI.setEmail(email, authToken)
   }
 
   @objc(getEmail:rejecter:)
   public func getEmail(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
     ITBInfo()
-
     resolver(IterableAPI.email)
   }
 
   @objc(setUserId:)
   public func setUserId(userId: String?) {
     ITBInfo()
-
     IterableAPI.userId = userId
   }
 
   @objc(setUserId:authToken:)
   public func setUserId(userId: String?, authToken: String?) {
     ITBInfo()
-
     IterableAPI.setUserId(userId, authToken)
   }
 
   @objc(getUserId:rejecter:)
   public func getUserId(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
     ITBInfo()
-
     resolver(IterableAPI.userId)
   }
 
@@ -138,16 +138,13 @@ import React
   @objc(setInAppShowResponse:)
   public func setInAppShowResponse(inAppShowResponse number: NSNumber) {
     ITBInfo()
-
     self.inAppShowResponse = InAppShowResponse.from(number: number)
-
     inAppHandlerSemaphore.signal()
   }
 
   @objc(disableDeviceForCurrentUser)
   public func disableDeviceForCurrentUser() {
     ITBInfo()
-
     IterableAPI.disableDeviceForCurrentUser()
   }
 
@@ -155,7 +152,6 @@ import React
   public func getLastPushPayload(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock)
   {
     ITBInfo()
-
     resolver(IterableAPI.lastPushPayload)
   }
 
@@ -163,19 +159,16 @@ import React
   public func getAttributionInfo(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock)
   {
     ITBInfo()
-
     resolver(IterableAPI.attributionInfo.map(SerializationUtil.encodableToDictionary))
   }
 
   @objc(setAttributionInfo:)
   public func setAttributionInfo(attributionInfo dict: NSDictionary?) {
     ITBInfo()
-
     guard let dict = dict else {
       IterableAPI.attributionInfo = nil
       return
     }
-
     IterableAPI.attributionInfo = SerializationUtil.dictionaryToDecodable(
       dict: dict as! [AnyHashable: Any])
   }
@@ -200,20 +193,18 @@ import React
   }
 
   @objc(updateCart:)
-  public func updateCart(items: [[AnyHashable: Any]]) {  // TODO: make sure this does not break
+  public func updateCart(items: [[AnyHashable: Any]]) {
     ITBInfo()
-
     IterableAPI.updateCart(items: items.compactMap(CommerceItem.from(dict:)))
   }
 
   @objc(trackPurchase:items:dataFields:)
   public func trackPurchase(
     total: NSNumber,
-    items: [[AnyHashable: Any]],  // TODO: make sure this does not break
-    dataFields: NSDictionary?
+    items: [[AnyHashable: Any]],
+    dataFields: [AnyHashable: Any]?
   ) {
     ITBInfo()
-
     IterableAPI.track(
       purchase: total,
       items: items.compactMap(CommerceItem.from(dict:)),
@@ -226,12 +217,10 @@ import React
     location locationNumber: NSNumber
   ) {
     ITBInfo()
-
     guard let message = IterableAPI.inAppManager.getMessage(withId: messageId) else {
       ITBError("Could not find message with id: \(messageId)")
       return
     }
-
     IterableAPI.track(inAppOpen: message, location: InAppLocation.from(number: locationNumber))
   }
 
@@ -242,12 +231,10 @@ import React
     clickedUrl: String
   ) {
     ITBInfo()
-
     guard let message = IterableAPI.inAppManager.getMessage(withId: messageId) else {
       ITBError("Could not find message with id: \(messageId)")
       return
     }
-
     IterableAPI.track(
       inAppClick: message, location: InAppLocation.from(number: locationNumber),
       clickedUrl: clickedUrl)
@@ -261,12 +248,10 @@ import React
     clickedUrl: String?
   ) {
     ITBInfo()
-
     guard let message = IterableAPI.inAppManager.getMessage(withId: messageId) else {
       ITBError("Could not find message with id: \(messageId)")
       return
     }
-
     if let inAppCloseSource = InAppCloseSource.from(number: sourceNumber) {
       IterableAPI.track(
         inAppClose: message,
@@ -288,12 +273,10 @@ import React
     source sourceNumber: NSNumber
   ) {
     ITBInfo()
-
     guard let message = IterableAPI.inAppManager.getMessage(withId: messageId) else {
       ITBError("Could not find message with id: \(messageId)")
       return
     }
-
     if let inAppDeleteSource = InAppDeleteSource.from(number: sourceNumber) {
       IterableAPI.inAppConsume(
         message: message,
@@ -311,19 +294,19 @@ import React
     messageId: String, resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock
   ) {
     ITBInfo()
-
     guard let message = IterableAPI.inAppManager.getMessage(withId: messageId) else {
       ITBError("Could not find message with id: \(messageId)")
-      rejecter("", "Could not find message with id: \(messageId)", nil)
+      rejecter(
+        "", "Could not find message with id: \(messageId)",
+        NSError(domain: "", code: 0, userInfo: nil))
       return
     }
-
     guard let content = message.content as? IterableHtmlInAppContent else {
       ITBError("Could not parse message content as HTML")
-      rejecter("", "Could not parse message content as HTML", nil)
+      rejecter(
+        "", "Could not parse message content as HTML", NSError(domain: "", code: 0, userInfo: nil))
       return
     }
-
     resolver(content.toDict())
   }
 
@@ -337,15 +320,13 @@ import React
   @objc(updateUser:mergeNestedObjects:)
   public func updateUser(dataFields: NSDictionary, mergeNestedObjects: Bool) {
     ITBInfo()
-
     IterableAPI.updateUser(
-      dataFields as? [AnyHashable: Any], mergeNestedObjects: mergeNestedObjects)
+      (dataFields as? [AnyHashable: Any])!, mergeNestedObjects: mergeNestedObjects)
   }
 
   @objc(updateEmail:authToken:)
   public func updateEmail(email: String, with authToken: String?) {
     ITBInfo()
-
     if let authToken = authToken {
       IterableAPI.updateEmail(email, withToken: authToken, onSuccess: nil, onFailure: nil)
     } else {
@@ -354,15 +335,14 @@ import React
   }
 
   @objc(handleAppLink:resolver:rejecter:)
-  public func handleAppLink(
+  public func handle(
     appLink: String, resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock
   ) {
     ITBInfo()
-
     if let url = URL(string: appLink) {
       resolver(IterableAPI.handle(universalLink: url))
     } else {
-      rejecter("", "invalid URL", nil)
+      rejecter("", "invalid URL", NSError(domain: "", code: 0, userInfo: nil))
     }
   }
 
@@ -371,14 +351,12 @@ import React
   @objc(getInAppMessages:rejecter:)
   public func getInAppMessages(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
     ITBInfo()
-
     resolver(IterableAPI.inAppManager.getMessages().map { $0.toDict() })
   }
 
   @objc(getInboxMessages:rejecter:)
   public func getInboxMessages(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
     ITBInfo()
-
     resolver(IterableAPI.inAppManager.getInboxMessages().map { $0.toDict() })
   }
 
@@ -387,7 +365,6 @@ import React
     resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock
   ) {
     ITBInfo()
-
     resolver(IterableAPI.inAppManager.getUnreadInboxMessagesCount())
   }
 
@@ -397,12 +374,10 @@ import React
     rejecter: RCTPromiseRejectBlock
   ) {
     ITBInfo()
-
     guard let message = IterableAPI.inAppManager.getMessage(withId: messageId) else {
       ITBError("Could not find message with id: \(messageId)")
       return
     }
-
     IterableAPI.inAppManager.show(message: message, consume: consume) { (url) in
       resolver(url.map({ $0.absoluteString }))
     }
@@ -413,12 +388,10 @@ import React
     messageId: String, location locationNumber: NSNumber, source sourceNumber: NSNumber
   ) {
     ITBInfo()
-
     guard let message = IterableAPI.inAppManager.getMessage(withId: messageId) else {
       ITBError("Could not find message with id: \(messageId)")
       return
     }
-
     if let inAppDeleteSource = InAppDeleteSource.from(number: sourceNumber) {
       IterableAPI.inAppManager.remove(
         message: message,
@@ -444,10 +417,8 @@ import React
     templateId: NSNumber
   ) {
     ITBInfo()
-
     let finalCampaignId: NSNumber? = campaignId.intValue <= 0 ? nil : campaignId
     let finalTemplateId: NSNumber? = templateId.intValue <= 0 ? nil : templateId
-
     IterableAPI.updateSubscriptions(
       emailListIds,
       unsubscribedChannelIds: unsubscribedChannelIds,
@@ -460,19 +431,16 @@ import React
   @objc(setReadForMessage:read:)
   public func setReadForMessage(for messageId: String, read: Bool) {
     ITBInfo()
-
     guard let message = IterableAPI.inAppManager.getMessage(withId: messageId) else {
       ITBError("Could not find message with id: \(messageId)")
       return
     }
-
     IterableAPI.inAppManager.set(read: read, forMessage: message)
   }
 
   @objc(setAutoDisplayPaused:)
   public func setAutoDisplayPaused(autoDisplayPaused: Bool) {
     ITBInfo()
-
     DispatchQueue.main.async {
       IterableAPI.inAppManager.isAutoDisplayPaused = autoDisplayPaused
     }
@@ -481,9 +449,8 @@ import React
   // MARK: - SDK Inbox Session Tracking Functions
 
   @objc(startSession:)
-  public func startSession(visibleRows: [[AnyHashable: Any]]) {  // TODO: make sure this does not break
+  public func startSession(visibleRows: [[AnyHashable: Any]]) {
     let serializedRows = InboxImpressionTracker.RowInfo.rowInfos(from: visibleRows)
-
     inboxSessionManager.startSession(visibleRows: serializedRows)
   }
 
@@ -493,7 +460,6 @@ import React
       ITBError("Could not find session info")
       return
     }
-
     let inboxSession = IterableInboxSession(
       id: sessionInfo.startInfo.id,
       sessionStartTime: sessionInfo.startInfo.startTime,
@@ -503,25 +469,28 @@ import React
       endTotalMessageCount: IterableAPI.inAppManager.getInboxMessages().count,
       endUnreadMessageCount: IterableAPI.inAppManager.getUnreadInboxMessagesCount(),
       impressions: sessionInfo.impressions.map { $0.toIterableInboxImpression() })
-
     IterableAPI.track(inboxSession: inboxSession)
   }
 
   @objc(updateVisibleRows:)
-  public func updateVisibleRows(visibleRows: [[AnyHashable: Any]]) {  // TODO: make sure this does not break
+  public func updateVisibleRows(visibleRows: [[AnyHashable: Any]]) {
     let serializedRows = InboxImpressionTracker.RowInfo.rowInfos(from: visibleRows)
-
     inboxSessionManager.updateVisibleRows(visibleRows: serializedRows)
   }
 
+  @objc(testEventDispatch)
+  public func testEventDispatch() {
+    NSLog("***ITBL SWIFT*** shouldEmit: \(shouldEmit)")
+    NSLog("***ITBL SWIFT*** testEventDispatch", EventName.onTestEventDispatch.rawValue)
+    delegate?.sendEvent(withName: EventName.onTestEventDispatch.rawValue, body: 0)
+  }
+
   // MARK: - SDK Auth Manager Functions
 
   @objc(passAlongAuthToken:)
   public func passAlongAuthToken(authToken: String?) {
     ITBInfo()
-
     passedAuthToken = authToken
-
     authHandlerSemaphore.signal()
   }
 
@@ -547,7 +516,6 @@ import React
     rejecter: @escaping RCTPromiseRejectBlock
   ) {
     ITBInfo()
-
     let launchOptions = createLaunchOptions()
     let iterableConfig = IterableConfig.from(
       dict: configDict as? [AnyHashable: Any]
@@ -593,11 +561,10 @@ import React
   }
 
   @objc(receivedIterableInboxChanged)
-  public func receivedIterableInboxChanged() {
+  func receivedIterableInboxChanged() {
     guard shouldEmit else {
       return
     }
-
     delegate?.sendEvent(
       withName: EventName.receivedIterableInboxChanged.rawValue, body: nil as Any?)
   }
@@ -606,7 +573,6 @@ import React
     guard let bridge = self.bridge else {
       return nil
     }
-
     return ReactIterableAPI.createLaunchOptions(bridgeLaunchOptions: bridge.launchOptions)
   }
 
@@ -619,10 +585,8 @@ import React
     else {
       return nil
     }
-
     var result = [UIApplication.LaunchOptionsKey: Any]()
     result[UIApplication.LaunchOptionsKey.remoteNotification] = remoteNotification
-
     return result
   }
 }
@@ -630,45 +594,36 @@ import React
 extension ReactIterableAPI: IterableURLDelegate {
   public func handle(iterableURL url: URL, inContext context: IterableActionContext) -> Bool {
     ITBInfo()
-
     guard shouldEmit else {
       return false
     }
-
     let contextDict = ReactIterableAPI.contextToDictionary(context: context)
     delegate?.sendEvent(
       withName: EventName.handleUrlCalled.rawValue,
       body: [
         "url": url.absoluteString,
         "context": contextDict,
-      ] as Any?)
-
+      ] as [String: Any])
     return true
   }
 
   private static func contextToDictionary(context: IterableActionContext) -> [AnyHashable: Any] {
     var result = [AnyHashable: Any]()
-
     let actionDict = actionToDictionary(action: context.action)
     result["action"] = actionDict
     result["source"] = context.source.rawValue
-
     return result
   }
 
   private static func actionToDictionary(action: IterableAction) -> [AnyHashable: Any] {
     var actionDict = [AnyHashable: Any]()
-
     actionDict["type"] = action.type
-
     if let data = action.data {
       actionDict["data"] = data
     }
-
     if let userInput = action.userInput {
       actionDict["userInput"] = userInput
     }
-
     return actionDict
   }
 }
@@ -676,19 +631,18 @@ extension ReactIterableAPI: IterableURLDelegate {
 extension ReactIterableAPI: IterableCustomActionDelegate {
   public func handle(
     iterableCustomAction action: IterableAction, inContext context: IterableActionContext
-  ) -> Bool {
+  )
+    -> Bool
+  {
     ITBInfo()
-
     let actionDict = ReactIterableAPI.actionToDictionary(action: action)
     let contextDict = ReactIterableAPI.contextToDictionary(context: context)
-
     delegate?.sendEvent(
       withName: EventName.handleCustomActionCalled.rawValue,
       body: [
         "action": actionDict,
         "context": contextDict,
       ])
-
     return true
   }
 }
@@ -696,17 +650,13 @@ extension ReactIterableAPI: IterableCustomActionDelegate {
 extension ReactIterableAPI: IterableInAppDelegate {
   public func onNew(message: IterableInAppMessage) -> InAppShowResponse {
     ITBInfo()
-
     guard shouldEmit else {
       return .show
     }
-
     delegate?.sendEvent(
       withName: EventName.handleInAppCalled.rawValue,
       body: message.toDict())
-
     let timeoutResult = inAppHandlerSemaphore.wait(timeout: .now() + 2.0)
-
     if timeoutResult == .success {
       ITBInfo("inAppShowResponse: \(inAppShowResponse == .show)")
       return inAppShowResponse
@@ -720,31 +670,24 @@ extension ReactIterableAPI: IterableInAppDelegate {
 extension ReactIterableAPI: IterableAuthDelegate {
   public func onAuthTokenRequested(completion: @escaping AuthTokenRetrievalHandler) {
     ITBInfo()
-
     DispatchQueue.global(qos: .userInitiated).async {
       self.delegate?.sendEvent(
         withName: EventName.handleAuthCalled.rawValue,
         body: nil as Any?)
-
       let authTokenRetrievalResult = self.authHandlerSemaphore.wait(timeout: .now() + 30.0)
-
       if authTokenRetrievalResult == .success {
         ITBInfo("authTokenRetrieval successful")
-
         DispatchQueue.main.async {
           completion(self.passedAuthToken)
         }
-
         self.delegate?.sendEvent(
           withName: EventName.handleAuthSuccessCalled.rawValue,
           body: nil as Any?)
       } else {
         ITBInfo("authTokenRetrieval timed out")
-
         DispatchQueue.main.async {
           completion(nil)
         }
-
         self.delegate?.sendEvent(
           withName: EventName.handleAuthFailureCalled.rawValue,
           body: nil as Any?)
@@ -753,6 +696,5 @@ extension ReactIterableAPI: IterableAuthDelegate {
   }
 
   public func onTokenRegistrationFailed(_ reason: String?) {
-
   }
 }

From 8126d284523db5cf1369686cf87af8f3b30e381c Mon Sep 17 00:00:00 2001
From: Loren Posen <loren.posen@iterable.com>
Date: Sat, 2 Aug 2025 09:51:08 -0700
Subject: [PATCH 05/13] refactor: update RNIterableAPI.mm to improve code
 clarity and remove unnecessary logging

---
 .../project.pbxproj                           |  58 +++++-----
 ios/RNIterableAPI/RNIterableAPI.mm            | 104 +-----------------
 2 files changed, 31 insertions(+), 131 deletions(-)

diff --git a/example/ios/ReactNativeSdkExample.xcodeproj/project.pbxproj b/example/ios/ReactNativeSdkExample.xcodeproj/project.pbxproj
index c6390b76b..36dbb67d0 100644
--- a/example/ios/ReactNativeSdkExample.xcodeproj/project.pbxproj
+++ b/example/ios/ReactNativeSdkExample.xcodeproj/project.pbxproj
@@ -12,7 +12,7 @@
 		779227342DFA3FB500D69EC0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 779227332DFA3FB500D69EC0 /* AppDelegate.swift */; };
 		81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
 		A3A40C20801B8F02005FA4C0 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 1FC6B09E65A7BD9F6864C5D8 /* PrivacyInfo.xcprivacy */; };
-		D8AD8DD7C4BBDAA8AE397A1B /* libPods-ReactNativeSdkExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1BA21919EC27D7F5BAE79A81 /* libPods-ReactNativeSdkExample.a */; };
+		A6C0695C2CEB3E991B349B28 /* libPods-ReactNativeSdkExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5750A1B5F0DE8C0CA5F46AD7 /* libPods-ReactNativeSdkExample.a */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -33,15 +33,15 @@
 		13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = ReactNativeSdkExample/Images.xcassets; sourceTree = "<group>"; };
 		13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ReactNativeSdkExample/Info.plist; sourceTree = "<group>"; };
 		13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = ReactNativeSdkExample/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
-		1BA21919EC27D7F5BAE79A81 /* libPods-ReactNativeSdkExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ReactNativeSdkExample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
 		1FC6B09E65A7BD9F6864C5D8 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = ReactNativeSdkExample/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
-		24F802EFDCFB094D34916C72 /* Pods-ReactNativeSdkExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReactNativeSdkExample.release.xcconfig"; path = "Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample.release.xcconfig"; sourceTree = "<group>"; };
+		489E9B1B73890306BCD7B250 /* Pods-ReactNativeSdkExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReactNativeSdkExample.release.xcconfig"; path = "Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample.release.xcconfig"; sourceTree = "<group>"; };
+		5750A1B5F0DE8C0CA5F46AD7 /* libPods-ReactNativeSdkExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ReactNativeSdkExample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		67C6240790C3DAF138EB4ADB /* Pods-ReactNativeSdkExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReactNativeSdkExample.debug.xcconfig"; path = "Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample.debug.xcconfig"; sourceTree = "<group>"; };
 		779227312DFA3FB500D69EC0 /* ReactNativeSdkExample-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ReactNativeSdkExample-Bridging-Header.h"; sourceTree = "<group>"; };
 		779227322DFA3FB500D69EC0 /* ReactNativeSdkExampleTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ReactNativeSdkExampleTests-Bridging-Header.h"; sourceTree = "<group>"; };
 		779227332DFA3FB500D69EC0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = ReactNativeSdkExample/AppDelegate.swift; sourceTree = "<group>"; };
 		81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = ReactNativeSdkExample/LaunchScreen.storyboard; sourceTree = "<group>"; };
 		ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
-		EDCEA27594161CE66029771A /* Pods-ReactNativeSdkExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReactNativeSdkExample.debug.xcconfig"; path = "Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample.debug.xcconfig"; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -56,7 +56,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				D8AD8DD7C4BBDAA8AE397A1B /* libPods-ReactNativeSdkExample.a in Frameworks */,
+				A6C0695C2CEB3E991B349B28 /* libPods-ReactNativeSdkExample.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -99,7 +99,7 @@
 			isa = PBXGroup;
 			children = (
 				ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
-				1BA21919EC27D7F5BAE79A81 /* libPods-ReactNativeSdkExample.a */,
+				5750A1B5F0DE8C0CA5F46AD7 /* libPods-ReactNativeSdkExample.a */,
 			);
 			name = Frameworks;
 			sourceTree = "<group>";
@@ -138,8 +138,8 @@
 		BBD78D7AC51CEA395F1C20DB /* Pods */ = {
 			isa = PBXGroup;
 			children = (
-				EDCEA27594161CE66029771A /* Pods-ReactNativeSdkExample.debug.xcconfig */,
-				24F802EFDCFB094D34916C72 /* Pods-ReactNativeSdkExample.release.xcconfig */,
+				67C6240790C3DAF138EB4ADB /* Pods-ReactNativeSdkExample.debug.xcconfig */,
+				489E9B1B73890306BCD7B250 /* Pods-ReactNativeSdkExample.release.xcconfig */,
 			);
 			path = Pods;
 			sourceTree = "<group>";
@@ -169,13 +169,13 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ReactNativeSdkExample" */;
 			buildPhases = (
-				F706883CA13F4E50A06B85B2 /* [CP] Check Pods Manifest.lock */,
+				39F16507F41D7B65C4BB2AFA /* [CP] Check Pods Manifest.lock */,
 				13B07F871A680F5B00A75B9A /* Sources */,
 				13B07F8C1A680F5B00A75B9A /* Frameworks */,
 				13B07F8E1A680F5B00A75B9A /* Resources */,
 				00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
-				2128D4591E26BD193F1293F1 /* [CP] Embed Pods Frameworks */,
-				BBD6908F2EAA6D3A6C078EA9 /* [CP] Copy Pods Resources */,
+				9BCDAF1ED4681299F154EB0B /* [CP] Embed Pods Frameworks */,
+				577CB6D19BA58383681D2C91 /* [CP] Copy Pods Resources */,
 			);
 			buildRules = (
 			);
@@ -260,24 +260,29 @@
 			shellPath = /bin/sh;
 			shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n";
 		};
-		2128D4591E26BD193F1293F1 /* [CP] Embed Pods Frameworks */ = {
+		39F16507F41D7B65C4BB2AFA /* [CP] Check Pods Manifest.lock */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample-frameworks-${CONFIGURATION}-input-files.xcfilelist",
 			);
-			name = "[CP] Embed Pods Frameworks";
+			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
+			);
+			name = "[CP] Check Pods Manifest.lock";
 			outputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+			);
+			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-ReactNativeSdkExample-checkManifestLockResult.txt",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample-frameworks.sh\"\n";
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
 			showEnvVarsInLog = 0;
 		};
-		BBD6908F2EAA6D3A6C078EA9 /* [CP] Copy Pods Resources */ = {
+		577CB6D19BA58383681D2C91 /* [CP] Copy Pods Resources */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
@@ -294,26 +299,21 @@
 			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample-resources.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
-		F706883CA13F4E50A06B85B2 /* [CP] Check Pods Manifest.lock */ = {
+		9BCDAF1ED4681299F154EB0B /* [CP] Embed Pods Frameworks */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample-frameworks-${CONFIGURATION}-input-files.xcfilelist",
 			);
-			inputPaths = (
-				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
-				"${PODS_ROOT}/Manifest.lock",
-			);
-			name = "[CP] Check Pods Manifest.lock";
+			name = "[CP] Embed Pods Frameworks";
 			outputFileListPaths = (
-			);
-			outputPaths = (
-				"$(DERIVED_FILE_DIR)/Pods-ReactNativeSdkExample-checkManifestLockResult.txt",
+				"${PODS_ROOT}/Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample-frameworks-${CONFIGURATION}-output-files.xcfilelist",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample-frameworks.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
 /* End PBXShellScriptBuildPhase section */
@@ -406,7 +406,7 @@
 		};
 		13B07F941A680F5B00A75B9A /* Debug */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = EDCEA27594161CE66029771A /* Pods-ReactNativeSdkExample.debug.xcconfig */;
+			baseConfigurationReference = 67C6240790C3DAF138EB4ADB /* Pods-ReactNativeSdkExample.debug.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
@@ -436,7 +436,7 @@
 		};
 		13B07F951A680F5B00A75B9A /* Release */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = 24F802EFDCFB094D34916C72 /* Pods-ReactNativeSdkExample.release.xcconfig */;
+			baseConfigurationReference = 489E9B1B73890306BCD7B250 /* Pods-ReactNativeSdkExample.release.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
diff --git a/ios/RNIterableAPI/RNIterableAPI.mm b/ios/RNIterableAPI/RNIterableAPI.mm
index dc877ba89..e7466767a 100644
--- a/ios/RNIterableAPI/RNIterableAPI.mm
+++ b/ios/RNIterableAPI/RNIterableAPI.mm
@@ -28,7 +28,7 @@ @implementation RNIterableAPI {
 - (instancetype)init {
   self = [super init];
   if(self) {
-    // Option 2.B - Instantiate the Calculator and set the delegate
+    // Instantiate the ReactIterableAPI and set the delegate
     _swiftAPI = [ReactIterableAPI new];
     _swiftAPI.delegate = self;
   }
@@ -37,10 +37,6 @@ - (instancetype)init {
 
 RCT_EXPORT_MODULE()
 
-// - (NSArray<NSString *> *)supportedEvents {
-//   return [_swiftAPI supportedEvents];
-// }
-
 - (NSArray<NSString *> *)supportedEvents {
   return [ReactIterableAPI supportedEvents];
 }
@@ -51,31 +47,18 @@ - (void)sendEventWithName:(NSString *_Nonnull)name result:(double)result {
 
 #if RCT_NEW_ARCH_ENABLED
 - (void)startObserving {
-  NSLog(@"ReactNativeSdk startObserving");
   [(ReactIterableAPI *)_swiftAPI startObserving];
 }
 
 - (void)stopObserving {
-  NSLog(@"ReactNativeSdk stopObserving");
   [(ReactIterableAPI *)_swiftAPI stopObserving];
 }
 
-- (void)hello {
-  NSLog(@"Hello from Objective-C");
-  [(ReactIterableAPI *)_swiftAPI hello];
-}
-
-- (void)testEventDispatch {
-  NSLog(@"***ITBL OBJ-C*** testEventDispatch");
-  [_swiftAPI testEventDispatch];
-}
-
 - (void)initializeWithApiKey:(NSString *)apiKey
                       config:(NSDictionary *)config
                      version:(NSString *)version
                      resolve:(RCTPromiseResolveBlock)resolve
                       reject:(RCTPromiseRejectBlock)reject {
-  NSLog(@"ReactNativeSdk initializeWithApiKey");
   [_swiftAPI initializeWithApiKey:apiKey
                            config:config
                           version:version
@@ -89,7 +72,6 @@ - (void)initialize2WithApiKey:(NSString *)apiKey
           apiEndPointOverride:(NSString *)apiEndPointOverride
                       resolve:(RCTPromiseResolveBlock)resolve
                        reject:(RCTPromiseRejectBlock)reject {
-  NSLog(@"ReactNativeSdk initialize2WithApiKey");
   [_swiftAPI initialize2WithApiKey:apiKey
                             config:config
                apiEndPointOverride:apiEndPointOverride
@@ -100,49 +82,41 @@ - (void)initialize2WithApiKey:(NSString *)apiKey
 
 - (void)setEmail:(NSString *_Nullable)email
        authToken:(NSString *_Nullable)authToken {
-  NSLog(@"ReactNativeSdk setEmail");
   [_swiftAPI setEmail:email authToken:authToken];
 }
 
 - (void)getEmail:(RCTPromiseResolveBlock)resolve
           reject:(RCTPromiseRejectBlock)reject {
-  NSLog(@"ReactNativeSdk getEmail");
   [_swiftAPI getEmail:resolve rejecter:reject];
 }
 
 - (void)setUserId:(NSString *_Nullable)userId
         authToken:(NSString *_Nullable)authToken {
-  NSLog(@"ReactNativeSdk setUserId");
   [_swiftAPI setUserId:userId authToken:authToken];
 }
 
 - (void)getUserId:(RCTPromiseResolveBlock)resolve
            reject:(RCTPromiseRejectBlock)reject {
-  NSLog(@"ReactNativeSdk getUserId");
   [_swiftAPI getUserId:resolve rejecter:reject];
 }
 
 - (void)setInAppShowResponse:(NSNumber *)inAppShowResponse {
-  NSLog(@"ReactNativeSdk setInAppShowResponse");
   [_swiftAPI setInAppShowResponse:inAppShowResponse];
 }
 
 - (void)getInAppMessages:(RCTPromiseResolveBlock)resolve
                   reject:(RCTPromiseRejectBlock)reject {
-  NSLog(@"ReactNativeSdk getInAppMessages");
   [_swiftAPI getInAppMessages:resolve rejecter:reject];
 }
 
 - (void)getInboxMessages:(RCTPromiseResolveBlock)resolve
                   reject:(RCTPromiseRejectBlock)reject {
-  NSLog(@"ReactNativeSdk getInboxMessages");
   [_swiftAPI getInboxMessages:resolve rejecter:reject];
 }
 
 // NOTE: This is not used anywhere on the JS side.
 - (void)getUnreadInboxMessagesCount:(RCTPromiseResolveBlock)resolve
                              reject:(RCTPromiseRejectBlock)reject {
-  NSLog(@"ReactNativeSdk getUnreadInboxMessagesCount");
   [_swiftAPI getUnreadInboxMessagesCount:resolve rejecter:reject];
 }
 
@@ -150,7 +124,6 @@ - (void)showMessage:(NSString *)messageId
             consume:(BOOL)consume
             resolve:(RCTPromiseResolveBlock)resolve
              reject:(RCTPromiseRejectBlock)reject {
-  NSLog(@"ReactNativeSdk showMessage");
   [_swiftAPI showMessage:messageId
                  consume:consume
                 resolver:resolve
@@ -160,22 +133,18 @@ - (void)showMessage:(NSString *)messageId
 - (void)removeMessage:(NSString *)messageId
              location:(NSNumber *)location
                source:(NSNumber *)source {
-  NSLog(@"ReactNativeSdk removeMessage");
   [_swiftAPI removeMessage:messageId location:location source:source];
 }
 
 - (void)setReadForMessage:(NSString *)messageId read:(BOOL)read {
-  NSLog(@"ReactNativeSdk setReadForMessage");
   [_swiftAPI setReadForMessage:messageId read:read];
 }
 
 - (void)setAutoDisplayPaused:(BOOL)autoDisplayPaused {
-  NSLog(@"ReactNativeSdk setAutoDisplayPaused");
   [_swiftAPI setAutoDisplayPaused:autoDisplayPaused];
 }
 
 - (void)trackEvent:(NSString *)name dataFields:(NSDictionary *)dataFields {
-  NSLog(@"ReactNativeSdk trackEvent");
   [_swiftAPI trackEvent:name dataFields:dataFields];
 }
 
@@ -184,7 +153,6 @@ - (void)trackPushOpenWithCampaignId:(NSNumber *)campaignId
                           messageId:(NSString *)messageId
                   appAlreadyRunning:(BOOL)appAlreadyRunning
                          dataFields:(NSDictionary *)dataFields {
-  NSLog(@"ReactNativeSdk trackPushOpenWithCampaignId");
   [_swiftAPI trackPushOpenWithCampaignId:campaignId
                               templateId:templateId
                                messageId:messageId
@@ -193,14 +161,12 @@ - (void)trackPushOpenWithCampaignId:(NSNumber *)campaignId
 }
 
 - (void)trackInAppOpen:(NSString *)messageId location:(NSNumber *)location {
-  NSLog(@"ReactNativeSdk trackInAppOpen");
   [_swiftAPI trackInAppOpen:messageId location:location];
 }
 
 - (void)trackInAppClick:(NSString *)messageId
                location:(NSNumber *)location
              clickedUrl:(NSString *)clickedUrl {
-  NSLog(@"ReactNativeSdk trackInAppClick");
   [_swiftAPI trackInAppClick:messageId location:location clickedUrl:clickedUrl];
 }
 
@@ -208,7 +174,6 @@ - (void)trackInAppClose:(NSString *)messageId
                location:(NSNumber *)location
                  source:(NSNumber *)source
              clickedUrl:(NSString *)clickedUrl {
-  NSLog(@"ReactNativeSdk trackInAppClose");
   [_swiftAPI trackInAppClose:messageId
                     location:location
                       source:source
@@ -218,59 +183,49 @@ - (void)trackInAppClose:(NSString *)messageId
 - (void)inAppConsume:(NSString *)messageId
             location:(NSNumber *)location
               source:(NSNumber *)source {
-  NSLog(@"ReactNativeSdk inAppConsume");
   [_swiftAPI inAppConsume:messageId location:location source:source];
 }
 
 - (void)updateCart:(NSArray *)items {
-  NSLog(@"ReactNativeSdk updateCart");
   [_swiftAPI updateCart:items];
 }
 
 - (void)trackPurchase:(NSNumber *)total
                 items:(NSArray *)items
            dataFields:(NSDictionary *)dataFields {
-  NSLog(@"ReactNativeSdk trackPurchase");
   [_swiftAPI trackPurchase:total items:items dataFields:dataFields];
 }
 
 - (void)updateUser:(NSDictionary *)dataFields
     mergeNestedObjects:(BOOL)mergeNestedObjects {
-  NSLog(@"ReactNativeSdk updateUser");
   [_swiftAPI updateUser:dataFields mergeNestedObjects:mergeNestedObjects];
 }
 
 - (void)updateEmail:(NSString *)email authToken:(NSString *)authToken {
-  NSLog(@"ReactNativeSdk updateEmail");
   [_swiftAPI updateEmail:email authToken:authToken];
 }
 
 - (void)getAttributionInfo:(RCTPromiseResolveBlock)resolve
                     reject:(RCTPromiseRejectBlock)reject {
-  NSLog(@"ReactNativeSdk getAttributionInfo");
   [_swiftAPI getAttributionInfo:resolve rejecter:reject];
 }
 
 - (void)setAttributionInfo:(NSDictionary *)attributionInfo {
-  NSLog(@"ReactNativeSdk setAttributionInfo");
   [_swiftAPI setAttributionInfo:attributionInfo];
 }
 
 - (void)disableDeviceForCurrentUser {
-  NSLog(@"ReactNativeSdk disableDeviceForCurrentUser");
   [_swiftAPI disableDeviceForCurrentUser];
 }
 
 - (void)getLastPushPayload:(RCTPromiseResolveBlock)resolve
                     reject:(RCTPromiseRejectBlock)reject {
-  NSLog(@"ReactNativeSdk getLastPushPayload");
   [_swiftAPI getLastPushPayload:resolve rejecter:reject];
 }
 
 - (void)getHtmlInAppContentForMessage:(NSString *)messageId
                               resolve:(RCTPromiseResolveBlock)resolve
                                reject:(RCTPromiseRejectBlock)reject {
-  NSLog(@"ReactNativeSdk getHtmlInAppContentForMessage");
   [_swiftAPI getHtmlInAppContentForMessage:messageId
                                   resolver:resolve
                                   rejecter:reject];
@@ -279,7 +234,6 @@ - (void)getHtmlInAppContentForMessage:(NSString *)messageId
 - (void)handleAppLink:(NSString *)appLink
               resolve:(RCTPromiseResolveBlock)resolve
                reject:(RCTPromiseRejectBlock)reject {
-  NSLog(@"ReactNativeSdk handleAppLink");
   [_swiftAPI handleAppLink:appLink resolver:resolve rejecter:reject];
 }
 
@@ -289,7 +243,6 @@ - (void)updateSubscriptions:(NSArray *)emailListIds
       subscribedMessageTypeIds:(NSArray *)subscribedMessageTypeIds
                     campaignId:(NSNumber *)campaignId
                     templateId:(NSNumber *)templateId {
-  NSLog(@"ReactNativeSdk updateSubscriptions");
   [_swiftAPI updateSubscriptions:emailListIds
           unsubscribedChannelIds:unsubscribedChannelIds
       unsubscribedMessageTypeIds:unsubscribedMessageTypeIds
@@ -299,22 +252,18 @@ - (void)updateSubscriptions:(NSArray *)emailListIds
 }
 
 - (void)startSession:(NSArray *)visibleRows {
-  NSLog(@"ReactNativeSdk startSession");
   [_swiftAPI startSession:visibleRows];
 }
 
 - (void)endSession {
-  NSLog(@"ReactNativeSdk endSession");
   [_swiftAPI endSession];
 }
 
 - (void)updateVisibleRows:(NSArray *)visibleRows {
-  NSLog(@"ReactNativeSdk updateVisibleRows");
   [_swiftAPI updateVisibleRows:visibleRows];
 }
 
 - (void)passAlongAuthToken:(NSString *)authToken {
-  NSLog(@"ReactNativeSdk passAlongAuthToken");
   [_swiftAPI passAlongAuthToken:authToken];
 }
 
@@ -325,30 +274,17 @@ - (void)passAlongAuthToken:(NSString *)authToken {
 #else
 
 RCT_EXPORT_METHOD(startObserving) {
-  NSLog(@"ReactNativeSdk startObserving");
   [(ReactIterableAPI *)_swiftAPI startObserving];
 }
 
 RCT_EXPORT_METHOD(stopObserving) {
-  NSLog(@"ReactNativeSdk stopObserving");
   [(ReactIterableAPI *)_swiftAPI stopObserving];
 }
 
-RCT_EXPORT_METHOD(hello) {
-  NSLog(@"***ITBL OBJ-C*** hello");
-  [_swiftAPI hello];
-}
-
-RCT_EXPORT_METHOD(testEventDispatch) {
-  NSLog(@"***ITBL OBJ-C*** testEventDispatch");
-  [_swiftAPI testEventDispatch];
-}
-
 RCT_EXPORT_METHOD(
     initializeWithApiKey : (NSString *)apiKey config : (NSDictionary *)
         config version : (NSString *)version resolve : (RCTPromiseResolveBlock)
             resolve reject : (RCTPromiseRejectBlock)reject) {
-  NSLog(@"ReactNativeSdk initializeWithApiKey");
   [_swiftAPI initializeWithApiKey:apiKey
                            config:config
                           version:version
@@ -361,7 +297,6 @@ - (void)passAlongAuthToken:(NSString *)authToken {
         config version : (NSString *)version apiEndPointOverride : (NSString *)
             apiEndPointOverride resolve : (RCTPromiseResolveBlock)
                 resolve reject : (RCTPromiseRejectBlock)reject) {
-  NSLog(@"ReactNativeSdk initialize2WithApiKey");
   [_swiftAPI initialize2WithApiKey:apiKey
                             config:config
                apiEndPointOverride:apiEndPointOverride
@@ -372,55 +307,46 @@ - (void)passAlongAuthToken:(NSString *)authToken {
 
 RCT_EXPORT_METHOD(setEmail : (NSString *_Nullable)
                       email authToken : (NSString *_Nullable)authToken) {
-  NSLog(@"ReactNativeSdk setEmail");
   [_swiftAPI setEmail:email authToken:authToken];
 }
 
 RCT_EXPORT_METHOD(getEmail : (RCTPromiseResolveBlock)
                       resolve reject : (RCTPromiseRejectBlock)reject) {
-  NSLog(@"ReactNativeSdk getEmail");
   [_swiftAPI getEmail:resolve rejecter:reject];
 }
 
 RCT_EXPORT_METHOD(setUserId : (NSString *_Nullable)
                       userId authToken : (NSString *_Nullable)authToken) {
-  NSLog(@"ReactNativeSdk setUserId");
   [_swiftAPI setUserId:userId authToken:authToken];
 }
 
 RCT_EXPORT_METHOD(getUserId : (RCTPromiseResolveBlock)
                       resolve reject : (RCTPromiseRejectBlock)reject) {
-  NSLog(@"ReactNativeSdk getUserId");
   [_swiftAPI getUserId:resolve rejecter:reject];
 }
 
 RCT_EXPORT_METHOD(setInAppShowResponse : (NSNumber *)inAppShowResponse) {
-  NSLog(@"ReactNativeSdk setInAppShowResponse");
   [_swiftAPI setInAppShowResponse:inAppShowResponse];
 }
 
 RCT_EXPORT_METHOD(getInAppMessages : (RCTPromiseResolveBlock)
                       resolve reject : (RCTPromiseRejectBlock)reject) {
-  NSLog(@"ReactNativeSdk getInAppMessages");
   [_swiftAPI getInAppMessages:resolve rejecter:reject];
 }
 
 RCT_EXPORT_METHOD(getInboxMessages : (RCTPromiseResolveBlock)
                       resolve reject : (RCTPromiseRejectBlock)reject) {
-  NSLog(@"ReactNativeSdk getInboxMessages");
   [_swiftAPI getInboxMessages:resolve rejecter:reject];
 }
 
 RCT_EXPORT_METHOD(getUnreadInboxMessagesCount : (RCTPromiseResolveBlock)
                       resolve reject : (RCTPromiseRejectBlock)reject) {
-  NSLog(@"ReactNativeSdk getUnreadInboxMessagesCount");
   [_swiftAPI getUnreadInboxMessagesCount:resolve rejecter:reject];
 }
 
 RCT_EXPORT_METHOD(showMessage : (NSString *)messageId consume : (BOOL)
                       consume resolve : (RCTPromiseResolveBlock)
                           resolve reject : (RCTPromiseRejectBlock)reject) {
-  NSLog(@"ReactNativeSdk showMessage");
   [_swiftAPI showMessage:messageId
                  consume:consume
                 resolver:resolve
@@ -429,23 +355,19 @@ - (void)passAlongAuthToken:(NSString *)authToken {
 
 RCT_EXPORT_METHOD(removeMessage : (NSString *)messageId location : (NSNumber *)
                       location source : (NSNumber *)source) {
-  NSLog(@"ReactNativeSdk removeMessage");
   [_swiftAPI removeMessage:messageId location:location source:source];
 }
 
 RCT_EXPORT_METHOD(setReadForMessage : (NSString *)messageId read : (BOOL)read) {
-  NSLog(@"ReactNativeSdk setReadForMessage");
   [_swiftAPI setReadForMessage:messageId read:read];
 }
 
 RCT_EXPORT_METHOD(setAutoDisplayPaused : (BOOL)autoDisplayPaused) {
-  NSLog(@"ReactNativeSdk setAutoDisplayPaused");
   [_swiftAPI setAutoDisplayPaused:autoDisplayPaused];
 }
 
 RCT_EXPORT_METHOD(trackEvent : (NSString *)name dataFields : (NSDictionary *)
                       dataFields) {
-  NSLog(@"ReactNativeSdk trackEvent");
   [_swiftAPI trackEvent:name dataFields:dataFields];
 }
 
@@ -454,7 +376,6 @@ - (void)passAlongAuthToken:(NSString *)authToken {
         campaignId templateId : (NSNumber *)templateId messageId : (NSString *)
             messageId appAlreadyRunning : (BOOL)
                 appAlreadyRunning dataFields : (NSDictionary *)dataFields) {
-  NSLog(@"ReactNativeSdk trackPushOpenWithCampaignId");
   [_swiftAPI trackPushOpenWithCampaignId:campaignId
                               templateId:templateId
                                messageId:messageId
@@ -464,20 +385,17 @@ - (void)passAlongAuthToken:(NSString *)authToken {
 
 RCT_EXPORT_METHOD(trackInAppOpen : (NSString *)messageId location : (NSNumber *)
                       location) {
-  NSLog(@"ReactNativeSdk trackInAppOpen");
   [_swiftAPI trackInAppOpen:messageId location:location];
 }
 
 RCT_EXPORT_METHOD(trackInAppClick : (NSString *)messageId location : (
     NSNumber *)location clickedUrl : (NSString *)clickedUrl) {
-  NSLog(@"ReactNativeSdk trackInAppClick");
   [_swiftAPI trackInAppClick:messageId location:location clickedUrl:clickedUrl];
 }
 
 RCT_EXPORT_METHOD(trackInAppClose : (NSString *)messageId location : (
     NSNumber *)location source : (NSNumber *)source clickedUrl : (NSString *)
                       clickedUrl) {
-  NSLog(@"ReactNativeSdk trackInAppClose");
   [_swiftAPI trackInAppClose:messageId
                     location:location
                       source:source
@@ -486,58 +404,48 @@ - (void)passAlongAuthToken:(NSString *)authToken {
 
 RCT_EXPORT_METHOD(inAppConsume : (NSString *)messageId location : (NSNumber *)
                       location source : (NSNumber *)source) {
-  NSLog(@"ReactNativeSdk inAppConsume");
   [_swiftAPI inAppConsume:messageId location:location source:source];
 }
 
 RCT_EXPORT_METHOD(updateCart : (NSArray *)items) {
-  NSLog(@"ReactNativeSdk updateCart");
   [_swiftAPI updateCart:items];
 }
 
 RCT_EXPORT_METHOD(trackPurchase : (NSNumber *)total items : (NSArray *)
                       items dataFields : (NSDictionary *)dataFields) {
-  NSLog(@"ReactNativeSdk trackPurchase");
   [_swiftAPI trackPurchase:total items:items dataFields:dataFields];
 }
 
 RCT_EXPORT_METHOD(updateUser : (NSDictionary *)dataFields mergeNestedObjects : (
     BOOL)mergeNestedObjects) {
-  NSLog(@"ReactNativeSdk updateUser");
   [_swiftAPI updateUser:dataFields mergeNestedObjects:mergeNestedObjects];
 }
 RCT_EXPORT_METHOD(updateEmail : (NSString *)email authToken : (NSString *)
                       authToken) {
-  NSLog(@"ReactNativeSdk updateEmail");
   [_swiftAPI updateEmail:email authToken:authToken];
 }
 
 RCT_EXPORT_METHOD(getAttributionInfo : (RCTPromiseResolveBlock)
                       resolve reject : (RCTPromiseRejectBlock)reject) {
-  NSLog(@"ReactNativeSdk getAttributionInfo");
   [_swiftAPI getAttributionInfo:resolve rejecter:reject];
 }
 
 RCT_EXPORT_METHOD(setAttributionInfo : (NSDictionary *)attributionInfo) {
-  NSLog(@"ReactNativeSdk setAttributionInfo");
   [_swiftAPI setAttributionInfo:attributionInfo];
 }
 
 RCT_EXPORT_METHOD(disableDeviceForCurrentUser) {
-  NSLog(@"ReactNativeSdk disableDeviceForCurrentUser");
   [_swiftAPI disableDeviceForCurrentUser];
 }
 
 RCT_EXPORT_METHOD(getLastPushPayload : (RCTPromiseResolveBlock)
                       resolve reject : (RCTPromiseRejectBlock)reject) {
-  NSLog(@"ReactNativeSdk getLastPushPayload");
   [_swiftAPI getLastPushPayload:resolve rejecter:reject];
 }
 
 RCT_EXPORT_METHOD(getHtmlInAppContentForMessage : (NSString *)
                       messageId resolve : (RCTPromiseResolveBlock)
                           resolve reject : (RCTPromiseRejectBlock)reject) {
-  NSLog(@"ReactNativeSdk getHtmlInAppContentForMessage");
   [_swiftAPI getHtmlInAppContentForMessage:messageId
                                   resolver:resolve
                                   rejecter:reject];
@@ -545,7 +453,6 @@ - (void)passAlongAuthToken:(NSString *)authToken {
 
 RCT_EXPORT_METHOD(handleAppLink : (NSString *)appLink resolve : (
     RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) {
-  NSLog(@"ReactNativeSdk handleAppLink");
   [_swiftAPI handleAppLink:appLink resolver:resolve rejecter:reject];
 }
 
@@ -556,7 +463,6 @@ - (void)passAlongAuthToken:(NSString *)authToken {
             unsubscribedMessageTypeIds subscribedMessageTypeIds : (NSArray *)
                 subscribedMessageTypeIds campaignId : (NSNumber *)
                     campaignId templateId : (NSNumber *)templateId) {
-  NSLog(@"ReactNativeSdk updateSubscriptions");
   [_swiftAPI updateSubscriptions:emailListIds
           unsubscribedChannelIds:unsubscribedChannelIds
       unsubscribedMessageTypeIds:unsubscribedMessageTypeIds
@@ -566,22 +472,16 @@ - (void)passAlongAuthToken:(NSString *)authToken {
 }
 
 RCT_EXPORT_METHOD(startSession : (NSArray *)visibleRows) {
-  NSLog(@"ReactNativeSdk startSession");
   [_swiftAPI startSession:visibleRows];
 }
 
-RCT_EXPORT_METHOD(endSession) {
-  NSLog(@"ReactNativeSdk endSession");
-  [_swiftAPI endSession];
-}
+RCT_EXPORT_METHOD(endSession) { [_swiftAPI endSession]; }
 
 RCT_EXPORT_METHOD(updateVisibleRows : (NSArray *)visibleRows) {
-  NSLog(@"ReactNativeSdk updateVisibleRows");
   [_swiftAPI updateVisibleRows:visibleRows];
 }
 
 RCT_EXPORT_METHOD(passAlongAuthToken : (NSString *)authToken) {
-  NSLog(@"ReactNativeSdk passAlongAuthToken");
   [_swiftAPI passAlongAuthToken:authToken];
 }
 

From 5f8fd9ffc27af83710dd1c0b5224b4f893046b29 Mon Sep 17 00:00:00 2001
From: Loren Posen <loren.posen@iterable.com>
Date: Sat, 2 Aug 2025 09:58:45 -0700
Subject: [PATCH 06/13] refactor: remove legacy architecture code to reduce PR
 bloat

---
 ios/RNIterableAPI/RNIterableAPI.h  |  18 +--
 ios/RNIterableAPI/RNIterableAPI.mm | 231 +----------------------------
 2 files changed, 12 insertions(+), 237 deletions(-)

diff --git a/ios/RNIterableAPI/RNIterableAPI.h b/ios/RNIterableAPI/RNIterableAPI.h
index b7eabdf33..7a5b20833 100644
--- a/ios/RNIterableAPI/RNIterableAPI.h
+++ b/ios/RNIterableAPI/RNIterableAPI.h
@@ -1,20 +1,10 @@
 #import <Foundation/Foundation.h>
 #import <React/RCTEventEmitter.h>
-
-#if RCT_NEW_ARCH_ENABLED
-
-  #import <React/RCTUtils.h>
-  #import <React/RCTConvert.h>
-  #import <React/RCTTurboModuleRegistry.h>
-  #import <RNIterableAPISpec/RNIterableAPISpec.h>
+#import <React/RCTUtils.h>
+#import <React/RCTConvert.h>
+#import <React/RCTTurboModuleRegistry.h>
+#import <RNIterableAPISpec/RNIterableAPISpec.h>
 
 @interface RNIterableAPI : RCTEventEmitter <NativeRNIterableAPISpec>
 
-#else
-
-  #import <React/RCTBridgeModule.h>
-@interface RNIterableAPI : RCTEventEmitter <RCTBridgeModule>
-
-#endif
-
 @end
diff --git a/ios/RNIterableAPI/RNIterableAPI.mm b/ios/RNIterableAPI/RNIterableAPI.mm
index e7466767a..16707c506 100644
--- a/ios/RNIterableAPI/RNIterableAPI.mm
+++ b/ios/RNIterableAPI/RNIterableAPI.mm
@@ -1,12 +1,9 @@
 #import "RNIterableAPI.h"
+#import "RNIterableAPISpec.h"
+#import <IterableSDK/IterableSDK.h>
 
-#if RCT_NEW_ARCH_ENABLED
-  #import "RNIterableAPISpec.h"
-#endif
-
-#import <IterableSDK/IterableSDK.h> // umbrella (Objective-C) header
-
-// Forward-declare the Swift protocols/enum used in the Swift header.
+// Forward-declare the Swift protocols/enum used in the Swift header
+// to avoid compiler errors.
 @protocol IterableInAppDelegate;
 @protocol IterableCustomActionDelegate;
 @protocol IterableAuthDelegate;
@@ -25,6 +22,7 @@ @implementation RNIterableAPI {
   ReactIterableAPI *_swiftAPI;
 }
 
+// MARK: - Initialization
 - (instancetype)init {
   self = [super init];
   if(self) {
@@ -37,6 +35,7 @@ - (instancetype)init {
 
 RCT_EXPORT_MODULE()
 
+// MARK: - RCTEventEmitter functions
 - (NSArray<NSString *> *)supportedEvents {
   return [ReactIterableAPI supportedEvents];
 }
@@ -45,7 +44,6 @@ - (void)sendEventWithName:(NSString *_Nonnull)name result:(double)result {
   [self sendEventWithName:name body:@(result)];
 }
 
-#if RCT_NEW_ARCH_ENABLED
 - (void)startObserving {
   [(ReactIterableAPI *)_swiftAPI startObserving];
 }
@@ -54,6 +52,7 @@ - (void)stopObserving {
   [(ReactIterableAPI *)_swiftAPI stopObserving];
 }
 
+// MARK: - RNIterableAPI functions exposed to JS
 - (void)initializeWithApiKey:(NSString *)apiKey
                       config:(NSDictionary *)config
                      version:(NSString *)version
@@ -267,224 +266,10 @@ - (void)passAlongAuthToken:(NSString *)authToken {
   [_swiftAPI passAlongAuthToken:authToken];
 }
 
+// MARK: - TurboModule integration
 - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
     (const facebook::react::ObjCTurboModule::InitParams &)params {
   return std::make_shared<facebook::react::NativeRNIterableAPISpecJSI>(params);
 }
-#else
-
-RCT_EXPORT_METHOD(startObserving) {
-  [(ReactIterableAPI *)_swiftAPI startObserving];
-}
-
-RCT_EXPORT_METHOD(stopObserving) {
-  [(ReactIterableAPI *)_swiftAPI stopObserving];
-}
-
-RCT_EXPORT_METHOD(
-    initializeWithApiKey : (NSString *)apiKey config : (NSDictionary *)
-        config version : (NSString *)version resolve : (RCTPromiseResolveBlock)
-            resolve reject : (RCTPromiseRejectBlock)reject) {
-  [_swiftAPI initializeWithApiKey:apiKey
-                           config:config
-                          version:version
-                         resolver:resolve
-                         rejecter:reject];
-}
-
-RCT_EXPORT_METHOD(
-    initialize2WithApiKey : (NSString *)apiKey config : (NSDictionary *)
-        config version : (NSString *)version apiEndPointOverride : (NSString *)
-            apiEndPointOverride resolve : (RCTPromiseResolveBlock)
-                resolve reject : (RCTPromiseRejectBlock)reject) {
-  [_swiftAPI initialize2WithApiKey:apiKey
-                            config:config
-               apiEndPointOverride:apiEndPointOverride
-                           version:version
-                          resolver:resolve
-                          rejecter:reject];
-}
-
-RCT_EXPORT_METHOD(setEmail : (NSString *_Nullable)
-                      email authToken : (NSString *_Nullable)authToken) {
-  [_swiftAPI setEmail:email authToken:authToken];
-}
-
-RCT_EXPORT_METHOD(getEmail : (RCTPromiseResolveBlock)
-                      resolve reject : (RCTPromiseRejectBlock)reject) {
-  [_swiftAPI getEmail:resolve rejecter:reject];
-}
-
-RCT_EXPORT_METHOD(setUserId : (NSString *_Nullable)
-                      userId authToken : (NSString *_Nullable)authToken) {
-  [_swiftAPI setUserId:userId authToken:authToken];
-}
-
-RCT_EXPORT_METHOD(getUserId : (RCTPromiseResolveBlock)
-                      resolve reject : (RCTPromiseRejectBlock)reject) {
-  [_swiftAPI getUserId:resolve rejecter:reject];
-}
-
-RCT_EXPORT_METHOD(setInAppShowResponse : (NSNumber *)inAppShowResponse) {
-  [_swiftAPI setInAppShowResponse:inAppShowResponse];
-}
-
-RCT_EXPORT_METHOD(getInAppMessages : (RCTPromiseResolveBlock)
-                      resolve reject : (RCTPromiseRejectBlock)reject) {
-  [_swiftAPI getInAppMessages:resolve rejecter:reject];
-}
-
-RCT_EXPORT_METHOD(getInboxMessages : (RCTPromiseResolveBlock)
-                      resolve reject : (RCTPromiseRejectBlock)reject) {
-  [_swiftAPI getInboxMessages:resolve rejecter:reject];
-}
-
-RCT_EXPORT_METHOD(getUnreadInboxMessagesCount : (RCTPromiseResolveBlock)
-                      resolve reject : (RCTPromiseRejectBlock)reject) {
-  [_swiftAPI getUnreadInboxMessagesCount:resolve rejecter:reject];
-}
-
-RCT_EXPORT_METHOD(showMessage : (NSString *)messageId consume : (BOOL)
-                      consume resolve : (RCTPromiseResolveBlock)
-                          resolve reject : (RCTPromiseRejectBlock)reject) {
-  [_swiftAPI showMessage:messageId
-                 consume:consume
-                resolver:resolve
-                rejecter:reject];
-}
-
-RCT_EXPORT_METHOD(removeMessage : (NSString *)messageId location : (NSNumber *)
-                      location source : (NSNumber *)source) {
-  [_swiftAPI removeMessage:messageId location:location source:source];
-}
-
-RCT_EXPORT_METHOD(setReadForMessage : (NSString *)messageId read : (BOOL)read) {
-  [_swiftAPI setReadForMessage:messageId read:read];
-}
-
-RCT_EXPORT_METHOD(setAutoDisplayPaused : (BOOL)autoDisplayPaused) {
-  [_swiftAPI setAutoDisplayPaused:autoDisplayPaused];
-}
-
-RCT_EXPORT_METHOD(trackEvent : (NSString *)name dataFields : (NSDictionary *)
-                      dataFields) {
-  [_swiftAPI trackEvent:name dataFields:dataFields];
-}
-
-RCT_EXPORT_METHOD(
-    trackPushOpenWithCampaignId : (NSNumber *)
-        campaignId templateId : (NSNumber *)templateId messageId : (NSString *)
-            messageId appAlreadyRunning : (BOOL)
-                appAlreadyRunning dataFields : (NSDictionary *)dataFields) {
-  [_swiftAPI trackPushOpenWithCampaignId:campaignId
-                              templateId:templateId
-                               messageId:messageId
-                       appAlreadyRunning:appAlreadyRunning
-                              dataFields:dataFields];
-}
-
-RCT_EXPORT_METHOD(trackInAppOpen : (NSString *)messageId location : (NSNumber *)
-                      location) {
-  [_swiftAPI trackInAppOpen:messageId location:location];
-}
-
-RCT_EXPORT_METHOD(trackInAppClick : (NSString *)messageId location : (
-    NSNumber *)location clickedUrl : (NSString *)clickedUrl) {
-  [_swiftAPI trackInAppClick:messageId location:location clickedUrl:clickedUrl];
-}
-
-RCT_EXPORT_METHOD(trackInAppClose : (NSString *)messageId location : (
-    NSNumber *)location source : (NSNumber *)source clickedUrl : (NSString *)
-                      clickedUrl) {
-  [_swiftAPI trackInAppClose:messageId
-                    location:location
-                      source:source
-                  clickedUrl:clickedUrl];
-}
-
-RCT_EXPORT_METHOD(inAppConsume : (NSString *)messageId location : (NSNumber *)
-                      location source : (NSNumber *)source) {
-  [_swiftAPI inAppConsume:messageId location:location source:source];
-}
-
-RCT_EXPORT_METHOD(updateCart : (NSArray *)items) {
-  [_swiftAPI updateCart:items];
-}
-
-RCT_EXPORT_METHOD(trackPurchase : (NSNumber *)total items : (NSArray *)
-                      items dataFields : (NSDictionary *)dataFields) {
-  [_swiftAPI trackPurchase:total items:items dataFields:dataFields];
-}
-
-RCT_EXPORT_METHOD(updateUser : (NSDictionary *)dataFields mergeNestedObjects : (
-    BOOL)mergeNestedObjects) {
-  [_swiftAPI updateUser:dataFields mergeNestedObjects:mergeNestedObjects];
-}
-RCT_EXPORT_METHOD(updateEmail : (NSString *)email authToken : (NSString *)
-                      authToken) {
-  [_swiftAPI updateEmail:email authToken:authToken];
-}
-
-RCT_EXPORT_METHOD(getAttributionInfo : (RCTPromiseResolveBlock)
-                      resolve reject : (RCTPromiseRejectBlock)reject) {
-  [_swiftAPI getAttributionInfo:resolve rejecter:reject];
-}
-
-RCT_EXPORT_METHOD(setAttributionInfo : (NSDictionary *)attributionInfo) {
-  [_swiftAPI setAttributionInfo:attributionInfo];
-}
-
-RCT_EXPORT_METHOD(disableDeviceForCurrentUser) {
-  [_swiftAPI disableDeviceForCurrentUser];
-}
-
-RCT_EXPORT_METHOD(getLastPushPayload : (RCTPromiseResolveBlock)
-                      resolve reject : (RCTPromiseRejectBlock)reject) {
-  [_swiftAPI getLastPushPayload:resolve rejecter:reject];
-}
-
-RCT_EXPORT_METHOD(getHtmlInAppContentForMessage : (NSString *)
-                      messageId resolve : (RCTPromiseResolveBlock)
-                          resolve reject : (RCTPromiseRejectBlock)reject) {
-  [_swiftAPI getHtmlInAppContentForMessage:messageId
-                                  resolver:resolve
-                                  rejecter:reject];
-}
-
-RCT_EXPORT_METHOD(handleAppLink : (NSString *)appLink resolve : (
-    RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) {
-  [_swiftAPI handleAppLink:appLink resolver:resolve rejecter:reject];
-}
-
-RCT_EXPORT_METHOD(
-    updateSubscriptions : (NSArray *)emailListIds unsubscribedChannelIds : (
-        NSArray *)
-        unsubscribedChannelIds unsubscribedMessageTypeIds : (NSArray *)
-            unsubscribedMessageTypeIds subscribedMessageTypeIds : (NSArray *)
-                subscribedMessageTypeIds campaignId : (NSNumber *)
-                    campaignId templateId : (NSNumber *)templateId) {
-  [_swiftAPI updateSubscriptions:emailListIds
-          unsubscribedChannelIds:unsubscribedChannelIds
-      unsubscribedMessageTypeIds:unsubscribedMessageTypeIds
-        subscribedMessageTypeIds:subscribedMessageTypeIds
-                      campaignId:campaignId
-                      templateId:templateId];
-}
-
-RCT_EXPORT_METHOD(startSession : (NSArray *)visibleRows) {
-  [_swiftAPI startSession:visibleRows];
-}
-
-RCT_EXPORT_METHOD(endSession) { [_swiftAPI endSession]; }
-
-RCT_EXPORT_METHOD(updateVisibleRows : (NSArray *)visibleRows) {
-  [_swiftAPI updateVisibleRows:visibleRows];
-}
-
-RCT_EXPORT_METHOD(passAlongAuthToken : (NSString *)authToken) {
-  [_swiftAPI passAlongAuthToken:authToken];
-}
-
-#endif
 
 @end

From 1b93af4a2862d59d136b37778cfb8e22eb470ce5 Mon Sep 17 00:00:00 2001
From: Loren Posen <loren.posen@iterable.com>
Date: Sat, 2 Aug 2025 11:09:11 -0700
Subject: [PATCH 07/13] refactor: adjust RNIterableAPI to expose methods for
 both new and legacy architectures

---
 ios/RNIterableAPI/RNIterableAPI.h  |  16 +-
 ios/RNIterableAPI/RNIterableAPI.mm | 229 ++++++++++++++++++++++++++++-
 2 files changed, 239 insertions(+), 6 deletions(-)

diff --git a/ios/RNIterableAPI/RNIterableAPI.h b/ios/RNIterableAPI/RNIterableAPI.h
index 7a5b20833..a8b725452 100644
--- a/ios/RNIterableAPI/RNIterableAPI.h
+++ b/ios/RNIterableAPI/RNIterableAPI.h
@@ -1,10 +1,18 @@
 #import <Foundation/Foundation.h>
 #import <React/RCTEventEmitter.h>
-#import <React/RCTUtils.h>
-#import <React/RCTConvert.h>
-#import <React/RCTTurboModuleRegistry.h>
-#import <RNIterableAPISpec/RNIterableAPISpec.h>
 
+#if RCT_NEW_ARCH_ENABLED
+
+  #import <React/RCTUtils.h>
+  #import <React/RCTConvert.h>
+  #import <React/RCTTurboModuleRegistry.h>
+  #import <RNIterableAPISpec/RNIterableAPISpec.h>
 @interface RNIterableAPI : RCTEventEmitter <NativeRNIterableAPISpec>
 
+#else
+  #import <React/RCTBridgeModule.h>
+@interface RNIterableAPI : RCTEventEmitter <RCTBridgeModule>
+
+#endif
+
 @end
diff --git a/ios/RNIterableAPI/RNIterableAPI.mm b/ios/RNIterableAPI/RNIterableAPI.mm
index 16707c506..a33a32d1d 100644
--- a/ios/RNIterableAPI/RNIterableAPI.mm
+++ b/ios/RNIterableAPI/RNIterableAPI.mm
@@ -1,5 +1,9 @@
 #import "RNIterableAPI.h"
-#import "RNIterableAPISpec.h"
+
+#if RCT_NEW_ARCH_ENABLED
+  #import "RNIterableAPISpec.h"
+#endif
+
 #import <IterableSDK/IterableSDK.h>
 
 // Forward-declare the Swift protocols/enum used in the Swift header
@@ -44,6 +48,10 @@ - (void)sendEventWithName:(NSString *_Nonnull)name result:(double)result {
   [self sendEventWithName:name body:@(result)];
 }
 
+#if RCT_NEW_ARCH_ENABLED
+
+// MARK: - New Architecture functions exposed to JS
+
 - (void)startObserving {
   [(ReactIterableAPI *)_swiftAPI startObserving];
 }
@@ -52,7 +60,6 @@ - (void)stopObserving {
   [(ReactIterableAPI *)_swiftAPI stopObserving];
 }
 
-// MARK: - RNIterableAPI functions exposed to JS
 - (void)initializeWithApiKey:(NSString *)apiKey
                       config:(NSDictionary *)config
                      version:(NSString *)version
@@ -272,4 +279,222 @@ - (void)passAlongAuthToken:(NSString *)authToken {
   return std::make_shared<facebook::react::NativeRNIterableAPISpecJSI>(params);
 }
 
+#else
+
+// MARK: - RCTBridgeModule integration for Legacy Architecture
+
+RCT_EXPORT_METHOD(startObserving) {
+  [(ReactIterableAPI *)_swiftAPI startObserving];
+}
+
+RCT_EXPORT_METHOD(stopObserving) {
+  [(ReactIterableAPI *)_swiftAPI stopObserving];
+}
+
+RCT_EXPORT_METHOD(
+    initializeWithApiKey : (NSString *)apiKey config : (NSDictionary *)
+        config version : (NSString *)version resolve : (RCTPromiseResolveBlock)
+            resolve reject : (RCTPromiseRejectBlock)reject) {
+  [_swiftAPI initializeWithApiKey:apiKey
+                           config:config
+                          version:version
+                         resolver:resolve
+                         rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(
+    initialize2WithApiKey : (NSString *)apiKey config : (NSDictionary *)
+        config version : (NSString *)version apiEndPointOverride : (NSString *)
+            apiEndPointOverride resolve : (RCTPromiseResolveBlock)
+                resolve reject : (RCTPromiseRejectBlock)reject) {
+  [_swiftAPI initialize2WithApiKey:apiKey
+                            config:config
+               apiEndPointOverride:apiEndPointOverride
+                           version:version
+                          resolver:resolve
+                          rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(setEmail : (NSString *_Nullable)
+                      email authToken : (NSString *_Nullable)authToken) {
+  [_swiftAPI setEmail:email authToken:authToken];
+}
+
+RCT_EXPORT_METHOD(getEmail : (RCTPromiseResolveBlock)
+                      resolve reject : (RCTPromiseRejectBlock)reject) {
+  [_swiftAPI getEmail:resolve rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(setUserId : (NSString *_Nullable)
+                      userId authToken : (NSString *_Nullable)authToken) {
+  [_swiftAPI setUserId:userId authToken:authToken];
+}
+
+RCT_EXPORT_METHOD(getUserId : (RCTPromiseResolveBlock)
+                      resolve reject : (RCTPromiseRejectBlock)reject) {
+  [_swiftAPI getUserId:resolve rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(setInAppShowResponse : (NSNumber *)inAppShowResponse) {
+  [_swiftAPI setInAppShowResponse:inAppShowResponse];
+}
+
+RCT_EXPORT_METHOD(getInAppMessages : (RCTPromiseResolveBlock)
+                      resolve reject : (RCTPromiseRejectBlock)reject) {
+  [_swiftAPI getInAppMessages:resolve rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(getInboxMessages : (RCTPromiseResolveBlock)
+                      resolve reject : (RCTPromiseRejectBlock)reject) {
+  [_swiftAPI getInboxMessages:resolve rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(getUnreadInboxMessagesCount : (RCTPromiseResolveBlock)
+                      resolve reject : (RCTPromiseRejectBlock)reject) {
+  [_swiftAPI getUnreadInboxMessagesCount:resolve rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(showMessage : (NSString *)messageId consume : (BOOL)
+                      consume resolve : (RCTPromiseResolveBlock)
+                          resolve reject : (RCTPromiseRejectBlock)reject) {
+  [_swiftAPI showMessage:messageId
+                 consume:consume
+                resolver:resolve
+                rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(removeMessage : (NSString *)messageId location : (NSNumber *)
+                      location source : (NSNumber *)source) {
+  [_swiftAPI removeMessage:messageId location:location source:source];
+}
+
+RCT_EXPORT_METHOD(setReadForMessage : (NSString *)messageId read : (BOOL)read) {
+  [_swiftAPI setReadForMessage:messageId read:read];
+}
+
+RCT_EXPORT_METHOD(setAutoDisplayPaused : (BOOL)autoDisplayPaused) {
+  [_swiftAPI setAutoDisplayPaused:autoDisplayPaused];
+}
+
+RCT_EXPORT_METHOD(trackEvent : (NSString *)name dataFields : (NSDictionary *)
+                      dataFields) {
+  [_swiftAPI trackEvent:name dataFields:dataFields];
+}
+
+RCT_EXPORT_METHOD(
+    trackPushOpenWithCampaignId : (NSNumber *)
+        campaignId templateId : (NSNumber *)templateId messageId : (NSString *)
+            messageId appAlreadyRunning : (BOOL)
+                appAlreadyRunning dataFields : (NSDictionary *)dataFields) {
+  [_swiftAPI trackPushOpenWithCampaignId:campaignId
+                              templateId:templateId
+                               messageId:messageId
+                       appAlreadyRunning:appAlreadyRunning
+                              dataFields:dataFields];
+}
+
+RCT_EXPORT_METHOD(trackInAppOpen : (NSString *)messageId location : (NSNumber *)
+                      location) {
+  [_swiftAPI trackInAppOpen:messageId location:location];
+}
+
+RCT_EXPORT_METHOD(trackInAppClick : (NSString *)messageId location : (
+    NSNumber *)location clickedUrl : (NSString *)clickedUrl) {
+  [_swiftAPI trackInAppClick:messageId location:location clickedUrl:clickedUrl];
+}
+
+RCT_EXPORT_METHOD(trackInAppClose : (NSString *)messageId location : (
+    NSNumber *)location source : (NSNumber *)source clickedUrl : (NSString *)
+                      clickedUrl) {
+  [_swiftAPI trackInAppClose:messageId
+                    location:location
+                      source:source
+                  clickedUrl:clickedUrl];
+}
+
+RCT_EXPORT_METHOD(inAppConsume : (NSString *)messageId location : (NSNumber *)
+                      location source : (NSNumber *)source) {
+  [_swiftAPI inAppConsume:messageId location:location source:source];
+}
+
+RCT_EXPORT_METHOD(updateCart : (NSArray *)items) {
+  [_swiftAPI updateCart:items];
+}
+
+RCT_EXPORT_METHOD(trackPurchase : (NSNumber *)total items : (NSArray *)
+                      items dataFields : (NSDictionary *)dataFields) {
+  [_swiftAPI trackPurchase:total items:items dataFields:dataFields];
+}
+
+RCT_EXPORT_METHOD(updateUser : (NSDictionary *)dataFields mergeNestedObjects : (
+    BOOL)mergeNestedObjects) {
+  [_swiftAPI updateUser:dataFields mergeNestedObjects:mergeNestedObjects];
+}
+RCT_EXPORT_METHOD(updateEmail : (NSString *)email authToken : (NSString *)
+                      authToken) {
+  [_swiftAPI updateEmail:email authToken:authToken];
+}
+
+RCT_EXPORT_METHOD(getAttributionInfo : (RCTPromiseResolveBlock)
+                      resolve reject : (RCTPromiseRejectBlock)reject) {
+  [_swiftAPI getAttributionInfo:resolve rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(setAttributionInfo : (NSDictionary *)attributionInfo) {
+  [_swiftAPI setAttributionInfo:attributionInfo];
+}
+
+RCT_EXPORT_METHOD(disableDeviceForCurrentUser) {
+  [_swiftAPI disableDeviceForCurrentUser];
+}
+
+RCT_EXPORT_METHOD(getLastPushPayload : (RCTPromiseResolveBlock)
+                      resolve reject : (RCTPromiseRejectBlock)reject) {
+  [_swiftAPI getLastPushPayload:resolve rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(getHtmlInAppContentForMessage : (NSString *)
+                      messageId resolve : (RCTPromiseResolveBlock)
+                          resolve reject : (RCTPromiseRejectBlock)reject) {
+  [_swiftAPI getHtmlInAppContentForMessage:messageId
+                                  resolver:resolve
+                                  rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(handleAppLink : (NSString *)appLink resolve : (
+    RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) {
+  [_swiftAPI handleAppLink:appLink resolver:resolve rejecter:reject];
+}
+
+RCT_EXPORT_METHOD(
+    updateSubscriptions : (NSArray *)emailListIds unsubscribedChannelIds : (
+        NSArray *)
+        unsubscribedChannelIds unsubscribedMessageTypeIds : (NSArray *)
+            unsubscribedMessageTypeIds subscribedMessageTypeIds : (NSArray *)
+                subscribedMessageTypeIds campaignId : (NSNumber *)
+                    campaignId templateId : (NSNumber *)templateId) {
+  [_swiftAPI updateSubscriptions:emailListIds
+          unsubscribedChannelIds:unsubscribedChannelIds
+      unsubscribedMessageTypeIds:unsubscribedMessageTypeIds
+        subscribedMessageTypeIds:subscribedMessageTypeIds
+                      campaignId:campaignId
+                      templateId:templateId];
+}
+
+RCT_EXPORT_METHOD(startSession : (NSArray *)visibleRows) {
+  [_swiftAPI startSession:visibleRows];
+}
+
+RCT_EXPORT_METHOD(endSession) { [_swiftAPI endSession]; }
+
+RCT_EXPORT_METHOD(updateVisibleRows : (NSArray *)visibleRows) {
+  [_swiftAPI updateVisibleRows:visibleRows];
+}
+
+RCT_EXPORT_METHOD(passAlongAuthToken : (NSString *)authToken) {
+  [_swiftAPI passAlongAuthToken:authToken];
+}
+
+#endif
+
 @end

From 077a3a6481a41532b84d31dab732f9ada432bb60 Mon Sep 17 00:00:00 2001
From: Loren Posen <loren.posen@iterable.com>
Date: Sat, 2 Aug 2025 11:11:12 -0700
Subject: [PATCH 08/13] refactor: remove unused methods and logging from
 ReactIterableAPI.swift to streamline code

---
 ios/RNIterableAPI/ReactIterableAPI.swift | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/ios/RNIterableAPI/ReactIterableAPI.swift b/ios/RNIterableAPI/ReactIterableAPI.swift
index 6efb2c0b4..419f76a29 100644
--- a/ios/RNIterableAPI/ReactIterableAPI.swift
+++ b/ios/RNIterableAPI/ReactIterableAPI.swift
@@ -33,7 +33,6 @@ import React
     case receivedIterableInboxChanged
     case handleAuthSuccessCalled
     case handleAuthFailureCalled
-    case onTestEventDispatch
   }
 
   @objc public static var supportedEvents: [String] {
@@ -54,10 +53,6 @@ import React
 
   // MARK: - Native SDK Functions
 
-  @objc public func hello() {
-    print("Hello from Swift Again")
-  }
-
   @objc(initializeWithApiKey:config:version:resolver:rejecter:)
   public func initializeWithApiKey(
     apiKey: String,
@@ -66,7 +61,6 @@ import React
     resolver: @escaping RCTPromiseResolveBlock,
     rejecter: @escaping RCTPromiseRejectBlock
   ) {
-    NSLog("initializeWithApiKey called from swift")
     ITBInfo()
 
     initialize(
@@ -478,13 +472,6 @@ import React
     inboxSessionManager.updateVisibleRows(visibleRows: serializedRows)
   }
 
-  @objc(testEventDispatch)
-  public func testEventDispatch() {
-    NSLog("***ITBL SWIFT*** shouldEmit: \(shouldEmit)")
-    NSLog("***ITBL SWIFT*** testEventDispatch", EventName.onTestEventDispatch.rawValue)
-    delegate?.sendEvent(withName: EventName.onTestEventDispatch.rawValue, body: 0)
-  }
-
   // MARK: - SDK Auth Manager Functions
 
   @objc(passAlongAuthToken:)

From 57dcf59d9c66239ba701a631428c51a65d9e24dc Mon Sep 17 00:00:00 2001
From: Loren Posen <loren.posen@iterable.com>
Date: Wed, 6 Aug 2025 13:11:21 -0700
Subject: [PATCH 09/13] feat: add iOS module configuration for RNIterableAPI
 and ReactIterableAPI in package.json

---
 package.json | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/package.json b/package.json
index fb9752664..ebfd25a20 100644
--- a/package.json
+++ b/package.json
@@ -182,6 +182,12 @@
     "jsSrcsDir": "src/api/",
     "android": {
       "javaPackageName": "com.iterable.reactnative"
+    },
+    "ios": {
+      "modules": {
+        "RNIterableAPI": "RNIterableAPI",
+        "ReactIterableAPI": "ReactIterableAPI"
+      }
     }
   },
   "create-react-native-library": {

From 9a1e16d629c82a8c155d601079c3ac824231cbaa Mon Sep 17 00:00:00 2001
From: Loren Posen <loren.posen@iterable.com>
Date: Wed, 20 Aug 2025 17:38:50 -0700
Subject: [PATCH 10/13] refactor: update podspec for Iterable-React-Native-SDK
 to support Swift and iOS SDK dependency

---
 Iterable-React-Native-SDK.podspec             | 40 ++++------
 .../project.pbxproj                           | 78 +++++++++----------
 2 files changed, 53 insertions(+), 65 deletions(-)

diff --git a/Iterable-React-Native-SDK.podspec b/Iterable-React-Native-SDK.podspec
index 14c6d5966..e074bb340 100644
--- a/Iterable-React-Native-SDK.podspec
+++ b/Iterable-React-Native-SDK.podspec
@@ -1,7 +1,6 @@
 require "json"
 
 package = JSON.parse(File.read(File.join(__dir__, "package.json")))
-folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
 
 Pod::Spec.new do |s|
   s.name         = "Iterable-React-Native-SDK"
@@ -14,31 +13,20 @@ Pod::Spec.new do |s|
   s.platforms    = { :ios => min_ios_version_supported }
   s.source       = { :git => "https://github.com/Iterable/react-native-sdk.git", :tag => "#{s.version}" }
 
-  s.source_files = "ios/**/*.{h,m,mm,swift}"
-
-  # Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
-  # See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
-  if respond_to?(:install_modules_dependencies, true)
-    install_modules_dependencies(s)
-  else
-    s.dependency "React-Core"
-
-    # Don't install the dependencies when we run `pod install` in the old architecture.
-    if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
-      s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
-      s.pod_target_xcconfig    = {
-          "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
-          "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
-          "CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
-      }
-      s.dependency "React-Codegen"
-      s.dependency "RCT-Folly"
-      s.dependency "RCTRequired"
-      s.dependency "RCTTypeSafety"
-      s.dependency "ReactCommon/turbomodule/core"
-    end
-  end
+  s.source_files = "ios/**/*.{h,m,mm,cpp,swift}"
+  s.private_header_files = "ios/**/*.h"
 
+  # Load Iterables iOS SDK as a dependency
   s.dependency "Iterable-iOS-SDK", "6.5.4"
-  
+
+  # Basic Swift support
+  s.pod_target_xcconfig = {
+    'DEFINES_MODULE'      => 'YES',
+    'CLANG_ENABLE_MODULES' => 'YES',
+    'SWIFT_VERSION'       => '5.0',
+    "CLANG_CXX_LANGUAGE_STANDARD" => rct_cxx_language_standard(),
+  }
+
+  install_modules_dependencies(s)
+
 end
diff --git a/example/ios/ReactNativeSdkExample.xcodeproj/project.pbxproj b/example/ios/ReactNativeSdkExample.xcodeproj/project.pbxproj
index 36dbb67d0..f51e2bd6b 100644
--- a/example/ios/ReactNativeSdkExample.xcodeproj/project.pbxproj
+++ b/example/ios/ReactNativeSdkExample.xcodeproj/project.pbxproj
@@ -10,9 +10,9 @@
 		00E356F31AD99517003FC87E /* ReactNativeSdkExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* ReactNativeSdkExampleTests.m */; };
 		13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
 		779227342DFA3FB500D69EC0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 779227332DFA3FB500D69EC0 /* AppDelegate.swift */; };
+		77F63EC390061314C0718D51 /* libPods-ReactNativeSdkExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F395BEFC7809290D1773C84F /* libPods-ReactNativeSdkExample.a */; };
 		81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
 		A3A40C20801B8F02005FA4C0 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 1FC6B09E65A7BD9F6864C5D8 /* PrivacyInfo.xcprivacy */; };
-		A6C0695C2CEB3E991B349B28 /* libPods-ReactNativeSdkExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5750A1B5F0DE8C0CA5F46AD7 /* libPods-ReactNativeSdkExample.a */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -34,14 +34,14 @@
 		13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ReactNativeSdkExample/Info.plist; sourceTree = "<group>"; };
 		13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = ReactNativeSdkExample/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
 		1FC6B09E65A7BD9F6864C5D8 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = ReactNativeSdkExample/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
-		489E9B1B73890306BCD7B250 /* Pods-ReactNativeSdkExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReactNativeSdkExample.release.xcconfig"; path = "Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample.release.xcconfig"; sourceTree = "<group>"; };
-		5750A1B5F0DE8C0CA5F46AD7 /* libPods-ReactNativeSdkExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ReactNativeSdkExample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
-		67C6240790C3DAF138EB4ADB /* Pods-ReactNativeSdkExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReactNativeSdkExample.debug.xcconfig"; path = "Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample.debug.xcconfig"; sourceTree = "<group>"; };
+		627A5082522E8122626A42E9 /* Pods-ReactNativeSdkExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReactNativeSdkExample.debug.xcconfig"; path = "Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample.debug.xcconfig"; sourceTree = "<group>"; };
 		779227312DFA3FB500D69EC0 /* ReactNativeSdkExample-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ReactNativeSdkExample-Bridging-Header.h"; sourceTree = "<group>"; };
 		779227322DFA3FB500D69EC0 /* ReactNativeSdkExampleTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ReactNativeSdkExampleTests-Bridging-Header.h"; sourceTree = "<group>"; };
 		779227332DFA3FB500D69EC0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = ReactNativeSdkExample/AppDelegate.swift; sourceTree = "<group>"; };
 		81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = ReactNativeSdkExample/LaunchScreen.storyboard; sourceTree = "<group>"; };
+		C37A515B34C484F156F48110 /* Pods-ReactNativeSdkExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReactNativeSdkExample.release.xcconfig"; path = "Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample.release.xcconfig"; sourceTree = "<group>"; };
 		ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
+		F395BEFC7809290D1773C84F /* libPods-ReactNativeSdkExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ReactNativeSdkExample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -56,7 +56,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				A6C0695C2CEB3E991B349B28 /* libPods-ReactNativeSdkExample.a in Frameworks */,
+				77F63EC390061314C0718D51 /* libPods-ReactNativeSdkExample.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -99,7 +99,7 @@
 			isa = PBXGroup;
 			children = (
 				ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
-				5750A1B5F0DE8C0CA5F46AD7 /* libPods-ReactNativeSdkExample.a */,
+				F395BEFC7809290D1773C84F /* libPods-ReactNativeSdkExample.a */,
 			);
 			name = Frameworks;
 			sourceTree = "<group>";
@@ -138,8 +138,8 @@
 		BBD78D7AC51CEA395F1C20DB /* Pods */ = {
 			isa = PBXGroup;
 			children = (
-				67C6240790C3DAF138EB4ADB /* Pods-ReactNativeSdkExample.debug.xcconfig */,
-				489E9B1B73890306BCD7B250 /* Pods-ReactNativeSdkExample.release.xcconfig */,
+				627A5082522E8122626A42E9 /* Pods-ReactNativeSdkExample.debug.xcconfig */,
+				C37A515B34C484F156F48110 /* Pods-ReactNativeSdkExample.release.xcconfig */,
 			);
 			path = Pods;
 			sourceTree = "<group>";
@@ -169,13 +169,13 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ReactNativeSdkExample" */;
 			buildPhases = (
-				39F16507F41D7B65C4BB2AFA /* [CP] Check Pods Manifest.lock */,
+				00A09C8D745F4A4962CFCB16 /* [CP] Check Pods Manifest.lock */,
 				13B07F871A680F5B00A75B9A /* Sources */,
 				13B07F8C1A680F5B00A75B9A /* Frameworks */,
 				13B07F8E1A680F5B00A75B9A /* Resources */,
 				00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
-				9BCDAF1ED4681299F154EB0B /* [CP] Embed Pods Frameworks */,
-				577CB6D19BA58383681D2C91 /* [CP] Copy Pods Resources */,
+				70E3A2A47E764F7A78602595 /* [CP] Embed Pods Frameworks */,
+				EDF40E5EF2B0A60C77B1B71B /* [CP] Copy Pods Resources */,
 			);
 			buildRules = (
 			);
@@ -244,23 +244,7 @@
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXShellScriptBuildPhase section */
-		00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputPaths = (
-				"$(SRCROOT)/.xcode.env.local",
-				"$(SRCROOT)/.xcode.env",
-			);
-			name = "Bundle React Native code and images";
-			outputPaths = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n";
-		};
-		39F16507F41D7B65C4BB2AFA /* [CP] Check Pods Manifest.lock */ = {
+		00A09C8D745F4A4962CFCB16 /* [CP] Check Pods Manifest.lock */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
@@ -282,24 +266,23 @@
 			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
 			showEnvVarsInLog = 0;
 		};
-		577CB6D19BA58383681D2C91 /* [CP] Copy Pods Resources */ = {
+		00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
-			inputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample-resources-${CONFIGURATION}-input-files.xcfilelist",
+			inputPaths = (
+				"$(SRCROOT)/.xcode.env.local",
+				"$(SRCROOT)/.xcode.env",
 			);
-			name = "[CP] Copy Pods Resources";
-			outputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample-resources-${CONFIGURATION}-output-files.xcfilelist",
+			name = "Bundle React Native code and images";
+			outputPaths = (
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample-resources.sh\"\n";
-			showEnvVarsInLog = 0;
+			shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n";
 		};
-		9BCDAF1ED4681299F154EB0B /* [CP] Embed Pods Frameworks */ = {
+		70E3A2A47E764F7A78602595 /* [CP] Embed Pods Frameworks */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
@@ -316,6 +299,23 @@
 			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample-frameworks.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
+		EDF40E5EF2B0A60C77B1B71B /* [CP] Copy Pods Resources */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample-resources-${CONFIGURATION}-input-files.xcfilelist",
+			);
+			name = "[CP] Copy Pods Resources";
+			outputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample-resources-${CONFIGURATION}-output-files.xcfilelist",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ReactNativeSdkExample/Pods-ReactNativeSdkExample-resources.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
 /* End PBXShellScriptBuildPhase section */
 
 /* Begin PBXSourcesBuildPhase section */
@@ -406,7 +406,7 @@
 		};
 		13B07F941A680F5B00A75B9A /* Debug */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = 67C6240790C3DAF138EB4ADB /* Pods-ReactNativeSdkExample.debug.xcconfig */;
+			baseConfigurationReference = 627A5082522E8122626A42E9 /* Pods-ReactNativeSdkExample.debug.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
@@ -436,7 +436,7 @@
 		};
 		13B07F951A680F5B00A75B9A /* Release */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = 489E9B1B73890306BCD7B250 /* Pods-ReactNativeSdkExample.release.xcconfig */;
+			baseConfigurationReference = C37A515B34C484F156F48110 /* Pods-ReactNativeSdkExample.release.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;

From 29ba5140283be6a4dd5e7906d2a3aaee85ae7b2b Mon Sep 17 00:00:00 2001
From: Loren <3190869+lposen@users.noreply.github.com>
Date: Thu, 21 Aug 2025 14:36:57 -0700
Subject: [PATCH 11/13] Update ios/RNIterableAPI/ReactIterableAPI.swift

Added copilot suggestion

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
 ios/RNIterableAPI/ReactIterableAPI.swift | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/ios/RNIterableAPI/ReactIterableAPI.swift b/ios/RNIterableAPI/ReactIterableAPI.swift
index 419f76a29..7473cf6a7 100644
--- a/ios/RNIterableAPI/ReactIterableAPI.swift
+++ b/ios/RNIterableAPI/ReactIterableAPI.swift
@@ -505,7 +505,12 @@ import React
     ITBInfo()
     let launchOptions = createLaunchOptions()
     let iterableConfig = IterableConfig.from(
-      dict: configDict as? [AnyHashable: Any]
+    guard let configDictTyped = configDict as? [AnyHashable: Any] else {
+      rejecter("E_INVALID_CONFIG", "configDict could not be cast to [AnyHashable: Any]", nil)
+      return
+    }
+    let iterableConfig = IterableConfig.from(
+      dict: configDictTyped
     )
 
     if let urlHandlerPresent = configDict["urlHandlerPresent"] as? Bool, urlHandlerPresent == true {

From 6dbead47c7b70dfa248b74c52e8faf162c31333e Mon Sep 17 00:00:00 2001
From: Loren <3190869+lposen@users.noreply.github.com>
Date: Thu, 21 Aug 2025 14:37:52 -0700
Subject: [PATCH 12/13] refactor: update
 ios/RNIterableAPI/ReactIterableAPI.swift with copilot suggestion

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
 ios/RNIterableAPI/ReactIterableAPI.swift | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/ios/RNIterableAPI/ReactIterableAPI.swift b/ios/RNIterableAPI/ReactIterableAPI.swift
index 7473cf6a7..5ecb9322d 100644
--- a/ios/RNIterableAPI/ReactIterableAPI.swift
+++ b/ios/RNIterableAPI/ReactIterableAPI.swift
@@ -315,7 +315,11 @@ import React
   public func updateUser(dataFields: NSDictionary, mergeNestedObjects: Bool) {
     ITBInfo()
     IterableAPI.updateUser(
-      (dataFields as? [AnyHashable: Any])!, mergeNestedObjects: mergeNestedObjects)
+    guard let fields = dataFields as? [AnyHashable: Any] else {
+      ITBError("Could not cast dataFields to [AnyHashable: Any]")
+      return
+    }
+    IterableAPI.updateUser(fields, mergeNestedObjects: mergeNestedObjects)
   }
 
   @objc(updateEmail:authToken:)

From c3e13893acef0ed02aa575b199c431b69e20e8af Mon Sep 17 00:00:00 2001
From: Loren <3190869+lposen@users.noreply.github.com>
Date: Thu, 21 Aug 2025 14:38:26 -0700
Subject: [PATCH 13/13] refactor: update
 ios/RNIterableAPI/ReactIterableAPI.swift with copilot suggestion

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
 ios/RNIterableAPI/ReactIterableAPI.swift | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/ios/RNIterableAPI/ReactIterableAPI.swift b/ios/RNIterableAPI/ReactIterableAPI.swift
index 5ecb9322d..714767f6a 100644
--- a/ios/RNIterableAPI/ReactIterableAPI.swift
+++ b/ios/RNIterableAPI/ReactIterableAPI.swift
@@ -164,7 +164,12 @@ import React
       return
     }
     IterableAPI.attributionInfo = SerializationUtil.dictionaryToDecodable(
-      dict: dict as! [AnyHashable: Any])
+    guard let swiftDict = dict as? [AnyHashable: Any] else {
+      IterableAPI.attributionInfo = nil
+      return
+    }
+    IterableAPI.attributionInfo = SerializationUtil.dictionaryToDecodable(
+      dict: swiftDict)
   }
 
   @objc(trackPushOpenWithCampaignId:templateId:messageId:appAlreadyRunning:dataFields:)
