You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: Restore swizzling category and consolidate all recent changes
This commit addresses several critical fixes and consolidates all recent
updates for the iOS App Delegate handling mechanism:
1. **Restored Swizzling Mechanism:**
- Re-added the `UIApplication(FirebaseAppDelegateSwizzling)` category
and its `+load` method to `app/src/util_ios.mm`. This was
inadvertently lost during a previous operation and is
essential for swizzling `[UIApplication setDelegate:]` with
`Firebase_setDelegate`.
2. **Core Logic (already in working tree, confirmed):**
- `Firebase_setDelegate` correctly tracks multiple unique delegate
classes, includes a superclass check, and executes persistent
pending blocks for genuinely new delegate classes.
- `RunOnAppDelegateClasses` executes blocks for all currently known
delegates and queues blocks for future new delegates.
- `ClassMethodImplementationCache::ReplaceOrAddMethod` includes an
idempotency check to prevent re-swizzling if a method already
has the target IMP.
3. **Documentation (`Jules.md`):**
- Learnings from this refactoring are integrated into relevant
existing sections.
- The document is formatted with 80-character line wrapping, and a
note regarding this convention is included.
This commit aims to bring the `refactor-forEachAppDelegateClass-ios` branch
to its fully intended functional state, including all logic fixes,
restorations, and documentation updates.
`firebase::database::kErrorNone`) usually indicates success.
210
216
* Get the error message: `future.error_message()`.
211
217
* Get the result: `future.result()`. This returns a pointer to the result
212
218
object of type `T`. The result is only valid if `future.error()`
@@ -218,8 +224,8 @@ where `T` is the type of the expected result.
218
224
219
225
### Core Classes and Operations (Examples from Auth and Database)
220
226
221
-
While each Firebase product has its own specific classes, the following examples
222
-
illustrate common API patterns:
227
+
While each Firebase product has its own specific classes, the following
228
+
examples illustrate common API patterns:
223
229
224
230
***`firebase::auth::Auth`**: The main entry point for Firebase
225
231
Authentication.
@@ -305,7 +311,12 @@ API documentation.
305
311
as mentioned in `CONTRIBUTING.md`.
306
312
***Formatting**: Use `python3 scripts/format_code.py -git_diff -verbose` to
307
313
format your code before committing.
308
-
***Naming Precision for Dynamic Systems**: Function names should precisely reflect their behavior, especially in systems with dynamic or asynchronous interactions. For example, a function that processes a list of items should be named differently from one that operates on a single, specific item captured asynchronously. Regularly re-evaluate function names as requirements evolve to maintain clarity.
314
+
***Naming Precision for Dynamic Systems**: Function names should precisely
315
+
reflect their behavior, especially in systems with dynamic or asynchronous
316
+
interactions. For example, a function that processes a list of items should
317
+
be named differently from one that operates on a single, specific item
318
+
captured asynchronously. Regularly re-evaluate function names as
319
+
requirements evolve to maintain clarity.
309
320
310
321
## Comments
311
322
@@ -329,8 +340,9 @@ API documentation.
329
340
***Check `Future` status and errors**: Always check `future.status()` and
330
341
`future.error()` before attempting to use `future.result()`.
Other specific error codes are defined per module (e.g.,
343
+
`firebase::auth::kAuthErrorNone`,
344
+
`firebase::database::kErrorNone`). Other specific error codes are
345
+
defined per module (e.g.,
334
346
`firebase::auth::kAuthErrorUserNotFound`).
335
347
***Callback error parameters**: When using listeners or other callbacks,
336
348
always check the provided error code and message before processing the
@@ -363,7 +375,13 @@ API documentation.
363
375
otherwise ensuring the `Future` completes its course, particularly for
364
376
operations with side effects or those that allocate significant backend
365
377
resources.
366
-
***Lifecycle of Queued Callbacks/Blocks**: If blocks or callbacks are queued to be run upon an asynchronous event (e.g., an App Delegate class being set or a Future completing), clearly define and document their lifecycle. Determine if they are one-shot (cleared after first execution) or persistent (intended to run for multiple or future events). This impacts how associated data and the blocks themselves are stored and cleared, preventing memory leaks or unexpected multiple executions.
378
+
***Lifecycle of Queued Callbacks/Blocks**: If blocks or callbacks are queued
379
+
to be run upon an asynchronous event (e.g., an App Delegate class being set
380
+
or a Future completing), clearly define and document their lifecycle.
381
+
Determine if they are one-shot (cleared after first execution) or
382
+
persistent (intended to run for multiple or future events). This impacts
383
+
how associated data and the blocks themselves are stored and cleared,
384
+
preventing memory leaks or unexpected multiple executions.
367
385
368
386
## Immutability
369
387
@@ -399,10 +417,29 @@ API documentation.
399
417
integration, it can occasionally be a factor to consider when debugging app
400
418
delegate behavior or integrating with other libraries that also perform
401
419
swizzling.
402
-
When implementing or interacting with swizzling, especially for App Delegate methods like `[UIApplication setDelegate:]`:
403
-
* Be highly aware that `setDelegate:` can be called multiple times with different delegate class instances, including proxy classes from other libraries (e.g., GUL - Google Utilities). Swizzling logic must be robust against being invoked multiple times for the same effective method on the same class or on classes in a hierarchy. An idempotency check (i.e., if the method's current IMP is already the target swizzled IMP, do nothing more for that specific swizzle attempt) in any swizzling utility can prevent issues like recursion.
404
-
* When tracking unique App Delegate classes (e.g., for applying hooks or callbacks via swizzling), consider the class hierarchy. If a superclass has already been processed, processing a subclass for the same inherited methods might be redundant or problematic. A strategy to check if a newly set delegate is a subclass of an already processed delegate can prevent such issues.
405
-
* For code that runs very early in the application lifecycle on iOS/macOS (e.g., `+load` methods, static initializers involved in swizzling), prefer using `NSLog` directly over custom logging frameworks if there's any uncertainty about whether the custom framework is fully initialized, to avoid crashes during logging itself.
420
+
When implementing or interacting with swizzling, especially for App Delegate
421
+
methods like `[UIApplication setDelegate:]`:
422
+
* Be highly aware that `setDelegate:` can be called multiple times
423
+
with different delegate class instances, including proxy classes
424
+
from other libraries (e.g., GUL - Google Utilities). Swizzling
425
+
logic must be robust against being invoked multiple times for the
426
+
same effective method on the same class or on classes in a
427
+
hierarchy. An idempotency check (i.e., if the method's current IMP
428
+
is already the target swizzled IMP, do nothing more for that
429
+
specific swizzle attempt) in any swizzling utility can prevent
430
+
issues like recursion.
431
+
* When tracking unique App Delegate classes (e.g., for applying hooks
432
+
or callbacks via swizzling), consider the class hierarchy. If a
433
+
superclass has already been processed, processing a subclass for
434
+
the same inherited methods might be redundant or problematic. A
435
+
strategy to check if a newly set delegate is a subclass of an
436
+
already processed delegate can prevent such issues.
437
+
* For code that runs very early in the application lifecycle on
438
+
iOS/macOS (e.g., `+load` methods, static initializers involved in
439
+
swizzling), prefer using `NSLog` directly over custom logging
440
+
frameworks if there's any uncertainty about whether the custom
441
+
framework is fully initialized, to avoid crashes during logging
442
+
itself.
406
443
407
444
## Class and File Structure
408
445
@@ -468,9 +505,9 @@ management:
468
505
module, but the fundamental responsibility for creation and deletion in
469
506
typical scenarios lies with the Pimpl class itself.
470
507
471
-
It's crucial to correctly implement all these aspects (constructors, destructor,
472
-
copy/move operators) when dealing with raw pointer Pimpls to prevent memory
473
-
leaks, dangling pointers, or double deletions.
508
+
It's crucial to correctly implement all these aspects (constructors,
509
+
destructor, copy/move operators) when dealing with raw pointer Pimpls to
510
+
prevent memory leaks, dangling pointers, or double deletions.
474
511
475
512
## Namespace Usage
476
513
@@ -582,4 +619,8 @@ practices detailed in `Jules.md`.
582
619
tests as described in the 'Testing' section of `Jules.md`.
583
620
***Commit Messages**: Follow standard commit message guidelines. A brief
584
621
summary line, followed by a more detailed explanation if necessary.
585
-
***Tool Limitations & Path Specificity**: If codebase search tools (like `grep` or recursive `ls`) are limited or unavailable, and initial attempts to locate files/modules based on common directory structures are unsuccessful, explicitly ask for more specific paths rather than assuming a module doesn't exist or contains no relevant code.
622
+
***Tool Limitations & Path Specificity**: If codebase search tools (like
623
+
`grep` or recursive `ls`) are limited or unavailable, and initial attempts
624
+
to locate files/modules based on common directory structures are
625
+
unsuccessful, explicitly ask for more specific paths rather than assuming a
626
+
module doesn't exist or contains no relevant code.
NSLog(@"Firebase: Successfully swizzled [UIApplication setDelegate:] and stored original IMP.");
181
+
} else {
182
+
// This would be unusual - method_setImplementation replacing a NULL IMP,
183
+
// or method_setImplementation itself failed (though it doesn't typically return NULL on failure,
184
+
// it might return the new IMP or the old one depending on versions/runtime).
185
+
// More robustly, g_original_setDelegate_imp should be checked before use.
186
+
// For now, this logging indicates if previousImp was unexpectedly nil.
187
+
NSLog(@"Firebase Error: Swizzled [UIApplication setDelegate:], but original IMP was NULL (or method_setImplementation failed to return the previous IMP).");
0 commit comments