Skip to content

Instantly share code, notes, and snippets.

@meandavejustice
Last active January 22, 2025 05:42
Show Gist options
  • Save meandavejustice/c8b49692a31fd3d9940992be31610baa to your computer and use it in GitHub Desktop.
Save meandavejustice/c8b49692a31fd3d9940992be31610baa to your computer and use it in GitHub Desktop.
#import <UIKit/UIKit.h>
#import "LegacyAppDelegate.h"
@import Firebase;
// Helper function for consistent user assignment
static uint32_t fnv1aHash(NSString *str) {
uint32_t hash = 2166136261u;
for (NSInteger i = 0; i < str.length; i++) {
hash ^= (uint32_t)[str characterAtIndex:i];
hash *= 16777619u;
}
return hash;
}
static BOOL shouldUseNewVersion(float percentage) {
NSString *identifier = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
uint32_t hash = fnv1aHash(identifier);
float normalizedValue = (float)hash / (float)UINT32_MAX;
return normalizedValue < (percentage / 100.0f);
}
int main(int argc, char * argv[]) {
#ifdef DEBUG
@autoreleasepool {
@try {
// Initialize Firebase
[FIRApp configure];
// Set up Remote Config with default value
FIRRemoteConfig *config = [FIRRemoteConfig remoteConfig];
[config setDefaults:@{@"new_version_rollout_percentage": @1.0}];
// Create semaphore for sync config fetch
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block BOOL useNewVersion = NO;
// Fetch config
[config fetchWithCompletionHandler:^(FIRRemoteConfigFetchStatus status, NSError *error) {
if (status == FIRRemoteConfigFetchStatusSuccess) {
[config activateWithCompletion:^(BOOL changed, NSError *error) {
float percentage = [config[@"new_version_rollout_percentage"].numberValue floatValue];
useNewVersion = shouldUseNewVersion(percentage);
dispatch_semaphore_signal(semaphore);
}];
} else {
useNewVersion = shouldUseNewVersion(1.0f); // Default to 1%
dispatch_semaphore_signal(semaphore);
}
}];
// Wait with timeout
dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC));
if (useNewVersion) {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
} else {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([LegacyAppDelegate class]));
}
} @catch (NSException *exception) {
NSLog(@"[weatherbug main] Caught exception. name: %@; reason: %@\n %@",
exception.name, exception.reason, [exception callStackSymbols]);
NSLog(@"[weatherbug main] Caught exception: %@", exception);
@throw;
} @catch (...) {
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
@throw;
});
}
}
#else
@autoreleasepool {
[FIRApp configure];
FIRRemoteConfig *config = [FIRRemoteConfig remoteConfig];
float percentage = [config[@"new_version_rollout_percentage"].numberValue floatValue];
BOOL useNewVersion = shouldUseNewVersion(percentage);
return UIApplicationMain(argc, argv, nil,
NSStringFromClass(useNewVersion ? [AppDelegate class] : [LegacyAppDelegate class]));
}
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment