From 06f73270cad44d4ff1278f085e7c4058f321ad95 Mon Sep 17 00:00:00 2001 From: Matt Hayashida Date: Fri, 22 Nov 2024 13:05:24 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fix=20crash=20when=20swizzling?= =?UTF-8?q?=20for=20push=20auto=20config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Push/UNUserNotificationCenter+AutoConfig.swift | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Sources/AppcuesKit/Push/UNUserNotificationCenter+AutoConfig.swift b/Sources/AppcuesKit/Push/UNUserNotificationCenter+AutoConfig.swift index b8f87e30d..55ea84fc2 100644 --- a/Sources/AppcuesKit/Push/UNUserNotificationCenter+AutoConfig.swift +++ b/Sources/AppcuesKit/Push/UNUserNotificationCenter+AutoConfig.swift @@ -34,6 +34,8 @@ extension UNUserNotificationCenter { private func appcues__getNotificationCenterDelegate() -> UNUserNotificationCenterDelegate? { let delegate: UNUserNotificationCenterDelegate + var shouldSetDelegate = false + // this call looks recursive, but it is not, it is calling the swapped implementation // to get the actual delegate value that has been assigned, if any - can be nil if let existingDelegate = appcues__getNotificationCenterDelegate() { @@ -42,7 +44,7 @@ extension UNUserNotificationCenter { // if it is nil, then we assign our own delegate implementation so there is // something hooked in to listen to notifications delegate = AppcuesUNUserNotificationCenterDelegate.shared - self.delegate = delegate + shouldSetDelegate = true } Swizzler.swizzle( @@ -61,6 +63,15 @@ extension UNUserNotificationCenter { swizzleSelector: #selector(appcues__userNotificationCenterWillPresent) ) + // If we need to set a non-nil implementation where there previously was not one, + // swap the swizzled getter back first, then assign, then restore the swizzled getter. + // This is done to avoid infinite recursion in some cases. + if shouldSetDelegate { + UNUserNotificationCenter.swizzleNotificationCenterGetDelegate() + self.delegate = delegate + UNUserNotificationCenter.swizzleNotificationCenterGetDelegate() + } + return delegate }