diff --git a/CHANGELOG.md b/CHANGELOG.md index 935b616abdd..15cb85bbd4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Fixes - Fix potential deadlock in app hang detection (#4063) +- Swizzling of view controllers `loadView` that don`t implement `loadView` (#4071) ## 8.29.0 diff --git a/Samples/iOS-Swift/iOS-Swift/Tools/UIAssert.swift b/Samples/iOS-Swift/iOS-Swift/Tools/UIAssert.swift index 7b591a3d1ed..2769e9909c3 100644 --- a/Samples/iOS-Swift/iOS-Swift/Tools/UIAssert.swift +++ b/Samples/iOS-Swift/iOS-Swift/Tools/UIAssert.swift @@ -84,7 +84,7 @@ class UIAssert { return } - let steps = stepsToCheck ?? ["loadView", "viewDidLoad", "viewWillAppear", "viewDidAppear"] + let steps = stepsToCheck ?? ["viewDidLoad", "viewWillAppear", "viewDidAppear"] var missing = [String]() steps.forEach { spanDescription in diff --git a/Sources/Sentry/SentryUIViewControllerSwizzling.m b/Sources/Sentry/SentryUIViewControllerSwizzling.m index 88564b33035..45c25b75fdf 100644 --- a/Sources/Sentry/SentryUIViewControllerSwizzling.m +++ b/Sources/Sentry/SentryUIViewControllerSwizzling.m @@ -348,13 +348,15 @@ - (BOOL)shouldSwizzleViewController:(Class)class - (void)swizzleLoadView:(Class)class { - // The UIViewController only searches for a nib file if you do not override the loadView method. + // Loading a Nib file is done automatically during `loadView` in the UIViewController + // or other native view controllers. // When swizzling the loadView of a custom UIViewController, the UIViewController doesn't search - // for a nib file and doesn't load a view. This would lead to crashes as no view is loaded. As a - // workaround, we skip swizzling the loadView and accept that the SKD doesn't create a span for - // loadView if the UIViewController doesn't implement it. + // for a nib file and doesn't load a view. This would lead to crashes as no view is loaded. + // By checking the implementation pointer of `loadView` from the current class with + // the implementation pointer of its parent class, we can determine if current class + // has a custom implementation of it, therefore it's safe to swizzle it. SEL selector = NSSelectorFromString(@"loadView"); - IMP viewControllerImp = class_getMethodImplementation([UIViewController class], selector); + IMP viewControllerImp = class_getMethodImplementation([class superclass], selector); IMP classLoadViewImp = class_getMethodImplementation(class, selector); if (viewControllerImp == classLoadViewImp) { return;