25
25
#import < UIKit/UIKit.h>
26
26
#import < objc/runtime.h>
27
27
28
+ #define MAX_PENDING_APP_DELEGATE_BLOCKS 8
29
+
28
30
static IMP g_original_setDelegate_imp = NULL ;
29
31
static Class g_app_delegate_class = nil ;
30
- static void (^g_pending_app_delegate_block)(Class ) = nil;
32
+ static void (^g_pending_app_delegate_blocks[MAX_PENDING_APP_DELEGATE_BLOCKS])(Class ) = {nil };
33
+ static int g_pending_block_count = 0 ;
31
34
32
35
// Swizzled implementation of setDelegate:
33
36
static void Firebase_setDelegate (id self, SEL _cmd, id <UIApplicationDelegate> delegate) {
@@ -40,17 +43,31 @@ static void Firebase_setDelegate(id self, SEL _cmd, id<UIApplicationDelegate> de
40
43
NSLog (@" Firebase: UIApplication setDelegate: called with nil delegate (Swizzled)" );
41
44
}
42
45
43
- if (g_pending_app_delegate_block && g_app_delegate_class) {
44
- NSLog (@" Firebase: Firebase_setDelegate executing pending block with delegate class: %s ." ,
45
- class_getName (g_app_delegate_class));
46
- g_pending_app_delegate_block (g_app_delegate_class);
47
- g_pending_app_delegate_block = nil ; // Clear the block after execution (ARC handles release)
48
- } else if (g_pending_app_delegate_block && !g_app_delegate_class) {
49
- // This case: setDelegate was called with nil, but a block was pending.
50
- // The pending block expects a Class. We don't have one.
51
- // So, we should clear the pending block as it can no longer be satisfied.
52
- NSLog (@" Firebase: Firebase_setDelegate called with nil delegate, clearing pending block as it cannot be executed." );
53
- g_pending_app_delegate_block = nil ;
46
+ // Check and execute/clear g_pending_app_delegate_blocks
47
+ if (g_app_delegate_class) { // Delegate is valid, execute pending blocks
48
+ if (g_pending_block_count > 0 ) {
49
+ NSLog (@" Firebase: Firebase_setDelegate executing %d pending block(s) with delegate class: %s ." ,
50
+ g_pending_block_count, class_getName (g_app_delegate_class));
51
+ for (int i = 0 ; i < g_pending_block_count; i++) {
52
+ if (g_pending_app_delegate_blocks[i]) {
53
+ g_pending_app_delegate_blocks[i](g_app_delegate_class);
54
+ g_pending_app_delegate_blocks[i] = nil ; // Release the block
55
+ }
56
+ }
57
+ // All pending blocks processed, reset count.
58
+ g_pending_block_count = 0 ;
59
+ }
60
+ } else { // Delegate is nil, clear any pending blocks
61
+ if (g_pending_block_count > 0 ) {
62
+ NSLog (@" Firebase: Firebase_setDelegate called with nil delegate, clearing %d pending block(s)." , g_pending_block_count);
63
+ for (int i = 0 ; i < g_pending_block_count; i++) {
64
+ if (g_pending_app_delegate_blocks[i]) {
65
+ g_pending_app_delegate_blocks[i] = nil ; // Release the block
66
+ }
67
+ }
68
+ // All pending blocks cleared, reset count.
69
+ g_pending_block_count = 0 ;
70
+ }
54
71
}
55
72
56
73
if (g_original_setDelegate_imp) {
@@ -141,17 +158,21 @@ - (BOOL)application:(UIApplication *)application
141
158
void ForEachAppDelegateClass (void (^block)(Class )) {
142
159
if (g_app_delegate_class) {
143
160
NSLog (@" Firebase: ForEachAppDelegateClass executing with stored delegate class: %s ." ,
144
- class_getName (g_app_delegate_class));
161
+ class_getName (g_app_delegate_class));
145
162
block (g_app_delegate_class);
146
- // Clear any pending block as we've now executed with a known delegate.
147
- if (g_pending_app_delegate_block) {
148
- g_pending_app_delegate_block = nil ; // ARC handles release
149
- }
163
+ // If the delegate is already known and we execute immediately,
164
+ // any previously pending blocks should have been cleared by Firebase_setDelegate.
165
+ // No need to touch g_pending_app_delegate_blocks here as they are for pre-setDelegate calls.
150
166
} else {
151
- NSLog (@" Firebase: ForEachAppDelegateClass - delegate class not yet known. Saving block for later execution." );
152
- // If a block is already pending, the new one replaces it. ARC handles the old one.
153
- // Make sure to copy the block to move it to the heap.
154
- g_pending_app_delegate_block = [block copy ];
167
+ // Delegate class not yet known, try to queue the block.
168
+ if (g_pending_block_count < MAX_PENDING_APP_DELEGATE_BLOCKS) {
169
+ g_pending_app_delegate_blocks[g_pending_block_count] = [block copy ];
170
+ g_pending_block_count++;
171
+ NSLog (@" Firebase: ForEachAppDelegateClass - delegate class not yet known. Saved block for later execution (pending count: %d )." , g_pending_block_count);
172
+ } else {
173
+ NSLog (@" Firebase Error: ForEachAppDelegateClass - pending block queue is full (max %d ). Discarding new block." , MAX_PENDING_APP_DELEGATE_BLOCKS);
174
+ // Block is discarded.
175
+ }
155
176
}
156
177
}
157
178
0 commit comments