From 9b92df8f9e6d35d32ca821466879d9e017481377 Mon Sep 17 00:00:00 2001 From: kenji Date: Wed, 26 Jul 2023 16:11:26 +0700 Subject: [PATCH] fix: throw exception when call BKTClient.initalize from a non-main thread --- Bucketeer/Sources/Public/BKTClient.swift | 5 +- BucketeerTests/E2E/E2ETestHelpers.swift | 14 ++++-- Example/AppDelegate.swift | 63 +++++++++++++----------- Example/FirstViewController.swift | 2 +- 4 files changed, 47 insertions(+), 37 deletions(-) diff --git a/Bucketeer/Sources/Public/BKTClient.swift b/Bucketeer/Sources/Public/BKTClient.swift index 9ca79775..10e069d6 100644 --- a/Bucketeer/Sources/Public/BKTClient.swift +++ b/Bucketeer/Sources/Public/BKTClient.swift @@ -73,10 +73,9 @@ public class BKTClient { } extension BKTClient { - public static func initialize(config: BKTConfig, user: BKTUser, timeoutMillis: Int64 = 5000, completion: ((BKTError?) -> Void)? = nil) { + public static func initialize(config: BKTConfig, user: BKTUser, timeoutMillis: Int64 = 5000, completion: ((BKTError?) -> Void)? = nil) throws { guard (Thread.isMainThread) else { - completion?(BKTError.illegalState(message: "the initialize method must be called on main thread")) - return + throw BKTError.illegalState(message: "the initialize method must be called on main thread") } concurrentQueue.sync { guard BKTClient.default == nil else { diff --git a/BucketeerTests/E2E/E2ETestHelpers.swift b/BucketeerTests/E2E/E2ETestHelpers.swift index 7cb922da..c5a65e55 100644 --- a/BucketeerTests/E2E/E2ETestHelpers.swift +++ b/BucketeerTests/E2E/E2ETestHelpers.swift @@ -35,12 +35,16 @@ extension BKTClient { static func initialize(config: BKTConfig, user: BKTUser, timeoutMillis: Int64 = 5000) async throws { return try await withCheckedThrowingContinuation { continuation in DispatchQueue.main.async { - self.initialize(config: config, user: user) { error in - if let error = error { - continuation.resume(throwing: error) - } else { - continuation.resume(returning: ()) + do { + try self.initialize(config: config, user: user) { error in + if let error = error { + continuation.resume(throwing: error) + } else { + continuation.resume(returning: ()) + } } + } catch { + continuation.resume(throwing: error) } } } diff --git a/Example/AppDelegate.swift b/Example/AppDelegate.swift index 2bd8c308..d209bed6 100644 --- a/Example/AppDelegate.swift +++ b/Example/AppDelegate.swift @@ -14,38 +14,45 @@ class AppDelegate: UIResponder, UIApplicationDelegate { .with(attributes: [:]) .build() - BKTClient.initialize( - config: self.makeConfigUsingBuilder(), - user: user - ) { error in - if let error { - print(error) - } - var client : BKTClient? - do { - try client = BKTClient.shared - } catch { - print(error.localizedDescription) - } - client?.updateUserAttributes(attributes: [:]) - print("intVariation =", client?.intVariation(featureId: "feature-ios-e2e-integer", defaultValue: 0) ?? 0) - print("doubleVariation =", client?.doubleVariation(featureId: "feature-ios-e2e-double", defaultValue: 0.0) ?? 0.0) - print("boolVariation =", client?.boolVariation(featureId: "feature-ios-e2e-bool", defaultValue: false) ?? false) - print("stringVariation =", client?.stringVariation(featureId: "feature-ios-e2e-string", defaultValue: "004 not found...") ?? "004 not found...") - print("jsonVariation =", client?.jsonVariation(featureId: "feature-ios-e2e-json", defaultValue: [:]) ?? [:]) - DispatchQueue.main.async { - self.setSingleViewController() - } - - DispatchQueue.main.async { - let isTabMode = client?.boolVariation(featureId: "ios_test_001", defaultValue: false) ?? false - if isTabMode { - self.setTabBarController() - } else { + do { + try BKTClient.initialize( + config: self.makeConfigUsingBuilder(), + user: user + ) { error in + if let error { + print(error) + } + var client : BKTClient? + do { + try client = BKTClient.shared + } catch { + print(error.localizedDescription) + } + client?.updateUserAttributes(attributes: [:]) + print("intVariation =", client?.intVariation(featureId: "feature-ios-e2e-integer", defaultValue: 0) ?? 0) + print("doubleVariation =", client?.doubleVariation(featureId: "feature-ios-e2e-double", defaultValue: 0.0) ?? 0.0) + print("boolVariation =", client?.boolVariation(featureId: "feature-ios-e2e-bool", defaultValue: false) ?? false) + print("stringVariation =", client?.stringVariation(featureId: "feature-ios-e2e-string", defaultValue: "004 not found...") ?? "004 not found...") + print("jsonVariation =", client?.jsonVariation(featureId: "feature-ios-e2e-json", defaultValue: [:]) ?? [:]) + DispatchQueue.main.async { self.setSingleViewController() } + + DispatchQueue.main.async { + let isTabMode = client?.boolVariation(featureId: "ios_test_001", defaultValue: false) ?? false + if isTabMode { + self.setTabBarController() + } else { + self.setSingleViewController() + } + } } + } catch { + // Handle exception when initialize the BKTClient, + // Usually because it required to call from the main thread + print(error.localizedDescription) } + return true } diff --git a/Example/FirstViewController.swift b/Example/FirstViewController.swift index a0fc6e67..656e46ab 100644 --- a/Example/FirstViewController.swift +++ b/Example/FirstViewController.swift @@ -11,7 +11,7 @@ class FirstViewController: UIViewController { do { try client = BKTClient.shared } catch { - // We may have an error when we did not initialize the client + // We may have an error when we did not success initialize the client // Handle error } }