From cd4753ef2dabaf7456899380d44bbab0e26a1e47 Mon Sep 17 00:00:00 2001 From: Stephen Radford Date: Wed, 20 May 2026 17:07:05 +0100 Subject: [PATCH] Add onMain helper and improve thread safety --- ios/CarouselInAppContentBlockViewProxy.swift | 25 ++++++++++++++------ ios/DictionaryExtensions.swift | 8 +++++++ ios/ExponeaBridge.swift | 5 ++-- ios/InAppContentBlocksPlaceholder.swift | 15 ++++++++---- 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/ios/CarouselInAppContentBlockViewProxy.swift b/ios/CarouselInAppContentBlockViewProxy.swift index 8006dcf..5fe7579 100644 --- a/ios/CarouselInAppContentBlockViewProxy.swift +++ b/ios/CarouselInAppContentBlockViewProxy.swift @@ -248,14 +248,19 @@ public class CarouselInAppContentBlockViewProxy: UIView, DefaultContentBlockCaro } private func notifyDimensChanged(width: CGFloat, height: CGFloat) { - eventEmitter?.emitDimensChanged( - width: Double(width), - height: Double(height) - ) + onMain { [weak self] in + self?.eventEmitter?.emitDimensChanged( + width: Double(width), + height: Double(height) + ) + } } private func notifyContentBlockCarouselEvent(_ event: ContentBlockCarouselEvent) { - eventEmitter?.emitContentBlockEvent(data: event.toDictionary() as NSDictionary) + let data = event.toDictionary() as NSDictionary + onMain { [weak self] in + self?.eventEmitter?.emitContentBlockEvent(data: data) + } } private func notifyContentFilterRequest(input: [ExponeaSDK.InAppContentBlockResponse]) { @@ -274,7 +279,10 @@ public class CarouselInAppContentBlockViewProxy: UIView, DefaultContentBlockCaro return } - eventEmitter?.emitDataRequest(data: ["requestType": "filter", "data": jsonString] as NSDictionary) + let payload: NSDictionary = ["requestType": "filter", "data": jsonString] + onMain { [weak self] in + self?.eventEmitter?.emitDataRequest(data: payload) + } } private func notifyContentSortRequest(input: [ExponeaSDK.InAppContentBlockResponse]) { @@ -293,6 +301,9 @@ public class CarouselInAppContentBlockViewProxy: UIView, DefaultContentBlockCaro return } - eventEmitter?.emitDataRequest(data: ["requestType": "sort", "data": jsonString] as NSDictionary) + let payload: NSDictionary = ["requestType": "sort", "data": jsonString] + onMain { [weak self] in + self?.eventEmitter?.emitDataRequest(data: payload) + } } } diff --git a/ios/DictionaryExtensions.swift b/ios/DictionaryExtensions.swift index a9f9717..7e4c09a 100644 --- a/ios/DictionaryExtensions.swift +++ b/ios/DictionaryExtensions.swift @@ -1,5 +1,13 @@ import Foundation +func onMain(_ block: @escaping () -> Void) { + if Thread.isMainThread { + block() + } else { + DispatchQueue.main.async(execute: block) + } +} + /// Error types for Exponea configuration public enum ExponeaDataError: Error { case invalidType(for: String) diff --git a/ios/ExponeaBridge.swift b/ios/ExponeaBridge.swift index f5b862e..f1bd33b 100644 --- a/ios/ExponeaBridge.swift +++ b/ios/ExponeaBridge.swift @@ -1080,8 +1080,9 @@ public class ExponeaRNVersion: NSObject, ExponeaVersionProvider { } private func sendEventToJS(name: String, body: Any?) { - // Use RCTEventEmitter to send events to JavaScript - eventEmitter?.sendEvent(withName: name, body: body) + onMain { [weak self] in + self?.eventEmitter?.sendEvent(withName: name, body: body) + } } private func convertToJSONString(_ dict: [AnyHashable: Any]) throws -> String { diff --git a/ios/InAppContentBlocksPlaceholder.swift b/ios/InAppContentBlocksPlaceholder.swift index 9b2a02c..7407f13 100644 --- a/ios/InAppContentBlocksPlaceholder.swift +++ b/ios/InAppContentBlocksPlaceholder.swift @@ -92,10 +92,12 @@ public class InAppContentBlocksPlaceholder: UIView, InAppContentBlockCallbackTyp } private func notifyDimensChanged(width: CGFloat, height: CGFloat) { - eventEmitter?.emitDimensChanged( - width: Double(width), - height: Double(height) - ) + onMain { [weak self] in + self?.eventEmitter?.emitDimensChanged( + width: Double(width), + height: Double(height) + ) + } } private func notifyInAppContentBlockEvent( @@ -137,7 +139,10 @@ public class InAppContentBlocksPlaceholder: UIView, InAppContentBlockCallbackTyp data["errorMessage"] = errorMessage } - eventEmitter?.emitContentBlockEvent(data: data as NSDictionary) + let eventData = data as NSDictionary + onMain { [weak self] in + self?.eventEmitter?.emitContentBlockEvent(data: eventData) + } } public func onMessageShown(placeholderId: String, contentBlock: ExponeaSDK.InAppContentBlockResponse) {