Skip to content

Commit 8071976

Browse files
iOS: Allow specifying your AppDelegate class's name in the Info.plist file. (#1741)
* Feature: Allow specifying AppDelegate via Info.plist for RunOnAppDelegateClasses Currently, `firebase::util::RunOnAppDelegateClasses` on iOS automatically swizzles `[UIApplication setDelegate:]` to capture and act on any class set as the application delegate. This change introduces an optional feature where developers can specify their app's main AppDelegate class name directly in the `Info.plist` file using the key `FirebaseAppDelegateClassName`. If this key is present and provides a valid class name: - `RunOnAppDelegateClasses` will only execute blocks for this specified class. - `[UIApplication setDelegate:]` will NOT be swizzled by Firebase. If the key is not present, is invalid, or the specified class is not found, Firebase will fall back to the original behavior of swizzling `[UIApplication setDelegate:]`. This provides developers more control over Firebase's interaction with the AppDelegate, especially in scenarios where swizzling might be undesirable or needs to be more targeted. Detailed logging has been added to trace the behavior in both modes. A manual testing plan has been outlined to cover various scenarios. * Feature: Allow specifying AppDelegate via Info.plist for RunOnAppDelegateClasses (Refined) Currently, `firebase::util::RunOnAppDelegateClasses` on iOS automatically swizzles `[UIApplication setDelegate:]` to capture and act on any class set as the application delegate. This change introduces an optional feature where developers can specify their app's main AppDelegate class name directly in the `Info.plist` file using the key `FirebaseAppDelegateClassName`. If this key is present and provides a valid class name: - `RunOnAppDelegateClasses` will only execute blocks for this specified class. - Pending blocks are processed once for this target. - New blocks execute immediately on this target and are not queued for others. - `[UIApplication setDelegate:]` will NOT be swizzled by Firebase. If the key is not present, is invalid, or the specified class is not found, Firebase will fall back to the original behavior of swizzling `[UIApplication setDelegate:]`. This provides developers more control over Firebase's interaction with the AppDelegate. The implementation of `RunOnAppDelegateClasses` has been refined to support this new mode more simply while ensuring correct block execution and pending queue management. Detailed logging has been added. A manual testing plan is provided. * Refactor: Improve comments and logging for AppDelegate Info.plist feature This commit cleans up comments and refines logging messages within the `+load` method in `FirebaseAppDelegateSwizzling` category for clarity and accuracy related to the recently added feature for specifying the AppDelegate via Info.plist. - Clarified comments explaining the Info.plist handling path, including the setup of the specified delegate and the execution of pending blocks. - Ensured comments accurately reflect that pending blocks are not cleared from the queue after execution in `+load` when in Info.plist mode. - Minor wording improvements to log messages for better diagnostics. - Removed redundant or outdated comments from previous iterations. No functional code changes are included in this commit. * Docs: Simplify AppDelegate Info.plist option in README Further refines the documentation for the `FirebaseAppDelegateClassName` Info.plist key feature on iOS. - The explanation in `release_build_files/readme.md` under "Specifying Your AppDelegate Class Directly (iOS)" has been made more concise and user-focused, removing internal implementation details. - The corresponding release note for version 12.9.0 has also been simplified to match this approach. This change aims to make the documentation easier for developers to understand by focusing on the action and benefit rather than Firebase internal mechanisms. * Docs: Use generic 'Upcoming Release' title in README Changes the heading for the newest release notes entry from '### 12.9.0 (Upcoming)' to '### Upcoming Release' as the specific version number is not yet known. * Update logging to not be verbose unless debug logs are on. Also clean up NSLog messages elsewhere. * Update log message. * Fix build error. * Format code. --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
1 parent 889ab61 commit 8071976

File tree

2 files changed

+183
-68
lines changed

2 files changed

+183
-68
lines changed

app/src/util_ios.mm

Lines changed: 151 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@
2727
#import <UIKit/UIKit.h>
2828
#import <objc/runtime.h>
2929

30+
using firebase::GetLogLevel;
31+
32+
// Key used in Info.plist to specify a custom AppDelegate class name.
33+
static NSString *const kFirebaseAppDelegateClassNameKey = @"FirebaseAppDelegateClassName";
34+
3035
#define MAX_PENDING_APP_DELEGATE_BLOCKS 8
3136
#define MAX_SEEN_DELEGATE_CLASSES 32
3237

@@ -40,10 +45,12 @@ static void Firebase_setDelegate(id self, SEL _cmd, id<UIApplicationDelegate> de
4045
Class new_class = nil;
4146
if (delegate) {
4247
new_class = [delegate class];
43-
NSLog(@"Firebase: UIApplication setDelegate: called with class %s (Swizzled)",
44-
class_getName(new_class));
48+
if (GetLogLevel() <= kLogLevelDebug)
49+
NSLog(@"Firebase: UIApplication setDelegate: called with class %s (Swizzled)",
50+
class_getName(new_class));
4551
} else {
46-
NSLog(@"Firebase: UIApplication setDelegate: called with nil delegate (Swizzled)");
52+
if (GetLogLevel() <= kLogLevelDebug)
53+
NSLog(@"Firebase: UIApplication setDelegate: called with nil delegate (Swizzled)");
4754
}
4855

4956
if (new_class) {
@@ -54,8 +61,10 @@ static void Firebase_setDelegate(id self, SEL _cmd, id<UIApplicationDelegate> de
5461
for (int i = 0; i < g_seen_delegate_classes_count; i++) {
5562
if (g_seen_delegate_classes[i] == current_super) {
5663
superclass_already_seen = true;
57-
NSLog(@"Firebase: Delegate class %s has superclass %s which was already seen. Skipping processing for %s.",
58-
class_getName(new_class), class_getName(current_super), class_getName(new_class));
64+
if (GetLogLevel() <= kLogLevelDebug)
65+
NSLog(@"Firebase: Delegate class %s has superclass %s which was already seen. Skipping "
66+
@"processing for %s.",
67+
class_getName(new_class), class_getName(current_super), class_getName(new_class));
5968
break;
6069
}
6170
}
@@ -69,8 +78,9 @@ static void Firebase_setDelegate(id self, SEL _cmd, id<UIApplicationDelegate> de
6978
for (int i = 0; i < g_seen_delegate_classes_count; i++) {
7079
if (g_seen_delegate_classes[i] == new_class) {
7180
direct_class_already_seen = true;
72-
NSLog(@"Firebase: Delegate class %s already seen directly. Skipping processing.",
73-
class_getName(new_class));
81+
if (GetLogLevel() <= kLogLevelDebug)
82+
NSLog(@"Firebase: Delegate class %s already seen directly. Skipping processing.",
83+
class_getName(new_class));
7484
break;
7585
}
7686
}
@@ -80,12 +90,14 @@ static void Firebase_setDelegate(id self, SEL _cmd, id<UIApplicationDelegate> de
8090
if (g_seen_delegate_classes_count < MAX_SEEN_DELEGATE_CLASSES) {
8191
g_seen_delegate_classes[g_seen_delegate_classes_count] = new_class;
8292
g_seen_delegate_classes_count++;
83-
NSLog(@"Firebase: Added new delegate class %s to seen list (total seen: %d).",
84-
class_getName(new_class), g_seen_delegate_classes_count);
93+
if (GetLogLevel() <= kLogLevelDebug)
94+
NSLog(@"Firebase: Added new delegate class %s to seen list (total seen: %d).",
95+
class_getName(new_class), g_seen_delegate_classes_count);
8596

8697
if (g_pending_block_count > 0) {
87-
NSLog(@"Firebase: Executing %d pending block(s) for new delegate class: %s.",
88-
g_pending_block_count, class_getName(new_class));
98+
if (GetLogLevel() <= kLogLevelDebug)
99+
NSLog(@"Firebase: Executing %d pending block(s) for new delegate class: %s.",
100+
g_pending_block_count, class_getName(new_class));
89101
for (int i = 0; i < g_pending_block_count; i++) {
90102
if (g_pending_app_delegate_blocks[i]) {
91103
g_pending_app_delegate_blocks[i](new_class);
@@ -94,7 +106,8 @@ static void Firebase_setDelegate(id self, SEL _cmd, id<UIApplicationDelegate> de
94106
}
95107
}
96108
} else {
97-
NSLog(@"Firebase Error: Exceeded MAX_SEEN_DELEGATE_CLASSES (%d). Cannot add new delegate class %s or run pending blocks for it.",
109+
NSLog(@"Firebase Error: Exceeded MAX_SEEN_DELEGATE_CLASSES (%d). Cannot add new delegate "
110+
@"class %s or run pending blocks for it.",
98111
MAX_SEEN_DELEGATE_CLASSES, class_getName(new_class));
99112
}
100113
}
@@ -103,7 +116,8 @@ static void Firebase_setDelegate(id self, SEL _cmd, id<UIApplicationDelegate> de
103116

104117
// Call the original setDelegate: implementation
105118
if (g_original_setDelegate_imp) {
106-
((void (*)(id, SEL, id<UIApplicationDelegate>))g_original_setDelegate_imp)(self, _cmd, delegate);
119+
((void (*)(id, SEL, id<UIApplicationDelegate>))g_original_setDelegate_imp)(self, _cmd,
120+
delegate);
107121
} else {
108122
NSLog(@"Firebase Error: Original setDelegate: IMP not found, cannot call original method.");
109123
}
@@ -163,28 +177,89 @@ @implementation UIApplication (FirebaseAppDelegateSwizzling)
163177
+ (void)load {
164178
static dispatch_once_t onceToken;
165179
dispatch_once(&onceToken, ^{
180+
NSString *appDelegateClassName =
181+
[[NSBundle mainBundle] objectForInfoDictionaryKey:kFirebaseAppDelegateClassNameKey];
182+
183+
if (appDelegateClassName && [appDelegateClassName isKindOfClass:[NSString class]] &&
184+
appDelegateClassName.length > 0) {
185+
Class specificClass = NSClassFromString(appDelegateClassName);
186+
if (specificClass) {
187+
if (GetLogLevel() <= kLogLevelDebug)
188+
NSLog(@"Firebase: Info.plist key '%@' found. Targeting AppDelegate class: %@. Swizzling "
189+
@"of [UIApplication setDelegate:] will be skipped.",
190+
kFirebaseAppDelegateClassNameKey, appDelegateClassName);
191+
192+
// Set this class as the sole "seen" delegate for Firebase processing.
193+
// g_seen_delegate_classes_count should be 0 here in +load, but clear just in case.
194+
for (int i = 0; i < g_seen_delegate_classes_count; i++) {
195+
g_seen_delegate_classes[i] = nil;
196+
}
197+
g_seen_delegate_classes[0] = specificClass;
198+
g_seen_delegate_classes_count = 1;
199+
if (GetLogLevel() <= kLogLevelDebug)
200+
NSLog(@"Firebase: %@ is now the only delegate class Firebase will initially process.",
201+
appDelegateClassName);
202+
203+
// If there are already blocks pending (e.g., from other Firebase components' +load
204+
// methods), execute them now for the specified delegate. These blocks will remain in the
205+
// pending queue, mirroring the behavior of the original swizzled setDelegate: method which
206+
// also does not clear pending blocks after execution (as they might apply to future
207+
// delegates). In this Info.plist mode, however, Firebase won't process further setDelegate:
208+
// calls.
209+
if (g_pending_block_count > 0) {
210+
if (GetLogLevel() <= kLogLevelDebug)
211+
NSLog(@"Firebase: +load (Info.plist Mode) - Executing %d PENDING block(s) for "
212+
@"specified delegate: %@. (Blocks are not removed from queue).",
213+
g_pending_block_count, NSStringFromClass(specificClass));
214+
for (int i = 0; i < g_pending_block_count; i++) {
215+
if (g_pending_app_delegate_blocks[i]) {
216+
g_pending_app_delegate_blocks[i](specificClass);
217+
}
218+
}
219+
if (GetLogLevel() <= kLogLevelDebug)
220+
NSLog(@"Firebase: +load (Info.plist Mode) - Pending blocks executed for specific "
221+
@"delegate.");
222+
}
223+
// Skip swizzling. g_original_setDelegate_imp remains NULL.
224+
return;
225+
} else {
226+
NSLog(@"Firebase Error: Info.plist key '%@' specifies class '%@', which was not found. "
227+
@"Proceeding with default swizzling.",
228+
kFirebaseAppDelegateClassNameKey, appDelegateClassName);
229+
}
230+
} else {
231+
if (appDelegateClassName) { // Key is present but value is invalid (e.g., empty string or
232+
// wrong type).
233+
NSLog(@"Firebase Error: Info.plist key '%@' has an invalid value ('%@'). Proceeding "
234+
@"with default swizzling.",
235+
kFirebaseAppDelegateClassNameKey, appDelegateClassName);
236+
} else { // Key is not present.
237+
// This is the default case, no special logging needed here beyond the swizzling log itself.
238+
}
239+
}
240+
241+
// Standard behavior: Swizzle [UIApplication setDelegate:]
242+
if (GetLogLevel() <= kLogLevelDebug)
243+
NSLog(@"Firebase: Proceeding with swizzling of [UIApplication setDelegate:].");
166244
Class uiApplicationClass = [UIApplication class];
167245
SEL originalSelector = @selector(setDelegate:);
168246
Method originalMethod = class_getInstanceMethod(uiApplicationClass, originalSelector);
169247

170248
if (!originalMethod) {
171-
NSLog(@"Firebase Error: Original [UIApplication setDelegate:] method not found for swizzling.");
249+
NSLog(
250+
@"Firebase Error: Original [UIApplication setDelegate:] method not found for swizzling.");
172251
return;
173252
}
174253

175-
// Replace the original method's implementation with Firebase_setDelegate
176-
// and store the original IMP.
177254
IMP previousImp = method_setImplementation(originalMethod, (IMP)Firebase_setDelegate);
178255
if (previousImp) {
179-
g_original_setDelegate_imp = previousImp;
180-
NSLog(@"Firebase: Successfully swizzled [UIApplication setDelegate:] and stored original IMP.");
256+
g_original_setDelegate_imp = previousImp;
257+
if (GetLogLevel() <= kLogLevelDebug)
258+
NSLog(@"Firebase: Successfully swizzled [UIApplication setDelegate:] and stored original "
259+
@"IMP.");
181260
} 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).");
261+
NSLog(@"Firebase Error: Swizzled [UIApplication setDelegate:], but original IMP was NULL (or "
262+
@"method_setImplementation failed to return the previous IMP).");
188263
}
189264
});
190265
}
@@ -196,24 +271,33 @@ + (void)load {
196271

197272
void RunOnAppDelegateClasses(void (^block)(Class)) {
198273
if (g_seen_delegate_classes_count > 0) {
199-
NSLog(@"Firebase: RunOnAppDelegateClasses executing block for %d already seen delegate class(es).",
200-
g_seen_delegate_classes_count);
274+
if (GetLogLevel() <= kLogLevelDebug)
275+
NSLog(@"Firebase: RunOnAppDelegateClasses executing block for %d already seen delegate "
276+
@"class(es).",
277+
g_seen_delegate_classes_count);
201278
for (int i = 0; i < g_seen_delegate_classes_count; i++) {
202-
if (g_seen_delegate_classes[i]) { // Safety check
279+
if (g_seen_delegate_classes[i]) { // Safety check
203280
block(g_seen_delegate_classes[i]);
204281
}
205282
}
206283
} else {
207-
NSLog(@"Firebase: RunOnAppDelegateClasses - no delegate classes seen yet. Block will be queued for future delegates.");
284+
if (GetLogLevel() <= kLogLevelDebug)
285+
NSLog(@"Firebase: RunOnAppDelegateClasses - no delegate classes seen yet. Block will be "
286+
@"queued for future delegates.");
208287
}
209288

210289
// Always try to queue the block for any future new delegate classes.
211290
if (g_pending_block_count < MAX_PENDING_APP_DELEGATE_BLOCKS) {
212291
g_pending_app_delegate_blocks[g_pending_block_count] = [block copy];
213292
g_pending_block_count++;
214-
NSLog(@"Firebase: RunOnAppDelegateClasses - added block to pending list (total pending: %d). This block will run on future new delegate classes.", g_pending_block_count);
293+
if (GetLogLevel() <= kLogLevelDebug)
294+
NSLog(@"Firebase: RunOnAppDelegateClasses - added block to pending list (total pending: %d). "
295+
@"This block will run on future new delegate classes.",
296+
g_pending_block_count);
215297
} else {
216-
NSLog(@"Firebase Error: RunOnAppDelegateClasses - pending block queue is full (max %d). Cannot add new block for future execution. Discarding block.", MAX_PENDING_APP_DELEGATE_BLOCKS);
298+
NSLog(@"Firebase Error: RunOnAppDelegateClasses - pending block queue is full (max %d). Cannot "
299+
@"add new block for future execution. Discarding block.",
300+
MAX_PENDING_APP_DELEGATE_BLOCKS);
217301
}
218302
}
219303

@@ -458,24 +542,26 @@ void RunOnBackgroundThread(void (*function_ptr)(void *function_data), void *func
458542
const char *class_name = class_getName(clazz);
459543
Method method = class_getInstanceMethod(clazz, name);
460544
NSString *selector_name_nsstring = NSStringFromSelector(name);
461-
const char *selector_name = selector_name_nsstring.UTF8String; // Used for logging later
545+
const char *selector_name = selector_name_nsstring.UTF8String; // Used for logging later
462546

463547
IMP current_actual_imp = method ? method_getImplementation(method) : nil;
464548

465549
// === Begin idempotency check ===
466550
if (current_actual_imp == imp) {
467551
// Assuming GetLogLevel() and kLogLevelDebug are available here.
468552
// Based on previous file content, GetLogLevel is available in this file from util_ios.h.
469-
if (GetLogLevel() <= kLogLevelDebug) {
470-
NSLog(@"Firebase Cache: Method %s on class %s is already swizzled with the target IMP. Skipping re-swizzle.",
553+
if (GetLogLevel() <= kLogLevelDebug)
554+
NSLog(@"Firebase: Method %s on class %s is already swizzled with the target IMP. Skipping "
555+
@"re-swizzle.",
471556
selector_name, class_name);
472-
}
473-
return; // Already swizzled to the desired implementation
557+
558+
return; // Already swizzled to the desired implementation
474559
}
475560
// === End idempotency check ===
476561

477562
// If we reach here, current_actual_imp is different from imp, or the method didn't exist.
478-
// We now assign original_method_implementation to be current_actual_imp for the rest of the function.
563+
// We now assign original_method_implementation to be current_actual_imp for the rest of the
564+
// function.
479565
IMP original_method_implementation = current_actual_imp;
480566

481567
// Get the type encoding of the selector from a type_encoding_class (which is a class which
@@ -485,9 +571,9 @@ void RunOnBackgroundThread(void (*function_ptr)(void *function_data), void *func
485571
assert(type_encoding);
486572

487573
NSString *new_method_name_nsstring = nil;
488-
if (GetLogLevel() <= kLogLevelDebug) {
489-
NSLog(@"Firebase Cache: Attempting to register method for %s selector %s", class_name, selector_name);
490-
}
574+
if (GetLogLevel() <= kLogLevelDebug)
575+
NSLog(@"Firebase: Attempting to register method for %s selector %s", class_name, selector_name);
576+
491577
if (original_method_implementation) {
492578
// Try adding a method with randomized prefix on the name.
493579
int retry = kRandomNameGenerationRetries;
@@ -502,32 +588,32 @@ void RunOnBackgroundThread(void (*function_ptr)(void *function_data), void *func
502588
}
503589
const char *new_method_name = new_method_name_nsstring.UTF8String;
504590
if (retry == 0) {
505-
NSLog(@"Failed to add method %s on class %s as the %s method already exists on the class. To "
506-
@"resolve this issue, change the name of the method %s on the class %s.",
507-
new_method_name, class_name, new_method_name, new_method_name, class_name);
591+
NSLog(
592+
@"Firebase Error: Failed to add method %s on class %s as the %s method already exists on "
593+
@"the class. To resolve this issue, change the name of the method %s on the class %s.",
594+
new_method_name, class_name, new_method_name, new_method_name, class_name);
508595
return;
509596
}
510597
method_setImplementation(method, imp);
511598
// Save the selector name that points at the original method implementation.
512599
SetMethod(name, new_method_name_nsstring);
513-
if (GetLogLevel() <= kLogLevelDebug) {
514-
NSLog(@"Registered method for %s selector %s (original method %s 0x%08x)", class_name,
515-
selector_name, new_method_name,
600+
if (GetLogLevel() <= kLogLevelDebug)
601+
NSLog(@"Firebase: Registered method for %s selector %s (original method %s 0x%08x)",
602+
class_name, selector_name, new_method_name,
516603
static_cast<int>(reinterpret_cast<intptr_t>(original_method_implementation)));
517-
}
604+
518605
} else if (add_method) {
519-
if (GetLogLevel() <= kLogLevelDebug) {
520-
NSLog(@"Adding method for %s selector %s", class_name, selector_name);
521-
}
606+
if (GetLogLevel() <= kLogLevelDebug)
607+
NSLog(@"Firebase: Adding method for %s selector %s", class_name, selector_name);
608+
522609
// The class doesn't implement the selector so simply install our method implementation.
523610
if (!class_addMethod(clazz, name, imp, type_encoding)) {
524-
NSLog(@"Failed to add new method %s on class %s.", selector_name, class_name);
611+
NSLog(@"Firebase Error: Failed to add new method %s on class %s.", selector_name, class_name);
525612
}
526613
} else {
527-
if (GetLogLevel() <= kLogLevelDebug) {
528-
NSLog(@"Method implementation for %s selector %s not found, ignoring.", class_name,
614+
if (GetLogLevel() <= kLogLevelDebug)
615+
NSLog(@"Firebase: Method implementation for %s selector %s not found, ignoring.", class_name,
529616
selector_name);
530-
}
531617
}
532618
}
533619

@@ -541,9 +627,9 @@ void RunOnBackgroundThread(void (*function_ptr)(void *function_data), void *func
541627
selector_implementation_names_per_selector_[selector_name_nsstring];
542628
const char *class_name = class_getName(clazz);
543629
if (!selector_implementation_names) {
544-
if (GetLogLevel() <= kLogLevelDebug) {
545-
NSLog(@"Method not cached for class %s selector %s.", class_name, selector_name);
546-
}
630+
if (GetLogLevel() <= kLogLevelDebug)
631+
NSLog(@"Firebase: Method not cached for class %s selector %s.", class_name, selector_name);
632+
547633
return nil;
548634
}
549635

@@ -561,29 +647,29 @@ void RunOnBackgroundThread(void (*function_ptr)(void *function_data), void *func
561647
search_class = clazz;
562648
for (; search_class; search_class = class_getSuperclass(search_class)) {
563649
const char *search_class_name = class_getName(search_class);
564-
if (GetLogLevel() <= kLogLevelDebug) {
565-
NSLog(@"Searching for selector %s (%s) on class %s", selector_name,
650+
if (GetLogLevel() <= kLogLevelDebug)
651+
NSLog(@"Firebase: Searching for selector %s (%s) on class %s", selector_name,
566652
selector_implementation_name, search_class_name);
567-
}
653+
568654
Method method = class_getInstanceMethod(search_class, selector_implementation);
569655
method_implementation = method ? method_getImplementation(method) : nil;
570656
if (method_implementation) break;
571657
}
572658
if (method_implementation) break;
573659
}
574660
if (!method_implementation) {
575-
if (GetLogLevel() <= kLogLevelDebug) {
576-
NSLog(@"Class %s does not respond to selector %s (%s)", class_name, selector_name,
661+
if (GetLogLevel() <= kLogLevelDebug)
662+
NSLog(@"Firebase: Class %s does not respond to selector %s (%s)", class_name, selector_name,
577663
selector_implementation_name_nsstring.UTF8String);
578-
}
664+
579665
return nil;
580666
}
581-
if (GetLogLevel() <= kLogLevelDebug) {
582-
NSLog(@"Found %s (%s, 0x%08x) on class %s (%s)", selector_name,
667+
if (GetLogLevel() <= kLogLevelDebug)
668+
NSLog(@"Firebase: Found %s (%s, 0x%08x) on class %s (%s)", selector_name,
583669
selector_implementation_name_nsstring.UTF8String,
584670
static_cast<int>(reinterpret_cast<intptr_t>(method_implementation)), class_name,
585671
class_getName(search_class));
586-
}
672+
587673
return method_implementation;
588674
}
589675

0 commit comments

Comments
 (0)