From 6b861fe77c47e44e4401cb8d0033ded538a5b128 Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Fri, 29 Aug 2025 11:56:31 -0300 Subject: [PATCH 01/22] Convert `SentryReachability` to Swift --- Sentry.xcodeproj/project.pbxproj | 20 +- .../SentryTestUtils-ObjC-BridgingHeader.h | 1 - Sources/Sentry/SentryBreadcrumbTracker.m | 5 +- Sources/Sentry/SentryDependencyContainer.m | 8 +- Sources/Sentry/SentryHttpTransport.m | 10 +- Sources/Sentry/SentryReachability.m | 264 ------------------ .../Sentry/SentrySessionReplayIntegration.m | 1 - Sources/Sentry/include/SentryReachability.h | 96 ------- Sources/Sentry/include/SentrySwift.h | 7 + .../Swift/Networking/SentryReachability.swift | 263 +++++++++++++++++ .../SentryBreadcrumbTrackerTests.swift | 16 +- .../SentryReachabilitySwiftTests.swift | 1 + .../Networking/SentryReachabilityTests.m | 68 +++-- .../Networking/TestSentryReachability.swift | 17 +- .../SentryTests/SentryTests-Bridging-Header.h | 4 - 15 files changed, 348 insertions(+), 433 deletions(-) delete mode 100644 Sources/Sentry/SentryReachability.m delete mode 100644 Sources/Sentry/include/SentryReachability.h create mode 100644 Sources/Swift/Networking/SentryReachability.swift diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index 0a84ebb6871..d465df026c9 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -48,8 +48,6 @@ 0A9BF4E928A125390068D266 /* TestSentryViewHierarchyProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9BF4E628A123270068D266 /* TestSentryViewHierarchyProvider.swift */; }; 0A9BF4EB28A127120068D266 /* SentryViewHierarchyIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9BF4EA28A127120068D266 /* SentryViewHierarchyIntegrationTests.swift */; }; 0A9E917128DC7E7000FB4182 /* SentryInternalCDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A9E917028DC7E7000FB4182 /* SentryInternalCDefines.h */; }; - 0AAE201E28ED9B9400D0CD80 /* SentryReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AAE201D28ED9B9400D0CD80 /* SentryReachability.m */; }; - 0AAE202128ED9BCC00D0CD80 /* SentryReachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 0AAE202028ED9BCC00D0CD80 /* SentryReachability.h */; }; 0ADC33F128D9BE940078D980 /* TestSentryUIDeviceWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ADC33EF28D9BE690078D980 /* TestSentryUIDeviceWrapper.swift */; }; 0AE455AD28F584D2006680E5 /* SentryReachabilityTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AE455AC28F584D2006680E5 /* SentryReachabilityTests.m */; }; 15360CCF2432777500112302 /* SentrySessionTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 15360CCE2432777400112302 /* SentrySessionTracker.m */; }; @@ -1039,6 +1037,7 @@ F458D1192E186E000028273E /* SentryScopePersistentStore+Extras.swift in Sources */ = {isa = PBXBuildFile; fileRef = F458D1182E186E000028273E /* SentryScopePersistentStore+Extras.swift */; }; F46DA6C32E1DBCA000DF6E3B /* SentryScopePersistentStore+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F46DA6C22E1DBCA000DF6E3B /* SentryScopePersistentStore+Helper.swift */; }; F48F767C2E60B555009D4E7D /* SentryNSTimerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48F767B2E60B555009D4E7D /* SentryNSTimerFactory.swift */; }; + F48F78692E61DE28009D4E7D /* SentryReachability.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48F78682E61DE28009D4E7D /* SentryReachability.swift */; }; F49D41982DEA27AF00D9244E /* SentryUseNSExceptionCallstackWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49D41972DEA27AF00D9244E /* SentryUseNSExceptionCallstackWrapperTests.swift */; }; F49D419A2DEA2FB000D9244E /* SentryCrashExceptionApplicationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49D41992DEA2FB000D9244E /* SentryCrashExceptionApplicationTests.swift */; }; F49D419C2DEA30C300D9244E /* SentryCrashExceptionApplicationHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = F49D419B2DEA30B800D9244E /* SentryCrashExceptionApplicationHelper.h */; }; @@ -1282,8 +1281,6 @@ 0A9BF4E628A123270068D266 /* TestSentryViewHierarchyProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSentryViewHierarchyProvider.swift; sourceTree = ""; }; 0A9BF4EA28A127120068D266 /* SentryViewHierarchyIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryViewHierarchyIntegrationTests.swift; sourceTree = ""; }; 0A9E917028DC7E7000FB4182 /* SentryInternalCDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryInternalCDefines.h; path = include/SentryInternalCDefines.h; sourceTree = ""; }; - 0AAE201D28ED9B9400D0CD80 /* SentryReachability.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryReachability.m; sourceTree = ""; }; - 0AAE202028ED9BCC00D0CD80 /* SentryReachability.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryReachability.h; path = include/SentryReachability.h; sourceTree = ""; }; 0ADC33EF28D9BE690078D980 /* TestSentryUIDeviceWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSentryUIDeviceWrapper.swift; sourceTree = ""; }; 0AE455AC28F584D2006680E5 /* SentryReachabilityTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryReachabilityTests.m; sourceTree = ""; }; 15360CCE2432777400112302 /* SentrySessionTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentrySessionTracker.m; sourceTree = ""; }; @@ -2383,6 +2380,7 @@ F458D1182E186E000028273E /* SentryScopePersistentStore+Extras.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentryScopePersistentStore+Extras.swift"; sourceTree = ""; }; F46DA6C22E1DBCA000DF6E3B /* SentryScopePersistentStore+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentryScopePersistentStore+Helper.swift"; sourceTree = ""; }; F48F767B2E60B555009D4E7D /* SentryNSTimerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryNSTimerFactory.swift; sourceTree = ""; }; + F48F78682E61DE28009D4E7D /* SentryReachability.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryReachability.swift; sourceTree = ""; }; F49D41972DEA27AF00D9244E /* SentryUseNSExceptionCallstackWrapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryUseNSExceptionCallstackWrapperTests.swift; sourceTree = ""; }; F49D41992DEA2FB000D9244E /* SentryCrashExceptionApplicationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashExceptionApplicationTests.swift; sourceTree = ""; }; F49D419B2DEA30B800D9244E /* SentryCrashExceptionApplicationHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryCrashExceptionApplicationHelper.h; path = include/SentryCrashExceptionApplicationHelper.h; sourceTree = ""; }; @@ -2667,8 +2665,6 @@ 84AC61D029F7541E009EEF61 /* SentryDispatchSourceWrapper.h */, 84AC61D429F75A98009EEF61 /* SentryDispatchFactory.h */, 84AC61D529F75A98009EEF61 /* SentryDispatchFactory.m */, - 0AAE202028ED9BCC00D0CD80 /* SentryReachability.h */, - 0AAE201D28ED9B9400D0CD80 /* SentryReachability.m */, ); name = Networking; sourceTree = ""; @@ -4331,6 +4327,7 @@ D800942328F82E8D005D3943 /* Swift */ = { isa = PBXGroup; children = ( + F48F78672E61DE08009D4E7D /* Networking */, FABB48B22E59310D0071397E /* Transaction */, FA67DCF32DDBD4EA00896B02 /* Core */, D8CAC02D2BA0663E00E38F34 /* Integrations */, @@ -4735,6 +4732,14 @@ name = "Recovered References"; sourceTree = ""; }; + F48F78672E61DE08009D4E7D /* Networking */ = { + isa = PBXGroup; + children = ( + F48F78682E61DE28009D4E7D /* SentryReachability.swift */, + ); + path = Networking; + sourceTree = ""; + }; FA67DCC62DDBD4EA00896B02 /* Extensions */ = { isa = PBXGroup; children = ( @@ -4974,7 +4979,6 @@ D8739D172BEEA33F007D2F66 /* SentryLevelHelper.h in Headers */, 8E4A037825F6F52100000D77 /* SentrySampleDecision.h in Headers */, 63FE717920DA4C1100CDBAE8 /* SentryCrashReportStore.h in Headers */, - 0AAE202128ED9BCC00D0CD80 /* SentryReachability.h in Headers */, D858FA662A29EAB3002A3503 /* SentryBinaryImageCache.h in Headers */, A839D89824864B80003B7AFD /* SentrySystemEventBreadcrumbs.h in Headers */, 7B14089624878F090035403D /* SentryCrashStackEntryMapper.h in Headers */, @@ -5588,6 +5592,7 @@ 7B8713B426415BAA006D6004 /* SentryAppStartTracker.m in Sources */, 7BDB03BB2513652900BAE198 /* _SentryDispatchQueueWrapperInternal.m in Sources */, FA6FC0A32E0B5ACE00ED2669 /* SentrySdkPackage.swift in Sources */, + F48F78692E61DE28009D4E7D /* SentryReachability.swift in Sources */, D8739D142BEE5049007D2F66 /* SentryRRWebSpanEvent.swift in Sources */, FAAB2F972E4D345800FE8B7E /* SentryUIDeviceWrapper.swift in Sources */, 7B6C5EDE264E8DF00010D138 /* SentryFramesTracker.m in Sources */, @@ -5742,7 +5747,6 @@ 7DB3A687238EA75E00A2D442 /* SentryHttpTransport.m in Sources */, 63FE70D520DA4C1000CDBAE8 /* SentryCrashMonitor_NSException.m in Sources */, 62F70E952D423BCD00634054 /* SentryMechanismCodable.swift in Sources */, - 0AAE201E28ED9B9400D0CD80 /* SentryReachability.m in Sources */, 7B0A54282521C22C00A71716 /* SentryFrameRemover.m in Sources */, 6283085F2D50AA8C00EAEF77 /* SentryMessage.swift in Sources */, 7BC63F0A28081288009D9E37 /* SentrySwizzleWrapper.m in Sources */, diff --git a/SentryTestUtils/SentryTestUtils-ObjC-BridgingHeader.h b/SentryTestUtils/SentryTestUtils-ObjC-BridgingHeader.h index adcfb473e48..475aa09aab1 100644 --- a/SentryTestUtils/SentryTestUtils-ObjC-BridgingHeader.h +++ b/SentryTestUtils/SentryTestUtils-ObjC-BridgingHeader.h @@ -46,7 +46,6 @@ #import "SentryNSProcessInfoWrapper.h" #import "SentryNetworkTracker.h" #import "SentryPerformanceTracker+Testing.h" -#import "SentryReachability.h" #import "SentrySDK+Private.h" #import "SentrySDKInternal+Tests.h" #import "SentryScopeSyncC.h" diff --git a/Sources/Sentry/SentryBreadcrumbTracker.m b/Sources/Sentry/SentryBreadcrumbTracker.m index 872aefaadc9..5264a160242 100644 --- a/Sources/Sentry/SentryBreadcrumbTracker.m +++ b/Sources/Sentry/SentryBreadcrumbTracker.m @@ -7,7 +7,6 @@ #import "SentryHub.h" #import "SentryInternalDefines.h" #import "SentryLogC.h" -#import "SentryReachability.h" #import "SentryScope.h" #import "SentrySwift.h" #import "SentrySwizzle.h" @@ -83,7 +82,7 @@ - (void)stop _delegate = nil; #if SENTRY_HAS_REACHABILITY [self stopTrackNetworkConnectivityChanges]; -#endif // !TARGET_OS_WATCH +#endif // SENTRY_HAS_REACHABILITY } - (void)trackApplicationNotifications @@ -163,7 +162,7 @@ - (void)connectivityChanged:(BOOL)connected typeDescription:(nonnull NSString *) [self.delegate addBreadcrumb:crumb]; } -#endif // !TARGET_OS_WATCH +#endif // SENTRY_HAS_REACHABILITY - (void)addBreadcrumbWithType:(NSString *)type withCategory:(NSString *)category diff --git a/Sources/Sentry/SentryDependencyContainer.m b/Sources/Sentry/SentryDependencyContainer.m index ce790cfd606..2b42d8e0e5c 100644 --- a/Sources/Sentry/SentryDependencyContainer.m +++ b/Sources/Sentry/SentryDependencyContainer.m @@ -51,10 +51,6 @@ # import "SentryNSApplication.h" #endif -#if !TARGET_OS_WATCH -# import "SentryReachability.h" -#endif // !TARGET_OS_WATCH - /** * Macro for implementing lazy initialization with a double-checked lock. The double-checked lock * speeds up the dependency retrieval by around 5%, so it's worth having it. Measured with @@ -128,7 +124,7 @@ + (void)reset @synchronized(sentryDependencyContainerInstanceLock) { #if SENTRY_HAS_REACHABILITY [instance->_reachability removeAllObservers]; -#endif // !TARGET_OS_WATCH +#endif // SENTRY_HAS_REACHABILITY #if SENTRY_HAS_UIKIT [instance->_framesTracker stop]; @@ -197,7 +193,7 @@ - (instancetype)init #if SENTRY_HAS_REACHABILITY _reachability = [[SentryReachability alloc] init]; -#endif // !SENTRY_HAS_REACHABILITY +#endif // SENTRY_HAS_REACHABILITY isInitialializingDependencyContainer = NO; } diff --git a/Sources/Sentry/SentryHttpTransport.m b/Sources/Sentry/SentryHttpTransport.m index d861f116d05..d2907ae3c4e 100644 --- a/Sources/Sentry/SentryHttpTransport.m +++ b/Sources/Sentry/SentryHttpTransport.m @@ -20,14 +20,10 @@ #import "SentrySerialization.h" #import "SentrySwift.h" -#if !TARGET_OS_WATCH -# import "SentryReachability.h" -#endif // !TARGET_OS_WATCH - @interface SentryHttpTransport () #if SENTRY_HAS_REACHABILITY -#endif // !TARGET_OS_WATCH +#endif // SENTRY_HAS_REACHABILITY @property (nonatomic, readonly) NSTimeInterval cachedEnvelopeSendDelay; @property (nonatomic, strong) SentryFileManager *fileManager; @@ -102,7 +98,7 @@ - (id)initWithDsn:(SentryDsn *)dsn #if SENTRY_HAS_REACHABILITY [SentryDependencyContainer.sharedInstance.reachability addObserver:self]; -#endif // !TARGET_OS_WATCH +#endif // SENTRY_HAS_REACHABILITY } return self; } @@ -122,7 +118,7 @@ - (void)dealloc { [SentryDependencyContainer.sharedInstance.reachability removeObserver:self]; } -#endif // !TARGET_OS_WATCH +#endif // SENTRY_HAS_REACHABILITY - (void)sendEnvelope:(SentryEnvelope *)envelope { diff --git a/Sources/Sentry/SentryReachability.m b/Sources/Sentry/SentryReachability.m deleted file mode 100644 index 655cbd159be..00000000000 --- a/Sources/Sentry/SentryReachability.m +++ /dev/null @@ -1,264 +0,0 @@ -// Adapted from -// https://github.com/bugsnag/bugsnag-cocoa/blob/2f373f21b965f1b13d7070662e2d35f46c17d975/Bugsnag/Delivery/BSGConnectivity.m -// -// Created by Jamie Lynch on 2017-09-04. -// -// Copyright (c) 2017 Bugsnag, Inc. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall remain in place -// in this source code. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -#import "SentryReachability.h" -#import "SentryLogC.h" - -#if SENTRY_HAS_REACHABILITY -static const SCNetworkReachabilityFlags kSCNetworkReachabilityFlagsUninitialized = UINT32_MAX; - -static NSHashTable> *sentry_reachability_observers; -static SCNetworkReachabilityFlags sentry_current_reachability_state - = kSCNetworkReachabilityFlagsUninitialized; -static dispatch_queue_t sentry_reachability_queue; - -NSString *const SentryConnectivityCellular = @"cellular"; -NSString *const SentryConnectivityWiFi = @"wifi"; -NSString *const SentryConnectivityNone = @"none"; - -# if defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) -static BOOL sentry_reachability_ignore_actual_callback = NO; - -void -SentrySetReachabilityIgnoreActualCallback(BOOL value) -{ - SENTRY_LOG_DEBUG(@"Setting ignore actual callback to %@", value ? @"YES" : @"NO"); - sentry_reachability_ignore_actual_callback = value; -} -# endif // defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) - -/** - * Check whether the connectivity change should be noted or ignored. - * @return @c YES if the connectivity change should be reported - */ -BOOL -SentryConnectivityShouldReportChange(SCNetworkReachabilityFlags flags) -{ -# if SENTRY_HAS_UIKIT - // kSCNetworkReachabilityFlagsIsWWAN does not exist on macOS - const SCNetworkReachabilityFlags importantFlags - = kSCNetworkReachabilityFlagsIsWWAN | kSCNetworkReachabilityFlagsReachable; -# else // !SENTRY_HAS_UIKIT - const SCNetworkReachabilityFlags importantFlags = kSCNetworkReachabilityFlagsReachable; -# endif // SENTRY_HAS_UIKIT - - // Check if the reported state is different from the last known state (if any) - SCNetworkReachabilityFlags newFlags = flags & importantFlags; - if (newFlags == sentry_current_reachability_state) { - SENTRY_LOG_DEBUG(@"No change in reachability state. SentryConnectivityShouldReportChange " - @"will return NO for flags %u, sentry_current_reachability_state %u", - flags, sentry_current_reachability_state); - return NO; - } - - sentry_current_reachability_state = newFlags; - return YES; -} - -/** - * Textual representation of a connection type - */ -NSString * -SentryConnectivityFlagRepresentation(SCNetworkReachabilityFlags flags) -{ - BOOL connected = (flags & kSCNetworkReachabilityFlagsReachable) != 0; -# if SENTRY_HAS_UIKIT - return connected ? ((flags & kSCNetworkReachabilityFlagsIsWWAN) ? SentryConnectivityCellular - : SentryConnectivityWiFi) - : SentryConnectivityNone; -# else // !SENTRY_HAS_UIKIT - return connected ? SentryConnectivityWiFi : SentryConnectivityNone; -# endif // SENTRY_HAS_UIKIT -} - -void -SentryConnectivityCallback(SCNetworkReachabilityFlags flags) -{ - @synchronized(sentry_reachability_observers) { - SENTRY_LOG_DEBUG( - @"Entered synchronized region of SentryConnectivityCallback with flags: %u", flags); - - if (sentry_reachability_observers.count == 0) { - SENTRY_LOG_DEBUG(@"No reachability observers registered. Nothing to do."); - return; - } - - if (!SentryConnectivityShouldReportChange(flags)) { - SENTRY_LOG_DEBUG(@"SentryConnectivityShouldReportChange returned NO for flags %u, will " - @"not report change to observers.", - flags); - return; - } - - BOOL connected = (flags & kSCNetworkReachabilityFlagsReachable) != 0; - - SENTRY_LOG_DEBUG(@"Notifying observers..."); - for (id observer in sentry_reachability_observers) { - SENTRY_LOG_DEBUG(@"Notifying %@", observer); - [observer connectivityChanged:connected - typeDescription:SentryConnectivityFlagRepresentation(flags)]; - } - SENTRY_LOG_DEBUG(@"Finished notifying observers."); - } -} - -/** - * Callback invoked by @c SCNetworkReachability, which calls an Objective-C block - * that handles the connection change. - */ -void -SentryConnectivityActualCallback( - __unused SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, __unused void *info) -{ - SENTRY_LOG_DEBUG( - @"SentryConnectivityCallback called with target: %@; flags: %u", target, flags); -# if defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) - if (sentry_reachability_ignore_actual_callback) { - SENTRY_LOG_DEBUG(@"Ignoring actual callback."); - return; - } -# endif // defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) - - SentryConnectivityCallback(flags); -} - -@interface SentryReachability () - -@property SCNetworkReachabilityRef sentry_reachability_ref; - -@end - -@implementation SentryReachability - -+ (void)initialize -{ - if (self == [SentryReachability class]) { - sentry_reachability_observers = [NSHashTable weakObjectsHashTable]; - } -} - -# if defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) - -- (instancetype)init -{ - if (self = [super init]) { - self.skipRegisteringActualCallbacks = NO; - } - - return self; -} - -# endif // defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) - -- (void)addObserver:(id)observer; -{ - SENTRY_LOG_DEBUG(@"Adding observer: %@", observer); - @synchronized(sentry_reachability_observers) { - SENTRY_LOG_DEBUG(@"Synchronized to add observer: %@", observer); - if ([sentry_reachability_observers containsObject:observer]) { - SENTRY_LOG_DEBUG(@"Observer already added. Doing nothing."); - return; - } - - [sentry_reachability_observers addObject:observer]; - - if (sentry_reachability_observers.count > 1) { - return; - } - -# if defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) - if (self.skipRegisteringActualCallbacks) { - SENTRY_LOG_DEBUG(@"Skip registering actual callbacks"); - return; - } -# endif // defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) - - sentry_reachability_queue - = dispatch_queue_create("io.sentry.cocoa.connectivity", DISPATCH_QUEUE_SERIAL); - // Ensure to call CFRelease for the return value of SCNetworkReachabilityCreateWithName, see - // https://developer.apple.com/documentation/systemconfiguration/1514904-scnetworkreachabilitycreatewithn?language=objc - // and - // https://developer.apple.com/documentation/systemconfiguration/scnetworkreachability?language=objc - _sentry_reachability_ref = SCNetworkReachabilityCreateWithName(NULL, "sentry.io"); - if (!_sentry_reachability_ref) { // Can be null if a bad hostname was specified - return; - } - - SENTRY_LOG_DEBUG(@"registering callback for reachability ref %@", _sentry_reachability_ref); - SCNetworkReachabilitySetCallback( - _sentry_reachability_ref, SentryConnectivityActualCallback, NULL); - SCNetworkReachabilitySetDispatchQueue(_sentry_reachability_ref, sentry_reachability_queue); - } -} - -- (void)removeObserver:(id)observer -{ - SENTRY_LOG_DEBUG(@"Removing observer: %@", observer); - @synchronized(sentry_reachability_observers) { - SENTRY_LOG_DEBUG(@"Synchronized to remove observer: %@", observer); - [sentry_reachability_observers removeObject:observer]; - - if (sentry_reachability_observers.count == 0) { - [self unsetReachabilityCallback]; - } - } -} - -- (void)removeAllObservers -{ - SENTRY_LOG_DEBUG(@"Removing all observers."); - @synchronized(sentry_reachability_observers) { - SENTRY_LOG_DEBUG(@"Synchronized to remove all observers."); - [sentry_reachability_observers removeAllObjects]; - [self unsetReachabilityCallback]; - } -} - -- (void)unsetReachabilityCallback -{ -# if defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) - if (self.skipRegisteringActualCallbacks) { - SENTRY_LOG_DEBUG(@"Skip unsetting actual callbacks"); - } -# endif // defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) - - sentry_current_reachability_state = kSCNetworkReachabilityFlagsUninitialized; - - if (_sentry_reachability_ref != nil) { - SENTRY_LOG_DEBUG(@"removing callback for reachability ref %@", _sentry_reachability_ref); - SCNetworkReachabilitySetCallback(_sentry_reachability_ref, NULL, NULL); - SCNetworkReachabilitySetDispatchQueue(_sentry_reachability_ref, NULL); - CFRelease(_sentry_reachability_ref); - _sentry_reachability_ref = nil; - } - - SENTRY_LOG_DEBUG(@"Cleaning up reachability queue."); - sentry_reachability_queue = nil; -} - -@end - -#endif // !TARGET_OS_WATCH diff --git a/Sources/Sentry/SentrySessionReplayIntegration.m b/Sources/Sentry/SentrySessionReplayIntegration.m index 3982a6edc53..7c2a196a7fb 100644 --- a/Sources/Sentry/SentrySessionReplayIntegration.m +++ b/Sources/Sentry/SentrySessionReplayIntegration.m @@ -16,7 +16,6 @@ # import "SentryOptions.h" # import "SentryRandom.h" # import "SentryRateLimits.h" -# import "SentryReachability.h" # import "SentrySDK+Private.h" # import "SentryScope+Private.h" # import "SentrySerialization.h" diff --git a/Sources/Sentry/include/SentryReachability.h b/Sources/Sentry/include/SentryReachability.h deleted file mode 100644 index d80b84c6a8b..00000000000 --- a/Sources/Sentry/include/SentryReachability.h +++ /dev/null @@ -1,96 +0,0 @@ -// Adapted from -// https://github.com/bugsnag/bugsnag-cocoa/blob/2f373f21b965f1b13d7070662e2d35f46c17d975/Bugsnag/Delivery/BSGConnectivity.h -// -// Created by Jamie Lynch on 2017-09-04. -// -// Copyright (c) 2017 Bugsnag, Inc. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall remain in place -// in this source code. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -#import "SentryDefines.h" - -#if SENTRY_HAS_REACHABILITY -# import - -NS_ASSUME_NONNULL_BEGIN - -void SentryConnectivityCallback(SCNetworkReachabilityFlags flags); - -# if defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) -/** - * Needed for testing. - */ -void SentrySetReachabilityIgnoreActualCallback(BOOL value); - -# endif // defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) - -NSString *SentryConnectivityFlagRepresentation(SCNetworkReachabilityFlags flags); - -BOOL SentryConnectivityShouldReportChange(SCNetworkReachabilityFlags flags); - -SENTRY_EXTERN NSString *const SentryConnectivityCellular; -SENTRY_EXTERN NSString *const SentryConnectivityWiFi; -SENTRY_EXTERN NSString *const SentryConnectivityNone; - -@protocol SentryReachabilityObserver - -/** - * Called when network connectivity changes. - * - * @param connected @c YES if the monitored URL is reachable - * @param typeDescription a textual representation of the connection type - */ -- (void)connectivityChanged:(BOOL)connected typeDescription:(NSString *)typeDescription; - -@end - -/** - * Monitors network connectivity using @c SCNetworkReachability callbacks, - * providing a customizable callback block invoked when connectivity changes. - */ -@interface SentryReachability : NSObject - -# if defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) - -/** - * Only needed for testing. Use this flag to skip registering and unregistering the actual callbacks - * to SCNetworkReachability to minimize side effects. - */ -@property (nonatomic, assign) BOOL skipRegisteringActualCallbacks; - -# endif // defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) - -/** - * Add an observer which is called each time network connectivity changes. - */ -- (void)addObserver:(id)observer; - -/** - * Stop monitoring the URL previously configured with @c monitorURL:usingCallback: - */ -- (void)removeObserver:(id)observer; - -- (void)removeAllObservers; - -@end - -NS_ASSUME_NONNULL_END - -#endif // !TARGET_OS_WATCH diff --git a/Sources/Sentry/include/SentrySwift.h b/Sources/Sentry/include/SentrySwift.h index 4c60786b3ab..612ace2c2da 100644 --- a/Sources/Sentry/include/SentrySwift.h +++ b/Sources/Sentry/include/SentrySwift.h @@ -7,6 +7,13 @@ # endif #endif +// Needed or we can't expose reachability functions from Swift +#ifdef __cplusplus +# if __has_include() +# import +# endif +#endif + #if __has_include() # if __has_include("SentryWithoutUIKit-Swift.h") # import "SentryWithoutUIKit-Swift.h" diff --git a/Sources/Swift/Networking/SentryReachability.swift b/Sources/Swift/Networking/SentryReachability.swift new file mode 100644 index 00000000000..afc250b9139 --- /dev/null +++ b/Sources/Swift/Networking/SentryReachability.swift @@ -0,0 +1,263 @@ +// Adapted from +// https://github.com/bugsnag/bugsnag-cocoa/blob/2f373f21b965f1b13d7070662e2d35f46c17d975/Bugsnag/Delivery/BSGConnectivity.m +// +// Created by Jamie Lynch on 2017-09-04. +// +// Copyright (c) 2017 Bugsnag, Inc. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall remain in place +// in this source code. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Foundation + +#if !os(watchOS) && !(os(visionOS) && !canImport(UIKit)) +import SystemConfiguration + +@objc +public enum SentryConnectivity: Int { + case cellular + case wiFi + case none + + func toString() -> String { + switch self { + case .cellular: + return "cellular" + case .wiFi: + return "wifi" + case .none: + return "none" + } + } +} + +private let kSCNetworkReachabilityFlagsUninitialized: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: UInt32.max) + +private var sentryReachabilityObservers = NSHashTable.weakObjects() +private var sentryCurrentReachabilityState: SCNetworkReachabilityFlags = kSCNetworkReachabilityFlagsUninitialized +private var sentryReachabilityQueue: DispatchQueue? + +#if DEBUG || SENTRY_TEST || SENTRY_TEST_CI +private var sentryReachabilityIgnoreActualCallback = false + +@objc public class SentryReachabilityTestHelper: NSObject { + @objc static public func setReachabilityIgnoreActualCallback(_ value: Bool) { + SentrySDKLog.debug("Setting ignore actual callback to \(value)") + sentryReachabilityIgnoreActualCallback = value + } + + @objc static public func connectivityCallback(_ flags: SCNetworkReachabilityFlags) { + sentryConnectivityCallback(flags) + } + + @objc static public func connectivityFlagRepresentation(_ flags: SCNetworkReachabilityFlags) -> String { + sentryConnectivityFlagRepresentation(flags) + } + + @objc static public func stringForSentryConnectivity(_ type: SentryConnectivity) -> String { + type.toString() + } +} +#endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI + +public func sentryConnectivityCallback(_ flags: SCNetworkReachabilityFlags) { + objc_sync_enter(sentryReachabilityObservers) + defer { objc_sync_exit(sentryReachabilityObservers) } + + SentrySDKLog.debug("Entered synchronized region of SentryConnectivityCallback with flags: \(flags.rawValue)") + + guard sentryReachabilityObservers.count > 0 else { + SentrySDKLog.debug("No reachability observers registered. Nothing to do.") + return + } + + guard sentryConnectivityShouldReportChange(flags) else { + SentrySDKLog.debug("SentryConnectivityShouldReportChange returned false for flags \(flags.rawValue), will not report change to observers.") + return + } + + let connected = flags.contains(.reachable) + + SentrySDKLog.debug("Notifying observers...") + for observer in sentryReachabilityObservers.allObjects { + SentrySDKLog.debug("Notifying \(observer)") + observer.connectivityChanged(connected, typeDescription: sentryConnectivityFlagRepresentation(flags)) + } + SentrySDKLog.debug("Finished notifying observers.") +} + +public func sentryConnectivityShouldReportChange(_ flags: SCNetworkReachabilityFlags) -> Bool { +#if canImport(UIKit) + let importantFlags: SCNetworkReachabilityFlags = [.isWWAN, .reachable] +#else + let importantFlags: SCNetworkReachabilityFlags = .reachable +#endif // canImport(UIKit) + + let newFlags = SCNetworkReachabilityFlags(rawValue: flags.rawValue & importantFlags.rawValue) + if newFlags == sentryCurrentReachabilityState { + SentrySDKLog.debug("No change in reachability state. SentryConnectivityShouldReportChange will return false for flags \(flags.rawValue), sentryCurrentReachabilityState \(sentryCurrentReachabilityState.rawValue)") + return false + } + + sentryCurrentReachabilityState = newFlags + return true +} + +public func sentryConnectivityFlagRepresentation(_ flags: SCNetworkReachabilityFlags) -> String { + let connected = flags.contains(.reachable) +#if canImport(UIKit) + if connected { + return flags.contains(.isWWAN) ? SentryConnectivity.cellular.toString() : SentryConnectivity.wiFi.toString() + } else { + return SentryConnectivity.none.toString() + } +#else + return connected ? SentryConnectivity.wiFi.toString() : SentryConnectivity.none.toString() +#endif // canImport(UIKit) +} + +private func sentryConnectivityActualCallback( + _ target: SCNetworkReachability, + _ flags: SCNetworkReachabilityFlags, + _ info: UnsafeMutableRawPointer? +) { + SentrySDKLog.debug("SentryConnectivityCallback called with target: \(target); flags: \(flags.rawValue)") + +#if DEBUG || SENTRY_TEST || SENTRY_TEST_CI + if sentryReachabilityIgnoreActualCallback { + SentrySDKLog.debug("Ignoring actual callback.") + return + } +#endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI + + sentryConnectivityCallback(flags) +} + +@_spi(Private) @objc public protocol SentryReachabilityObserver: NSObjectProtocol { + @objc func connectivityChanged(_ connected: Bool, typeDescription: String) +} + +@_spi(Private) @objc public class SentryReachability: NSObject { + private var sentryReachabilityRef: SCNetworkReachability? + +#if DEBUG || SENTRY_TEST || SENTRY_TEST_CI + @objc public var skipRegisteringActualCallbacks = false +#endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI + + @objc(addObserver:) + public func add(_ observer: SentryReachabilityObserver) { + SentrySDKLog.debug("Adding observer: \(observer)") + + objc_sync_enter(sentryReachabilityObservers) + defer { objc_sync_exit(sentryReachabilityObservers) } + + SentrySDKLog.debug("Synchronized to add observer: \(observer)") + + if sentryReachabilityObservers.contains(observer) { + SentrySDKLog.debug("Observer already added. Doing nothing.") + return + } + + sentryReachabilityObservers.add(observer) + + if sentryReachabilityObservers.count > 1 { + return + } + +#if DEBUG || SENTRY_TEST || SENTRY_TEST_CI + if skipRegisteringActualCallbacks { + SentrySDKLog.debug("Skip registering actual callbacks") + return + } +#endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI + + sentryReachabilityQueue = DispatchQueue(label: "io.sentry.cocoa.connectivity") + + guard let reachabilityRef = SCNetworkReachabilityCreateWithName(nil, "sentry.io") else { + return + } + + sentryReachabilityRef = reachabilityRef + + SentrySDKLog.debug("registering callback for reachability ref \(reachabilityRef)") + + var context = SCNetworkReachabilityContext( + version: 0, + info: nil, + retain: nil, + release: nil, + copyDescription: nil + ) + + SCNetworkReachabilitySetCallback(reachabilityRef, sentryConnectivityActualCallback, &context) + SCNetworkReachabilitySetDispatchQueue(reachabilityRef, sentryReachabilityQueue) + } + + @objc(removeObserver:) + public func remove(_ observer: SentryReachabilityObserver) { + SentrySDKLog.debug("Removing observer: \(observer)") + + objc_sync_enter(sentryReachabilityObservers) + defer { objc_sync_exit(sentryReachabilityObservers) } + + SentrySDKLog.debug("Synchronized to remove observer: \(observer)") + sentryReachabilityObservers.remove(observer) + + if sentryReachabilityObservers.count == 0 { + unsetReachabilityCallback() + } + } + + @objc public func removeAllObservers() { + SentrySDKLog.debug("Removing all observers.") + + objc_sync_enter(sentryReachabilityObservers) + defer { objc_sync_exit(sentryReachabilityObservers) } + + SentrySDKLog.debug("Synchronized to remove all observers.") + sentryReachabilityObservers.removeAllObjects() + unsetReachabilityCallback() + } + + private func unsetReachabilityCallback() { +#if DEBUG || SENTRY_TEST || SENTRY_TEST_CI + if skipRegisteringActualCallbacks { + SentrySDKLog.debug("Skip unsetting actual callbacks") + } +#endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI + + sentryCurrentReachabilityState = kSCNetworkReachabilityFlagsUninitialized + + if let reachabilityRef = sentryReachabilityRef { + SentrySDKLog.debug("removing callback for reachability ref \(reachabilityRef)") + SCNetworkReachabilitySetCallback(reachabilityRef, nil, nil) + SCNetworkReachabilitySetDispatchQueue(reachabilityRef, nil) + sentryReachabilityRef = nil + } + + SentrySDKLog.debug("Cleaning up reachability queue.") + sentryReachabilityQueue = nil + } + + deinit { + removeAllObservers() + } +} + +#endif // !os(watchOS) && !(os(visionOS) && !canImport(UIKit)) diff --git a/Tests/SentryTests/Integrations/Breadcrumbs/SentryBreadcrumbTrackerTests.swift b/Tests/SentryTests/Integrations/Breadcrumbs/SentryBreadcrumbTrackerTests.swift index a1f6285b654..8ced22c92d8 100644 --- a/Tests/SentryTests/Integrations/Breadcrumbs/SentryBreadcrumbTrackerTests.swift +++ b/Tests/SentryTests/Integrations/Breadcrumbs/SentryBreadcrumbTrackerTests.swift @@ -43,12 +43,12 @@ class SentryBreadcrumbTrackerTests: XCTestCase { let sut = SentryBreadcrumbTracker() sut.start(with: delegate) - let states = [SentryConnectivityCellular, - SentryConnectivityWiFi, - SentryConnectivityNone, - SentryConnectivityWiFi, - SentryConnectivityCellular, - SentryConnectivityWiFi + let states: [SentryConnectivity] = [.cellular, + .wiFi, + .none, + .wiFi, + .cellular, + .wiFi ] states.forEach { testReachability.setReachabilityState(state: $0) @@ -59,7 +59,7 @@ class SentryBreadcrumbTrackerTests: XCTestCase { let crumb = delegate.addCrumbInvocations.invocations[$0.offset + 1] XCTAssertEqual(crumb.type, "connectivity") XCTAssertEqual(crumb.category, "device.connectivity") - XCTAssertEqual(try XCTUnwrap(crumb.data?["connectivity"] as? String), $0.element) + XCTAssertEqual(try XCTUnwrap(crumb.data?["connectivity"] as? String), $0.element.toString()) } } @@ -68,7 +68,7 @@ class SentryBreadcrumbTrackerTests: XCTestCase { SentryDependencyContainer.sharedInstance().reachability = testReachability let sut = SentryBreadcrumbTracker() sut.start(with: delegate) - testReachability.setReachabilityState(state: SentryConnectivityCellular) + testReachability.setReachabilityState(state: .cellular) sut.stop() guard let breadcrumb = delegate.addCrumbInvocations.invocations.dropFirst().first else { diff --git a/Tests/SentryTests/Networking/SentryReachabilitySwiftTests.swift b/Tests/SentryTests/Networking/SentryReachabilitySwiftTests.swift index 1c7cc776658..7d1f06cedf2 100644 --- a/Tests/SentryTests/Networking/SentryReachabilitySwiftTests.swift +++ b/Tests/SentryTests/Networking/SentryReachabilitySwiftTests.swift @@ -1,3 +1,4 @@ +@_spi(Private) @testable import Sentry import XCTest final class SentryReachabilitySwiftTests: XCTestCase { diff --git a/Tests/SentryTests/Networking/SentryReachabilityTests.m b/Tests/SentryTests/Networking/SentryReachabilityTests.m index 6fbff7f36c9..e800fe8a1ab 100644 --- a/Tests/SentryTests/Networking/SentryReachabilityTests.m +++ b/Tests/SentryTests/Networking/SentryReachabilityTests.m @@ -1,6 +1,7 @@ #import "SentryLogC.h" -#import "SentryReachability.h" +#import "SentrySwift.h" #import +@import SystemConfiguration; @interface TestSentryReachabilityObserver : NSObject @@ -38,7 +39,7 @@ - (void)setUp // Ignore the actual reachability callbacks, cause we call the callbacks manually. // Otherwise, the actual reachability callbacks are called during later unrelated tests causing // flakes. - SentrySetReachabilityIgnoreActualCallback(YES); + [SentryReachabilityTestHelper setReachabilityIgnoreActualCallback:YES]; self.reachability = [[SentryReachability alloc] init]; self.reachability.skipRegisteringActualCallbacks = YES; @@ -48,27 +49,39 @@ - (void)tearDown { [self.reachability removeAllObservers]; self.reachability = nil; - SentrySetReachabilityIgnoreActualCallback(NO); + [SentryReachabilityTestHelper setReachabilityIgnoreActualCallback:NO]; } - (void)testConnectivityRepresentations { - XCTAssertEqualObjects(SentryConnectivityNone, SentryConnectivityFlagRepresentation(0)); - XCTAssertEqualObjects(SentryConnectivityNone, - SentryConnectivityFlagRepresentation(kSCNetworkReachabilityFlagsIsDirect)); + XCTAssertEqualObjects( + [SentryReachabilityTestHelper stringForSentryConnectivity:SentryConnectivityNone], + [SentryReachabilityTestHelper connectivityFlagRepresentation:0]); + XCTAssertEqualObjects( + [SentryReachabilityTestHelper stringForSentryConnectivity:SentryConnectivityNone], + [SentryReachabilityTestHelper + connectivityFlagRepresentation:kSCNetworkReachabilityFlagsIsDirect]); # if SENTRY_HAS_UIKIT // kSCNetworkReachabilityFlagsIsWWAN does not exist on macOS - XCTAssertEqualObjects(SentryConnectivityNone, - SentryConnectivityFlagRepresentation(kSCNetworkReachabilityFlagsIsWWAN)); - XCTAssertEqualObjects(SentryConnectivityCellular, - SentryConnectivityFlagRepresentation( - kSCNetworkReachabilityFlagsIsWWAN | kSCNetworkReachabilityFlagsReachable)); + XCTAssertEqualObjects( + [SentryReachabilityTestHelper stringForSentryConnectivity:SentryConnectivityNone], + [SentryReachabilityTestHelper + connectivityFlagRepresentation:kSCNetworkReachabilityFlagsIsWWAN]); + XCTAssertEqualObjects( + [SentryReachabilityTestHelper stringForSentryConnectivity:SentryConnectivityCellular], + [SentryReachabilityTestHelper + connectivityFlagRepresentation:kSCNetworkReachabilityFlagsIsWWAN | + kSCNetworkReachabilityFlagsReachable]); # endif // SENTRY_HAS_UIKIT - XCTAssertEqualObjects(SentryConnectivityWiFi, - SentryConnectivityFlagRepresentation(kSCNetworkReachabilityFlagsReachable)); - XCTAssertEqualObjects(SentryConnectivityWiFi, - SentryConnectivityFlagRepresentation( - kSCNetworkReachabilityFlagsReachable | kSCNetworkReachabilityFlagsIsDirect)); + XCTAssertEqualObjects( + [SentryReachabilityTestHelper stringForSentryConnectivity:SentryConnectivityWiFi], + [SentryReachabilityTestHelper + connectivityFlagRepresentation:kSCNetworkReachabilityFlagsReachable]); + XCTAssertEqualObjects( + [SentryReachabilityTestHelper stringForSentryConnectivity:SentryConnectivityWiFi], + [SentryReachabilityTestHelper + connectivityFlagRepresentation:kSCNetworkReachabilityFlagsReachable | + kSCNetworkReachabilityFlagsIsDirect]); } - (void)testMultipleReachabilityObservers @@ -79,10 +92,11 @@ - (void)testMultipleReachabilityObservers [self.reachability addObserver:observerA]; NSLog(@"[Sentry] [TEST] throwaway reachability callback, setting to reachable"); - SentryConnectivityCallback( - kSCNetworkReachabilityFlagsReachable); // ignored, as it's the first callback + [SentryReachabilityTestHelper + connectivityCallback:kSCNetworkReachabilityFlagsReachable]; // ignored, as it's the + // first callback NSLog(@"[Sentry] [TEST] reachability callback set to unreachable"); - SentryConnectivityCallback(0); + [SentryReachabilityTestHelper connectivityCallback:0]; NSLog(@"[Sentry] [TEST] creating observer B"); TestSentryReachabilityObserver *observerB = [[TestSentryReachabilityObserver alloc] init]; @@ -90,15 +104,15 @@ - (void)testMultipleReachabilityObservers [self.reachability addObserver:observerB]; NSLog(@"[Sentry] [TEST] reachability callback set back to reachable"); - SentryConnectivityCallback(kSCNetworkReachabilityFlagsReachable); + [SentryReachabilityTestHelper connectivityCallback:kSCNetworkReachabilityFlagsReachable]; NSLog(@"[Sentry] [TEST] reachability callback set back to unreachable"); - SentryConnectivityCallback(0); + [SentryReachabilityTestHelper connectivityCallback:0]; NSLog(@"[Sentry] [TEST] removing observer B as reachability observer"); [self.reachability removeObserver:observerB]; NSLog(@"[Sentry] [TEST] reachability callback set back to reachable"); - SentryConnectivityCallback(kSCNetworkReachabilityFlagsReachable); + [SentryReachabilityTestHelper connectivityCallback:kSCNetworkReachabilityFlagsReachable]; XCTAssertEqual(5, observerA.connectivityChangedInvocations); XCTAssertEqual(2, observerB.connectivityChangedInvocations); @@ -113,7 +127,7 @@ - (void)testNoObservers [self.reachability addObserver:observer]; [self.reachability removeObserver:observer]; - SentryConnectivityCallback(kSCNetworkReachabilityFlagsReachable); + [SentryReachabilityTestHelper connectivityCallback:kSCNetworkReachabilityFlagsReachable]; XCTAssertEqual(0, observer.connectivityChangedInvocations); @@ -126,7 +140,7 @@ - (void)testReportSameObserver_OnlyCalledOnce [self.reachability addObserver:observer]; [self.reachability addObserver:observer]; - SentryConnectivityCallback(kSCNetworkReachabilityFlagsReachable); + [SentryReachabilityTestHelper connectivityCallback:kSCNetworkReachabilityFlagsReachable]; XCTAssertEqual(1, observer.connectivityChangedInvocations); @@ -138,9 +152,9 @@ - (void)testReportSameReachabilityState_OnlyCalledOnce TestSentryReachabilityObserver *observer = [[TestSentryReachabilityObserver alloc] init]; [self.reachability addObserver:observer]; - SentryConnectivityCallback(kSCNetworkReachabilityFlagsReachable); - SentryConnectivityCallback(kSCNetworkReachabilityFlagsReachable); - SentryConnectivityCallback(kSCNetworkReachabilityFlagsReachable); + [SentryReachabilityTestHelper connectivityCallback:kSCNetworkReachabilityFlagsReachable]; + [SentryReachabilityTestHelper connectivityCallback:kSCNetworkReachabilityFlagsReachable]; + [SentryReachabilityTestHelper connectivityCallback:kSCNetworkReachabilityFlagsReachable]; XCTAssertEqual(1, observer.connectivityChangedInvocations); diff --git a/Tests/SentryTests/Networking/TestSentryReachability.swift b/Tests/SentryTests/Networking/TestSentryReachability.swift index 3e1084863f6..1398ce50514 100644 --- a/Tests/SentryTests/Networking/TestSentryReachability.swift +++ b/Tests/SentryTests/Networking/TestSentryReachability.swift @@ -1,32 +1,33 @@ -#if !os(watchOS) +#if !os(watchOS) && !(os(visionOS) && !canImport(UIKit)) +@_spi(Private) @testable import Sentry import SentryTestUtils -class TestSentryReachability: SentryReachability { +@_spi(Private) public class TestSentryReachability: SentryReachability { private var observers: NSHashTable = NSHashTable.weakObjects() - override func add(_ observer: SentryReachabilityObserver) { + public override func add(_ observer: SentryReachabilityObserver) { observers.add(observer) } - func setReachabilityState(state: String) { + func setReachabilityState(state: SentryConnectivity) { for observer in observers.allObjects { - observer.connectivityChanged(state != SentryConnectivityNone, typeDescription: state) + observer.connectivityChanged(state != .none, typeDescription: state.toString()) } } func triggerNetworkReachable() { for observer in observers.allObjects { - observer.connectivityChanged(true, typeDescription: SentryConnectivityWiFi) + observer.connectivityChanged(true, typeDescription: SentryConnectivity.wiFi.toString()) } } var stopMonitoringInvocations = Invocations() - override func remove(_ observer: SentryReachabilityObserver) { + public override func remove(_ observer: SentryReachabilityObserver) { stopMonitoringInvocations.record(Void()) } } -#endif // !os(watchOS) +#endif // !os(watchOS) && !(os(visionOS) && !canImport(UIKit)) diff --git a/Tests/SentryTests/SentryTests-Bridging-Header.h b/Tests/SentryTests/SentryTests-Bridging-Header.h index 82fa8c6b14b..447c8a2e864 100644 --- a/Tests/SentryTests/SentryTests-Bridging-Header.h +++ b/Tests/SentryTests/SentryTests-Bridging-Header.h @@ -1,6 +1,3 @@ -#if !TARGET_OS_WATCH -# import "SentryReachability.h" -#endif // !TARGET_OS_WATCH #import "SentryDefines.h" #import "SentryProfilingConditionals.h" @@ -168,7 +165,6 @@ #import "SentryQueueableRequestManager.h" #import "SentryRateLimitParser.h" #import "SentryRateLimits.h" -#import "SentryReachability.h" #import "SentryRetryAfterHeaderParser.h" #import "SentrySDK+Private.h" #import "SentrySDKInternal+Tests.h" From d0fdbf6af2667bedc17032da28427f1f9e98ef1a Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Fri, 29 Aug 2025 12:35:43 -0300 Subject: [PATCH 02/22] Update SDK API --- sdk_api.json | 287 ++++++++++++++++++++++++++++++++++++++++++++++++ sdk_api_V9.json | 287 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 574 insertions(+) diff --git a/sdk_api.json b/sdk_api.json index 31d6948f49b..cf81dca7210 100644 --- a/sdk_api.json +++ b/sdk_api.json @@ -42880,6 +42880,13 @@ "Exported" ] }, + { + "kind": "Import", + "name": "SystemConfiguration", + "printedName": "SystemConfiguration", + "declKind": "Import", + "moduleName": "Sentry" + }, { "kind": "Import", "name": "UIKit", @@ -42915,6 +42922,286 @@ "declKind": "Import", "moduleName": "Sentry" }, + { + "kind": "TypeDecl", + "name": "SentryConnectivity", + "printedName": "SentryConnectivity", + "children": [ + { + "kind": "Var", + "name": "cellular", + "printedName": "cellular", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryConnectivity.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityCellular", + "mangledName": "$s6Sentry0A12ConnectivityO8cellularyA2CmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "wiFi", + "printedName": "wiFi", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryConnectivity.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityWiFi", + "mangledName": "$s6Sentry0A12ConnectivityO4wiFiyA2CmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "none", + "printedName": "none", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryConnectivity.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityNone", + "mangledName": "$s6Sentry0A12ConnectivityO4noneyA2CmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryConnectivity?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A12ConnectivityO8rawValueACSgSi_tcfc", + "mangledName": "$s6Sentry0A12ConnectivityO8rawValueACSgSi_tcfc", + "moduleName": "Sentry", + "init_kind": "Designated" + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A12ConnectivityO8RawValuea", + "mangledName": "$s6Sentry0A12ConnectivityO8RawValuea", + "moduleName": "Sentry" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A12ConnectivityO8rawValueSivp", + "mangledName": "$s6Sentry0A12ConnectivityO8rawValueSivp", + "moduleName": "Sentry", + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A12ConnectivityO8rawValueSivg", + "mangledName": "$s6Sentry0A12ConnectivityO8rawValueSivg", + "moduleName": "Sentry", + "accessorKind": "get" + } + ] + } + ], + "declKind": "Enum", + "usr": "c:@M@Sentry@E@SentryConnectivity", + "mangledName": "$s6Sentry0A12ConnectivityO", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryConnectivity.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + } + ] + }, { "kind": "TypeDecl", "name": "SentryFeedback", diff --git a/sdk_api_V9.json b/sdk_api_V9.json index c298cafa12c..b738c42d866 100644 --- a/sdk_api_V9.json +++ b/sdk_api_V9.json @@ -40049,6 +40049,13 @@ "Exported" ] }, + { + "kind": "Import", + "name": "SystemConfiguration", + "printedName": "SystemConfiguration", + "declKind": "Import", + "moduleName": "Sentry" + }, { "kind": "Import", "name": "UIKit", @@ -40084,6 +40091,286 @@ "declKind": "Import", "moduleName": "Sentry" }, + { + "kind": "TypeDecl", + "name": "SentryConnectivity", + "printedName": "SentryConnectivity", + "children": [ + { + "kind": "Var", + "name": "cellular", + "printedName": "cellular", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryConnectivity.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityCellular", + "mangledName": "$s6Sentry0A12ConnectivityO8cellularyA2CmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "wiFi", + "printedName": "wiFi", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryConnectivity.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityWiFi", + "mangledName": "$s6Sentry0A12ConnectivityO4wiFiyA2CmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "none", + "printedName": "none", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryConnectivity.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityNone", + "mangledName": "$s6Sentry0A12ConnectivityO4noneyA2CmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryConnectivity?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A12ConnectivityO8rawValueACSgSi_tcfc", + "mangledName": "$s6Sentry0A12ConnectivityO8rawValueACSgSi_tcfc", + "moduleName": "Sentry", + "init_kind": "Designated" + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A12ConnectivityO8RawValuea", + "mangledName": "$s6Sentry0A12ConnectivityO8RawValuea", + "moduleName": "Sentry" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A12ConnectivityO8rawValueSivp", + "mangledName": "$s6Sentry0A12ConnectivityO8rawValueSivp", + "moduleName": "Sentry", + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A12ConnectivityO8rawValueSivg", + "mangledName": "$s6Sentry0A12ConnectivityO8rawValueSivg", + "moduleName": "Sentry", + "accessorKind": "get" + } + ] + } + ], + "declKind": "Enum", + "usr": "c:@M@Sentry@E@SentryConnectivity", + "mangledName": "$s6Sentry0A12ConnectivityO", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryConnectivity.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + } + ] + }, { "kind": "TypeDecl", "name": "SentryFeedback", From 0ddbca02555912767f40cdc9cde12f3a90204eff Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Fri, 29 Aug 2025 12:37:08 -0300 Subject: [PATCH 03/22] Update SentrySwift.h --- Sources/Sentry/include/SentrySwift.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Sources/Sentry/include/SentrySwift.h b/Sources/Sentry/include/SentrySwift.h index 612ace2c2da..34b8bd5c1de 100644 --- a/Sources/Sentry/include/SentrySwift.h +++ b/Sources/Sentry/include/SentrySwift.h @@ -7,13 +7,6 @@ # endif #endif -// Needed or we can't expose reachability functions from Swift -#ifdef __cplusplus -# if __has_include() -# import -# endif -#endif - #if __has_include() # if __has_include("SentryWithoutUIKit-Swift.h") # import "SentryWithoutUIKit-Swift.h" @@ -29,6 +22,13 @@ # import "SentryDefines.h" # endif // __has_include() +// Needed or we can't expose reachability functions from Swift +# ifdef __cplusplus +# if SENTRY_HAS_REACHABILITY && __has_include() +# import +# endif +# endif + # if SENTRY_HAS_UIKIT // this is needed to fix a build issue when building iOS-ObjectiveC where the definitions of some // UIKIt enums used from SentryUserFeedbackWidgetConfiguration.swift aren't visible from the From 7c9cc57856bf796ca8d391f6dc33aeb2bd3089f6 Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Fri, 29 Aug 2025 12:37:40 -0300 Subject: [PATCH 04/22] Update SentryReachability --- .../Swift/Networking/SentryReachability.swift | 47 ++++++++++++++++--- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/Sources/Swift/Networking/SentryReachability.swift b/Sources/Swift/Networking/SentryReachability.swift index afc250b9139..b56051816c2 100644 --- a/Sources/Swift/Networking/SentryReachability.swift +++ b/Sources/Swift/Networking/SentryReachability.swift @@ -26,7 +26,7 @@ import Foundation -#if !os(watchOS) && !(os(visionOS) && !canImport(UIKit)) +#if !os(watchOS) && !(os(visionOS) && SENTRY_NO_UIKIT) import SystemConfiguration @objc @@ -49,6 +49,7 @@ public enum SentryConnectivity: Int { private let kSCNetworkReachabilityFlagsUninitialized: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: UInt32.max) +// Global variables are lazy by default private var sentryReachabilityObservers = NSHashTable.weakObjects() private var sentryCurrentReachabilityState: SCNetworkReachabilityFlags = kSCNetworkReachabilityFlagsUninitialized private var sentryReachabilityQueue: DispatchQueue? @@ -56,7 +57,7 @@ private var sentryReachabilityQueue: DispatchQueue? #if DEBUG || SENTRY_TEST || SENTRY_TEST_CI private var sentryReachabilityIgnoreActualCallback = false -@objc public class SentryReachabilityTestHelper: NSObject { +@_spi(Private) @objc public class SentryReachabilityTestHelper: NSObject { @objc static public func setReachabilityIgnoreActualCallback(_ value: Bool) { SentrySDKLog.debug("Setting ignore actual callback to \(value)") sentryReachabilityIgnoreActualCallback = value @@ -76,7 +77,7 @@ private var sentryReachabilityIgnoreActualCallback = false } #endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI -public func sentryConnectivityCallback(_ flags: SCNetworkReachabilityFlags) { +@_spi(Private) public func sentryConnectivityCallback(_ flags: SCNetworkReachabilityFlags) { objc_sync_enter(sentryReachabilityObservers) defer { objc_sync_exit(sentryReachabilityObservers) } @@ -102,7 +103,11 @@ public func sentryConnectivityCallback(_ flags: SCNetworkReachabilityFlags) { SentrySDKLog.debug("Finished notifying observers.") } -public func sentryConnectivityShouldReportChange(_ flags: SCNetworkReachabilityFlags) -> Bool { +/** + * Check whether the connectivity change should be noted or ignored. + * @return @c true if the connectivity change should be reported + */ +@_spi(Private) public func sentryConnectivityShouldReportChange(_ flags: SCNetworkReachabilityFlags) -> Bool { #if canImport(UIKit) let importantFlags: SCNetworkReachabilityFlags = [.isWWAN, .reachable] #else @@ -119,7 +124,10 @@ public func sentryConnectivityShouldReportChange(_ flags: SCNetworkReachabilityF return true } -public func sentryConnectivityFlagRepresentation(_ flags: SCNetworkReachabilityFlags) -> String { +/** + * Textual representation of a connection type + */ +@_spi(Private) public func sentryConnectivityFlagRepresentation(_ flags: SCNetworkReachabilityFlags) -> String { let connected = flags.contains(.reachable) #if canImport(UIKit) if connected { @@ -132,6 +140,29 @@ public func sentryConnectivityFlagRepresentation(_ flags: SCNetworkReachabilityF #endif // canImport(UIKit) } +// +#if os(visionOS) +/** + * visionOS-specific callback wrapper that handles the different parameter type + * for SCNetworkReachabilityFlags. visionOS uses UInt32 for flags instead of + * the SCNetworkReachabilityFlags type used on other platforms. + */ +private func connectivityCallbackWrapper(_ target: SCNetworkReachability, + _ flags: UInt32, + _ info: UnsafeMutableRawPointer?) { + sentryConnectivityActualCallback(target, SCNetworkReachabilityFlags(rawValue: flags), info) +} +#else +private func connectivityCallbackWrapper(_ target: SCNetworkReachability, + _ flags: SCNetworkReachabilityFlags, + _ info: UnsafeMutableRawPointer?) { + sentryConnectivityActualCallback(target, flags, info) +} +#endif + +/** + * Callback invoked by @c SCNetworkReachability, handles the connection change. + */ private func sentryConnectivityActualCallback( _ target: SCNetworkReachability, _ flags: SCNetworkReachabilityFlags, @@ -189,6 +220,10 @@ private func sentryConnectivityActualCallback( sentryReachabilityQueue = DispatchQueue(label: "io.sentry.cocoa.connectivity") + // Ensure to call CFRelease for the return value of SCNetworkReachabilityCreateWithName, see + // https://developer.apple.com/documentation/systemconfiguration/1514904-scnetworkreachabilitycreatewithn?language=objc + // and + // https://developer.apple.com/documentation/systemconfiguration/scnetworkreachability?language=objc guard let reachabilityRef = SCNetworkReachabilityCreateWithName(nil, "sentry.io") else { return } @@ -205,7 +240,7 @@ private func sentryConnectivityActualCallback( copyDescription: nil ) - SCNetworkReachabilitySetCallback(reachabilityRef, sentryConnectivityActualCallback, &context) + SCNetworkReachabilitySetCallback(reachabilityRef, connectivityCallbackWrapper, &context) SCNetworkReachabilitySetDispatchQueue(reachabilityRef, sentryReachabilityQueue) } From a7542a4a977e122fff29bb0e2353ca3ccb5865b0 Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Fri, 29 Aug 2025 13:57:37 -0300 Subject: [PATCH 05/22] Remove unnecessary public signature --- Sources/Swift/Networking/SentryReachability.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/Swift/Networking/SentryReachability.swift b/Sources/Swift/Networking/SentryReachability.swift index b56051816c2..301651ba7cf 100644 --- a/Sources/Swift/Networking/SentryReachability.swift +++ b/Sources/Swift/Networking/SentryReachability.swift @@ -77,7 +77,7 @@ private var sentryReachabilityIgnoreActualCallback = false } #endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI -@_spi(Private) public func sentryConnectivityCallback(_ flags: SCNetworkReachabilityFlags) { +func sentryConnectivityCallback(_ flags: SCNetworkReachabilityFlags) { objc_sync_enter(sentryReachabilityObservers) defer { objc_sync_exit(sentryReachabilityObservers) } @@ -107,7 +107,7 @@ private var sentryReachabilityIgnoreActualCallback = false * Check whether the connectivity change should be noted or ignored. * @return @c true if the connectivity change should be reported */ -@_spi(Private) public func sentryConnectivityShouldReportChange(_ flags: SCNetworkReachabilityFlags) -> Bool { +func sentryConnectivityShouldReportChange(_ flags: SCNetworkReachabilityFlags) -> Bool { #if canImport(UIKit) let importantFlags: SCNetworkReachabilityFlags = [.isWWAN, .reachable] #else @@ -127,7 +127,7 @@ private var sentryReachabilityIgnoreActualCallback = false /** * Textual representation of a connection type */ -@_spi(Private) public func sentryConnectivityFlagRepresentation(_ flags: SCNetworkReachabilityFlags) -> String { +func sentryConnectivityFlagRepresentation(_ flags: SCNetworkReachabilityFlags) -> String { let connected = flags.contains(.reachable) #if canImport(UIKit) if connected { From e5422d3c2ef85c12012badb4317d788353f1aba6 Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Fri, 29 Aug 2025 14:09:04 -0300 Subject: [PATCH 06/22] Fix compile error on Xcode 14 --- Sources/Swift/Networking/SentryReachability.swift | 4 ++-- Tests/SentryTests/Networking/TestSentryReachability.swift | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/Swift/Networking/SentryReachability.swift b/Sources/Swift/Networking/SentryReachability.swift index 301651ba7cf..35a0eaf7e75 100644 --- a/Sources/Swift/Networking/SentryReachability.swift +++ b/Sources/Swift/Networking/SentryReachability.swift @@ -26,7 +26,7 @@ import Foundation -#if !os(watchOS) && !(os(visionOS) && SENTRY_NO_UIKIT) +#if !os(watchOS) && !((swift(>=5.9) && os(visionOS)) && SENTRY_NO_UIKIT) import SystemConfiguration @objc @@ -295,4 +295,4 @@ private func sentryConnectivityActualCallback( } } -#endif // !os(watchOS) && !(os(visionOS) && !canImport(UIKit)) +#endif // !os(watchOS) && !((swift(>=5.9) && os(visionOS)) && SENTRY_NO_UIKIT) diff --git a/Tests/SentryTests/Networking/TestSentryReachability.swift b/Tests/SentryTests/Networking/TestSentryReachability.swift index 1398ce50514..01597c8196a 100644 --- a/Tests/SentryTests/Networking/TestSentryReachability.swift +++ b/Tests/SentryTests/Networking/TestSentryReachability.swift @@ -1,4 +1,4 @@ -#if !os(watchOS) && !(os(visionOS) && !canImport(UIKit)) +#if !os(watchOS) && !((swift(>=5.9) && os(visionOS)) && !canImport(UIKit)) @_spi(Private) @testable import Sentry import SentryTestUtils @@ -30,4 +30,4 @@ import SentryTestUtils } } -#endif // !os(watchOS) && !(os(visionOS) && !canImport(UIKit)) +#endif // !os(watchOS) && !((swift(>=5.9) && os(visionOS)) && !canImport(UIKit)) From c63a99799cab0b46d55c631cb7e499243870d7b6 Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Fri, 29 Aug 2025 15:19:18 -0300 Subject: [PATCH 07/22] Use nil context --- Sources/Swift/Networking/SentryReachability.swift | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Sources/Swift/Networking/SentryReachability.swift b/Sources/Swift/Networking/SentryReachability.swift index 35a0eaf7e75..4107f94bcc4 100644 --- a/Sources/Swift/Networking/SentryReachability.swift +++ b/Sources/Swift/Networking/SentryReachability.swift @@ -232,15 +232,7 @@ private func sentryConnectivityActualCallback( SentrySDKLog.debug("registering callback for reachability ref \(reachabilityRef)") - var context = SCNetworkReachabilityContext( - version: 0, - info: nil, - retain: nil, - release: nil, - copyDescription: nil - ) - - SCNetworkReachabilitySetCallback(reachabilityRef, connectivityCallbackWrapper, &context) + SCNetworkReachabilitySetCallback(reachabilityRef, connectivityCallbackWrapper, nil) SCNetworkReachabilitySetDispatchQueue(reachabilityRef, sentryReachabilityQueue) } From f35fc7016c0a06445ebb7208b7720b265a303efa Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Mon, 1 Sep 2025 11:50:11 -0300 Subject: [PATCH 08/22] Fix build issue --- Sentry.xcodeproj/project.pbxproj | 4 ++-- Sources/Swift/Networking/SentryReachability.swift | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index c2336469879..234339ce0e8 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -1036,9 +1036,9 @@ F48F74F32E5F9959009D4E7D /* SentryCrashBinaryImageCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F48F74F22E5F9959009D4E7D /* SentryCrashBinaryImageCacheTests.m */; }; F48F75712E5FA630009D4E7D /* SentryBinaryImageCacheCallbacks.m in Sources */ = {isa = PBXBuildFile; fileRef = F48F75702E5FA630009D4E7D /* SentryBinaryImageCacheCallbacks.m */; }; F48F75732E5FA649009D4E7D /* SentryBinaryImageCacheCallbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = F48F75722E5FA649009D4E7D /* SentryBinaryImageCacheCallbacks.h */; }; - F49236EB2E5E4B2F00663673 /* SentryBinaryImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49236EA2E5E4B2F00663673 /* SentryBinaryImageCache.swift */; }; F48F767C2E60B555009D4E7D /* SentryNSTimerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48F767B2E60B555009D4E7D /* SentryNSTimerFactory.swift */; }; F48F78692E61DE28009D4E7D /* SentryReachability.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48F78682E61DE28009D4E7D /* SentryReachability.swift */; }; + F49236EB2E5E4B2F00663673 /* SentryBinaryImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49236EA2E5E4B2F00663673 /* SentryBinaryImageCache.swift */; }; F49D41982DEA27AF00D9244E /* SentryUseNSExceptionCallstackWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49D41972DEA27AF00D9244E /* SentryUseNSExceptionCallstackWrapperTests.swift */; }; F49D419A2DEA2FB000D9244E /* SentryCrashExceptionApplicationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49D41992DEA2FB000D9244E /* SentryCrashExceptionApplicationTests.swift */; }; F49D419C2DEA30C300D9244E /* SentryCrashExceptionApplicationHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = F49D419B2DEA30B800D9244E /* SentryCrashExceptionApplicationHelper.h */; }; @@ -2380,9 +2380,9 @@ F48F74F22E5F9959009D4E7D /* SentryCrashBinaryImageCacheTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryCrashBinaryImageCacheTests.m; sourceTree = ""; }; F48F75702E5FA630009D4E7D /* SentryBinaryImageCacheCallbacks.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryBinaryImageCacheCallbacks.m; sourceTree = ""; }; F48F75722E5FA649009D4E7D /* SentryBinaryImageCacheCallbacks.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryBinaryImageCacheCallbacks.h; path = ../../Sentry/include/SentryBinaryImageCacheCallbacks.h; sourceTree = ""; }; - F49236EA2E5E4B2F00663673 /* SentryBinaryImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryBinaryImageCache.swift; sourceTree = ""; }; F48F767B2E60B555009D4E7D /* SentryNSTimerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryNSTimerFactory.swift; sourceTree = ""; }; F48F78682E61DE28009D4E7D /* SentryReachability.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryReachability.swift; sourceTree = ""; }; + F49236EA2E5E4B2F00663673 /* SentryBinaryImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryBinaryImageCache.swift; sourceTree = ""; }; F49D41972DEA27AF00D9244E /* SentryUseNSExceptionCallstackWrapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryUseNSExceptionCallstackWrapperTests.swift; sourceTree = ""; }; F49D41992DEA2FB000D9244E /* SentryCrashExceptionApplicationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashExceptionApplicationTests.swift; sourceTree = ""; }; F49D419B2DEA30B800D9244E /* SentryCrashExceptionApplicationHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryCrashExceptionApplicationHelper.h; path = include/SentryCrashExceptionApplicationHelper.h; sourceTree = ""; }; diff --git a/Sources/Swift/Networking/SentryReachability.swift b/Sources/Swift/Networking/SentryReachability.swift index 4107f94bcc4..eb83c75c27d 100644 --- a/Sources/Swift/Networking/SentryReachability.swift +++ b/Sources/Swift/Networking/SentryReachability.swift @@ -140,8 +140,7 @@ func sentryConnectivityFlagRepresentation(_ flags: SCNetworkReachabilityFlags) - #endif // canImport(UIKit) } -// -#if os(visionOS) +#if swift(>=5.9) && os(visionOS) /** * visionOS-specific callback wrapper that handles the different parameter type * for SCNetworkReachabilityFlags. visionOS uses UInt32 for flags instead of @@ -158,7 +157,7 @@ private func connectivityCallbackWrapper(_ target: SCNetworkReachability, _ info: UnsafeMutableRawPointer?) { sentryConnectivityActualCallback(target, flags, info) } -#endif +#endif // swift(>=5.9) && os(visionOS) /** * Callback invoked by @c SCNetworkReachability, handles the connection change. From cb96bfa8ad534281cc9a5a4f4f6e2e27f7b637ce Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Wed, 3 Sep 2025 17:38:02 -0300 Subject: [PATCH 09/22] Use NWPathMonitor for iOS12+ --- .../Swift/Networking/SentryReachability.swift | 345 ++++++++---------- .../Networking/SentryReachabilityTests.m | 56 +-- 2 files changed, 161 insertions(+), 240 deletions(-) diff --git a/Sources/Swift/Networking/SentryReachability.swift b/Sources/Swift/Networking/SentryReachability.swift index eb83c75c27d..33f8aea2d71 100644 --- a/Sources/Swift/Networking/SentryReachability.swift +++ b/Sources/Swift/Networking/SentryReachability.swift @@ -1,34 +1,9 @@ -// Adapted from -// https://github.com/bugsnag/bugsnag-cocoa/blob/2f373f21b965f1b13d7070662e2d35f46c17d975/Bugsnag/Delivery/BSGConnectivity.m -// -// Created by Jamie Lynch on 2017-09-04. -// -// Copyright (c) 2017 Bugsnag, Inc. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall remain in place -// in this source code. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - import Foundation #if !os(watchOS) && !((swift(>=5.9) && os(visionOS)) && SENTRY_NO_UIKIT) -import SystemConfiguration +import Network +// MARK: - SentryConectivity @objc public enum SentryConnectivity: Int { case cellular @@ -47,166 +22,41 @@ public enum SentryConnectivity: Int { } } -private let kSCNetworkReachabilityFlagsUninitialized: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: UInt32.max) - -// Global variables are lazy by default -private var sentryReachabilityObservers = NSHashTable.weakObjects() -private var sentryCurrentReachabilityState: SCNetworkReachabilityFlags = kSCNetworkReachabilityFlagsUninitialized -private var sentryReachabilityQueue: DispatchQueue? - -#if DEBUG || SENTRY_TEST || SENTRY_TEST_CI -private var sentryReachabilityIgnoreActualCallback = false - -@_spi(Private) @objc public class SentryReachabilityTestHelper: NSObject { - @objc static public func setReachabilityIgnoreActualCallback(_ value: Bool) { - SentrySDKLog.debug("Setting ignore actual callback to \(value)") - sentryReachabilityIgnoreActualCallback = value - } - - @objc static public func connectivityCallback(_ flags: SCNetworkReachabilityFlags) { - sentryConnectivityCallback(flags) - } - - @objc static public func connectivityFlagRepresentation(_ flags: SCNetworkReachabilityFlags) -> String { - sentryConnectivityFlagRepresentation(flags) - } - - @objc static public func stringForSentryConnectivity(_ type: SentryConnectivity) -> String { - type.toString() - } -} -#endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI - -func sentryConnectivityCallback(_ flags: SCNetworkReachabilityFlags) { - objc_sync_enter(sentryReachabilityObservers) - defer { objc_sync_exit(sentryReachabilityObservers) } - - SentrySDKLog.debug("Entered synchronized region of SentryConnectivityCallback with flags: \(flags.rawValue)") - - guard sentryReachabilityObservers.count > 0 else { - SentrySDKLog.debug("No reachability observers registered. Nothing to do.") - return - } - - guard sentryConnectivityShouldReportChange(flags) else { - SentrySDKLog.debug("SentryConnectivityShouldReportChange returned false for flags \(flags.rawValue), will not report change to observers.") - return - } - - let connected = flags.contains(.reachable) - - SentrySDKLog.debug("Notifying observers...") - for observer in sentryReachabilityObservers.allObjects { - SentrySDKLog.debug("Notifying \(observer)") - observer.connectivityChanged(connected, typeDescription: sentryConnectivityFlagRepresentation(flags)) - } - SentrySDKLog.debug("Finished notifying observers.") -} - -/** - * Check whether the connectivity change should be noted or ignored. - * @return @c true if the connectivity change should be reported - */ -func sentryConnectivityShouldReportChange(_ flags: SCNetworkReachabilityFlags) -> Bool { -#if canImport(UIKit) - let importantFlags: SCNetworkReachabilityFlags = [.isWWAN, .reachable] -#else - let importantFlags: SCNetworkReachabilityFlags = .reachable -#endif // canImport(UIKit) - - let newFlags = SCNetworkReachabilityFlags(rawValue: flags.rawValue & importantFlags.rawValue) - if newFlags == sentryCurrentReachabilityState { - SentrySDKLog.debug("No change in reachability state. SentryConnectivityShouldReportChange will return false for flags \(flags.rawValue), sentryCurrentReachabilityState \(sentryCurrentReachabilityState.rawValue)") - return false - } - - sentryCurrentReachabilityState = newFlags - return true -} - -/** - * Textual representation of a connection type - */ -func sentryConnectivityFlagRepresentation(_ flags: SCNetworkReachabilityFlags) -> String { - let connected = flags.contains(.reachable) -#if canImport(UIKit) - if connected { - return flags.contains(.isWWAN) ? SentryConnectivity.cellular.toString() : SentryConnectivity.wiFi.toString() - } else { - return SentryConnectivity.none.toString() - } -#else - return connected ? SentryConnectivity.wiFi.toString() : SentryConnectivity.none.toString() -#endif // canImport(UIKit) -} - -#if swift(>=5.9) && os(visionOS) -/** - * visionOS-specific callback wrapper that handles the different parameter type - * for SCNetworkReachabilityFlags. visionOS uses UInt32 for flags instead of - * the SCNetworkReachabilityFlags type used on other platforms. - */ -private func connectivityCallbackWrapper(_ target: SCNetworkReachability, - _ flags: UInt32, - _ info: UnsafeMutableRawPointer?) { - sentryConnectivityActualCallback(target, SCNetworkReachabilityFlags(rawValue: flags), info) -} -#else -private func connectivityCallbackWrapper(_ target: SCNetworkReachability, - _ flags: SCNetworkReachabilityFlags, - _ info: UnsafeMutableRawPointer?) { - sentryConnectivityActualCallback(target, flags, info) -} -#endif // swift(>=5.9) && os(visionOS) - -/** - * Callback invoked by @c SCNetworkReachability, handles the connection change. - */ -private func sentryConnectivityActualCallback( - _ target: SCNetworkReachability, - _ flags: SCNetworkReachabilityFlags, - _ info: UnsafeMutableRawPointer? -) { - SentrySDKLog.debug("SentryConnectivityCallback called with target: \(target); flags: \(flags.rawValue)") - -#if DEBUG || SENTRY_TEST || SENTRY_TEST_CI - if sentryReachabilityIgnoreActualCallback { - SentrySDKLog.debug("Ignoring actual callback.") - return - } -#endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI - - sentryConnectivityCallback(flags) -} - -@_spi(Private) @objc public protocol SentryReachabilityObserver: NSObjectProtocol { +@_spi(Private) @objc +public protocol SentryReachabilityObserver: NSObjectProtocol { @objc func connectivityChanged(_ connected: Bool, typeDescription: String) } -@_spi(Private) @objc public class SentryReachability: NSObject { - private var sentryReachabilityRef: SCNetworkReachability? +// MARK: - SentryReachability +@_spi(Private) @objc +public class SentryReachability: NSObject { + private var reachabilityObservers = NSHashTable.weakObjects() + private var currentConnectivity: SentryConnectivity = .none + private var pathMonitor: Any? // NWPathMonitor for iOS 12+ + private var reachabilityQueue: DispatchQueue? #if DEBUG || SENTRY_TEST || SENTRY_TEST_CI @objc public var skipRegisteringActualCallbacks = false + private var ignoreActualCallback = false #endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI @objc(addObserver:) public func add(_ observer: SentryReachabilityObserver) { SentrySDKLog.debug("Adding observer: \(observer)") - objc_sync_enter(sentryReachabilityObservers) - defer { objc_sync_exit(sentryReachabilityObservers) } + objc_sync_enter(reachabilityObservers) + defer { objc_sync_exit(reachabilityObservers) } SentrySDKLog.debug("Synchronized to add observer: \(observer)") - if sentryReachabilityObservers.contains(observer) { + if reachabilityObservers.contains(observer) { SentrySDKLog.debug("Observer already added. Doing nothing.") return } - sentryReachabilityObservers.add(observer) + reachabilityObservers.add(observer) - if sentryReachabilityObservers.count > 1 { + if reachabilityObservers.count > 1 { return } @@ -217,68 +67,140 @@ private func sentryConnectivityActualCallback( } #endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI - sentryReachabilityQueue = DispatchQueue(label: "io.sentry.cocoa.connectivity") - - // Ensure to call CFRelease for the return value of SCNetworkReachabilityCreateWithName, see - // https://developer.apple.com/documentation/systemconfiguration/1514904-scnetworkreachabilitycreatewithn?language=objc - // and - // https://developer.apple.com/documentation/systemconfiguration/scnetworkreachability?language=objc - guard let reachabilityRef = SCNetworkReachabilityCreateWithName(nil, "sentry.io") else { - return + let reachabilityQueue = DispatchQueue(label: "io.sentry.cocoa.connectivity") + self.reachabilityQueue = reachabilityQueue + + if #available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, *) { + let monitor = NWPathMonitor() + pathMonitor = monitor + monitor.pathUpdateHandler = pathUpdateHandler + monitor.start(queue: reachabilityQueue) + + SentrySDKLog.debug("Started NWPathMonitor") + } else { + // For iOS 11 and earlier, simulate always being connected via WiFi + SentrySDKLog.debug("NWPathMonitor not available. Using fallback: always connected via WiFi") + reachabilityQueue.async { [weak self] in + self?.connectivityCallback(.wiFi) + } } - - sentryReachabilityRef = reachabilityRef - - SentrySDKLog.debug("registering callback for reachability ref \(reachabilityRef)") - - SCNetworkReachabilitySetCallback(reachabilityRef, connectivityCallbackWrapper, nil) - SCNetworkReachabilitySetDispatchQueue(reachabilityRef, sentryReachabilityQueue) } @objc(removeObserver:) public func remove(_ observer: SentryReachabilityObserver) { SentrySDKLog.debug("Removing observer: \(observer)") - objc_sync_enter(sentryReachabilityObservers) - defer { objc_sync_exit(sentryReachabilityObservers) } + objc_sync_enter(reachabilityObservers) + defer { objc_sync_exit(reachabilityObservers) } SentrySDKLog.debug("Synchronized to remove observer: \(observer)") - sentryReachabilityObservers.remove(observer) + reachabilityObservers.remove(observer) - if sentryReachabilityObservers.count == 0 { - unsetReachabilityCallback() + if reachabilityObservers.count == 0 { + stopMonitoring() } } - @objc public func removeAllObservers() { + @objc + public func removeAllObservers() { SentrySDKLog.debug("Removing all observers.") - objc_sync_enter(sentryReachabilityObservers) - defer { objc_sync_exit(sentryReachabilityObservers) } + objc_sync_enter(reachabilityObservers) + defer { objc_sync_exit(reachabilityObservers) } SentrySDKLog.debug("Synchronized to remove all observers.") - sentryReachabilityObservers.removeAllObjects() - unsetReachabilityCallback() + reachabilityObservers.removeAllObjects() + stopMonitoring() } - private func unsetReachabilityCallback() { + private func stopMonitoring() { #if DEBUG || SENTRY_TEST || SENTRY_TEST_CI if skipRegisteringActualCallbacks { - SentrySDKLog.debug("Skip unsetting actual callbacks") + SentrySDKLog.debug("Skip stopping actual monitoring") } #endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI - sentryCurrentReachabilityState = kSCNetworkReachabilityFlagsUninitialized + currentConnectivity = .none - if let reachabilityRef = sentryReachabilityRef { - SentrySDKLog.debug("removing callback for reachability ref \(reachabilityRef)") - SCNetworkReachabilitySetCallback(reachabilityRef, nil, nil) - SCNetworkReachabilitySetDispatchQueue(reachabilityRef, nil) - sentryReachabilityRef = nil + // Clean up NWPathMonitor + if #available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, *) { + if let monitor = pathMonitor as? NWPathMonitor { + SentrySDKLog.debug("Stopping NWPathMonitor") + monitor.cancel() + pathMonitor = nil + } } SentrySDKLog.debug("Cleaning up reachability queue.") - sentryReachabilityQueue = nil + reachabilityQueue = nil + } + + @available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, *) + private func pathUpdateHandler(_ path: NWPath) { + SentrySDKLog.debug("SentryPathUpdateHandler called with path status: \(path.status)") + +#if DEBUG || SENTRY_TEST || SENTRY_TEST_CI + if ignoreActualCallback { + SentrySDKLog.debug("Ignoring actual callback.") + return + } +#endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI + + let connectivity = connectivityFromPath(path) + connectivityCallback(connectivity) + } + + @available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, *) + private func connectivityFromPath(_ path: NWPath) -> SentryConnectivity { + guard path.status == .satisfied else { + return .none + } + +#if canImport(UIKit) + if path.usesInterfaceType(.cellular) { + return .cellular + } else { + return .wiFi + } +#else + return .wiFi +#endif // canImport(UIKit) + } + + private func connectivityShouldReportChange(_ connectivity: SentryConnectivity) -> Bool { + if connectivity == currentConnectivity { + SentrySDKLog.debug("No change in reachability state. ConnectivityShouldReportChange will return false for connectivity \(connectivity.toString()), currentConnectivity \(currentConnectivity.toString())") + return false + } + + currentConnectivity = connectivity + return true + } + + fileprivate func connectivityCallback(_ connectivity: SentryConnectivity) { + objc_sync_enter(reachabilityObservers) + defer { objc_sync_exit(reachabilityObservers) } + + SentrySDKLog.debug("Entered synchronized region of SentryConnectivityCallback with connectivity: \(connectivity.toString())") + + guard reachabilityObservers.count > 0 else { + SentrySDKLog.debug("No reachability observers registered. Nothing to do.") + return + } + + guard connectivityShouldReportChange(connectivity) else { + SentrySDKLog.debug("ConnectivityShouldReportChange returned false for connectivity \(connectivity.toString()), will not report change to observers.") + return + } + + let connected = connectivity != .none + + SentrySDKLog.debug("Notifying observers...") + for observer in reachabilityObservers.allObjects { + SentrySDKLog.debug("Notifying \(observer)") + observer.connectivityChanged(connected, typeDescription: connectivity.toString()) + } + SentrySDKLog.debug("Finished notifying observers.") } deinit { @@ -286,4 +208,25 @@ private func sentryConnectivityActualCallback( } } +// MARK: - Test utils +#if DEBUG || SENTRY_TEST || SENTRY_TEST_CI +@available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, *) +extension SentryReachability { + @objc public func setReachabilityIgnoreActualCallback(_ value: Bool) { + SentrySDKLog.debug("Setting ignore actual callback to \(value)") + ignoreActualCallback = value + } + + @objc public func triggerConnectivityCallback(_ connectivity: SentryConnectivity) { + connectivityCallback(connectivity) + } +} + +@_spi(Private) @objc public class SentryReachabilityTestHelper: NSObject { + @objc static public func stringForSentryConnectivity(_ type: SentryConnectivity) -> String { + type.toString() + } +} +#endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI + #endif // !os(watchOS) && !((swift(>=5.9) && os(visionOS)) && SENTRY_NO_UIKIT) diff --git a/Tests/SentryTests/Networking/SentryReachabilityTests.m b/Tests/SentryTests/Networking/SentryReachabilityTests.m index e800fe8a1ab..62af028ff50 100644 --- a/Tests/SentryTests/Networking/SentryReachabilityTests.m +++ b/Tests/SentryTests/Networking/SentryReachabilityTests.m @@ -1,7 +1,6 @@ #import "SentryLogC.h" #import "SentrySwift.h" #import -@import SystemConfiguration; @interface TestSentryReachabilityObserver : NSObject @@ -39,7 +38,7 @@ - (void)setUp // Ignore the actual reachability callbacks, cause we call the callbacks manually. // Otherwise, the actual reachability callbacks are called during later unrelated tests causing // flakes. - [SentryReachabilityTestHelper setReachabilityIgnoreActualCallback:YES]; + [self.reachability setReachabilityIgnoreActualCallback:YES]; self.reachability = [[SentryReachability alloc] init]; self.reachability.skipRegisteringActualCallbacks = YES; @@ -49,39 +48,19 @@ - (void)tearDown { [self.reachability removeAllObservers]; self.reachability = nil; - [SentryReachabilityTestHelper setReachabilityIgnoreActualCallback:NO]; + [self.reachability setReachabilityIgnoreActualCallback:NO]; } - (void)testConnectivityRepresentations { XCTAssertEqualObjects( - [SentryReachabilityTestHelper stringForSentryConnectivity:SentryConnectivityNone], - [SentryReachabilityTestHelper connectivityFlagRepresentation:0]); + @"none", [SentryReachabilityTestHelper stringForSentryConnectivity:SentryConnectivityNone]); XCTAssertEqualObjects( - [SentryReachabilityTestHelper stringForSentryConnectivity:SentryConnectivityNone], - [SentryReachabilityTestHelper - connectivityFlagRepresentation:kSCNetworkReachabilityFlagsIsDirect]); + @"wifi", [SentryReachabilityTestHelper stringForSentryConnectivity:SentryConnectivityWiFi]); # if SENTRY_HAS_UIKIT - // kSCNetworkReachabilityFlagsIsWWAN does not exist on macOS - XCTAssertEqualObjects( - [SentryReachabilityTestHelper stringForSentryConnectivity:SentryConnectivityNone], - [SentryReachabilityTestHelper - connectivityFlagRepresentation:kSCNetworkReachabilityFlagsIsWWAN]); - XCTAssertEqualObjects( - [SentryReachabilityTestHelper stringForSentryConnectivity:SentryConnectivityCellular], - [SentryReachabilityTestHelper - connectivityFlagRepresentation:kSCNetworkReachabilityFlagsIsWWAN | - kSCNetworkReachabilityFlagsReachable]); + XCTAssertEqualObjects(@"cellular", + [SentryReachabilityTestHelper stringForSentryConnectivity:SentryConnectivityCellular]); # endif // SENTRY_HAS_UIKIT - XCTAssertEqualObjects( - [SentryReachabilityTestHelper stringForSentryConnectivity:SentryConnectivityWiFi], - [SentryReachabilityTestHelper - connectivityFlagRepresentation:kSCNetworkReachabilityFlagsReachable]); - XCTAssertEqualObjects( - [SentryReachabilityTestHelper stringForSentryConnectivity:SentryConnectivityWiFi], - [SentryReachabilityTestHelper - connectivityFlagRepresentation:kSCNetworkReachabilityFlagsReachable | - kSCNetworkReachabilityFlagsIsDirect]); } - (void)testMultipleReachabilityObservers @@ -92,11 +71,10 @@ - (void)testMultipleReachabilityObservers [self.reachability addObserver:observerA]; NSLog(@"[Sentry] [TEST] throwaway reachability callback, setting to reachable"); - [SentryReachabilityTestHelper - connectivityCallback:kSCNetworkReachabilityFlagsReachable]; // ignored, as it's the - // first callback + [self.reachability + triggerConnectivityCallback:SentryConnectivityWiFi]; // ignored, as it's the first callback NSLog(@"[Sentry] [TEST] reachability callback set to unreachable"); - [SentryReachabilityTestHelper connectivityCallback:0]; + [self.reachability triggerConnectivityCallback:SentryConnectivityNone]; NSLog(@"[Sentry] [TEST] creating observer B"); TestSentryReachabilityObserver *observerB = [[TestSentryReachabilityObserver alloc] init]; @@ -104,15 +82,15 @@ - (void)testMultipleReachabilityObservers [self.reachability addObserver:observerB]; NSLog(@"[Sentry] [TEST] reachability callback set back to reachable"); - [SentryReachabilityTestHelper connectivityCallback:kSCNetworkReachabilityFlagsReachable]; + [self.reachability triggerConnectivityCallback:SentryConnectivityWiFi]; NSLog(@"[Sentry] [TEST] reachability callback set back to unreachable"); - [SentryReachabilityTestHelper connectivityCallback:0]; + [self.reachability triggerConnectivityCallback:SentryConnectivityNone]; NSLog(@"[Sentry] [TEST] removing observer B as reachability observer"); [self.reachability removeObserver:observerB]; NSLog(@"[Sentry] [TEST] reachability callback set back to reachable"); - [SentryReachabilityTestHelper connectivityCallback:kSCNetworkReachabilityFlagsReachable]; + [self.reachability triggerConnectivityCallback:SentryConnectivityWiFi]; XCTAssertEqual(5, observerA.connectivityChangedInvocations); XCTAssertEqual(2, observerB.connectivityChangedInvocations); @@ -127,7 +105,7 @@ - (void)testNoObservers [self.reachability addObserver:observer]; [self.reachability removeObserver:observer]; - [SentryReachabilityTestHelper connectivityCallback:kSCNetworkReachabilityFlagsReachable]; + [self.reachability triggerConnectivityCallback:SentryConnectivityWiFi]; XCTAssertEqual(0, observer.connectivityChangedInvocations); @@ -140,7 +118,7 @@ - (void)testReportSameObserver_OnlyCalledOnce [self.reachability addObserver:observer]; [self.reachability addObserver:observer]; - [SentryReachabilityTestHelper connectivityCallback:kSCNetworkReachabilityFlagsReachable]; + [self.reachability triggerConnectivityCallback:SentryConnectivityWiFi]; XCTAssertEqual(1, observer.connectivityChangedInvocations); @@ -152,9 +130,9 @@ - (void)testReportSameReachabilityState_OnlyCalledOnce TestSentryReachabilityObserver *observer = [[TestSentryReachabilityObserver alloc] init]; [self.reachability addObserver:observer]; - [SentryReachabilityTestHelper connectivityCallback:kSCNetworkReachabilityFlagsReachable]; - [SentryReachabilityTestHelper connectivityCallback:kSCNetworkReachabilityFlagsReachable]; - [SentryReachabilityTestHelper connectivityCallback:kSCNetworkReachabilityFlagsReachable]; + [self.reachability triggerConnectivityCallback:SentryConnectivityWiFi]; + [self.reachability triggerConnectivityCallback:SentryConnectivityWiFi]; + [self.reachability triggerConnectivityCallback:SentryConnectivityWiFi]; XCTAssertEqual(1, observer.connectivityChangedInvocations); From 62f0e70b6425a9a890f490864a296a1feba2806d Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Thu, 4 Sep 2025 15:52:56 -0300 Subject: [PATCH 10/22] Use NSLock --- .../Swift/Networking/SentryReachability.swift | 19 ++++++++++--------- .../Networking/SentryReachabilityTests.m | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Sources/Swift/Networking/SentryReachability.swift b/Sources/Swift/Networking/SentryReachability.swift index 33f8aea2d71..11dd206fb05 100644 --- a/Sources/Swift/Networking/SentryReachability.swift +++ b/Sources/Swift/Networking/SentryReachability.swift @@ -34,6 +34,7 @@ public class SentryReachability: NSObject { private var currentConnectivity: SentryConnectivity = .none private var pathMonitor: Any? // NWPathMonitor for iOS 12+ private var reachabilityQueue: DispatchQueue? + private let observersLock = NSLock() #if DEBUG || SENTRY_TEST || SENTRY_TEST_CI @objc public var skipRegisteringActualCallbacks = false @@ -44,8 +45,8 @@ public class SentryReachability: NSObject { public func add(_ observer: SentryReachabilityObserver) { SentrySDKLog.debug("Adding observer: \(observer)") - objc_sync_enter(reachabilityObservers) - defer { objc_sync_exit(reachabilityObservers) } + observersLock.lock() + defer { observersLock.unlock() } SentrySDKLog.debug("Synchronized to add observer: \(observer)") @@ -79,7 +80,7 @@ public class SentryReachability: NSObject { SentrySDKLog.debug("Started NWPathMonitor") } else { // For iOS 11 and earlier, simulate always being connected via WiFi - SentrySDKLog.debug("NWPathMonitor not available. Using fallback: always connected via WiFi") + SentrySDKLog.warning("NWPathMonitor not available. Using fallback: always connected via WiFi") reachabilityQueue.async { [weak self] in self?.connectivityCallback(.wiFi) } @@ -90,8 +91,8 @@ public class SentryReachability: NSObject { public func remove(_ observer: SentryReachabilityObserver) { SentrySDKLog.debug("Removing observer: \(observer)") - objc_sync_enter(reachabilityObservers) - defer { objc_sync_exit(reachabilityObservers) } + observersLock.lock() + defer { observersLock.unlock() } SentrySDKLog.debug("Synchronized to remove observer: \(observer)") reachabilityObservers.remove(observer) @@ -105,8 +106,8 @@ public class SentryReachability: NSObject { public func removeAllObservers() { SentrySDKLog.debug("Removing all observers.") - objc_sync_enter(reachabilityObservers) - defer { objc_sync_exit(reachabilityObservers) } + observersLock.lock() + defer { observersLock.unlock() } SentrySDKLog.debug("Synchronized to remove all observers.") reachabilityObservers.removeAllObjects() @@ -178,8 +179,8 @@ public class SentryReachability: NSObject { } fileprivate func connectivityCallback(_ connectivity: SentryConnectivity) { - objc_sync_enter(reachabilityObservers) - defer { objc_sync_exit(reachabilityObservers) } + observersLock.lock() + defer { observersLock.unlock() } SentrySDKLog.debug("Entered synchronized region of SentryConnectivityCallback with connectivity: \(connectivity.toString())") diff --git a/Tests/SentryTests/Networking/SentryReachabilityTests.m b/Tests/SentryTests/Networking/SentryReachabilityTests.m index 62af028ff50..e50d68024df 100644 --- a/Tests/SentryTests/Networking/SentryReachabilityTests.m +++ b/Tests/SentryTests/Networking/SentryReachabilityTests.m @@ -47,8 +47,8 @@ - (void)setUp - (void)tearDown { [self.reachability removeAllObservers]; - self.reachability = nil; [self.reachability setReachabilityIgnoreActualCallback:NO]; + self.reachability = nil; } - (void)testConnectivityRepresentations From f2edc81cc6be83abf163ce4e9da1321923a89117 Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Fri, 5 Sep 2025 10:32:26 -0300 Subject: [PATCH 11/22] Update sdk_api.json --- sdk_api.json | 1484 +++++++++++++++++++++++------------------------ sdk_api_V9.json | 1484 +++++++++++++++++++++++------------------------ 2 files changed, 1484 insertions(+), 1484 deletions(-) diff --git a/sdk_api.json b/sdk_api.json index 923aed03c1a..f8d718e340a 100644 --- a/sdk_api.json +++ b/sdk_api.json @@ -43270,6 +43270,13 @@ "declKind": "Import", "moduleName": "Sentry" }, + { + "kind": "Import", + "name": "Network", + "printedName": "Network", + "declKind": "Import", + "moduleName": "Sentry" + }, { "kind": "Import", "name": "ObjectiveC", @@ -43294,13 +43301,6 @@ "Exported" ] }, - { - "kind": "Import", - "name": "SystemConfiguration", - "printedName": "SystemConfiguration", - "declKind": "Import", - "moduleName": "Sentry" - }, { "kind": "Import", "name": "UIKit", @@ -43345,260 +43345,309 @@ }, { "kind": "TypeDecl", - "name": "SentryViewScreenshotOptions", - "printedName": "SentryViewScreenshotOptions", + "name": "SentryConnectivity", + "printedName": "SentryConnectivity", "children": [ { - "kind": "TypeDecl", - "name": "DefaultValues", - "printedName": "DefaultValues", + "kind": "Var", + "name": "cellular", + "printedName": "cellular", "children": [ { - "kind": "Var", - "name": "enableViewRendererV2", - "printedName": "enableViewRendererV2", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Var", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvpZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvpZ", - "moduleName": "Sentry", - "static": true, - "declAttributes": [ - "Final", - "HasStorage" - ], - "isLet": true, - "hasStorage": true, - "accessors": [ + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + }, { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryConnectivity.Type", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" } - ], - "declKind": "Accessor", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvgZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvgZ", - "moduleName": "Sentry", - "static": true, - "implicit": true, - "declAttributes": [ - "Final" - ], - "accessorKind": "get" + ] } ] - }, + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityCellular", + "mangledName": "$s6Sentry0A12ConnectivityO8cellularyA2CmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "wiFi", + "printedName": "wiFi", + "children": [ { - "kind": "Var", - "name": "enableFastViewRendering", - "printedName": "enableFastViewRendering", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Var", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvpZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvpZ", - "moduleName": "Sentry", - "static": true, - "declAttributes": [ - "Final", - "HasStorage" - ], - "isLet": true, - "hasStorage": true, - "accessors": [ + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + }, { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryConnectivity.Type", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" } - ], - "declKind": "Accessor", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvgZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvgZ", - "moduleName": "Sentry", - "static": true, - "implicit": true, - "declAttributes": [ - "Final" - ], - "accessorKind": "get" + ] } ] - }, + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityWiFi", + "mangledName": "$s6Sentry0A12ConnectivityO4wiFiyA2CmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "none", + "printedName": "none", + "children": [ { - "kind": "Var", - "name": "maskAllText", - "printedName": "maskAllText", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Var", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvpZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvpZ", - "moduleName": "Sentry", - "static": true, - "declAttributes": [ - "Final", - "HasStorage" - ], - "isLet": true, - "hasStorage": true, - "accessors": [ + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + }, { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryConnectivity.Type", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" } - ], - "declKind": "Accessor", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvgZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvgZ", - "moduleName": "Sentry", - "static": true, - "implicit": true, - "declAttributes": [ - "Final" - ], - "accessorKind": "get" + ] } ] - }, + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityNone", + "mangledName": "$s6Sentry0A12ConnectivityO4noneyA2CmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ { - "kind": "Var", - "name": "maskAllImages", - "printedName": "maskAllImages", + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryConnectivity?", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" } ], - "declKind": "Var", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvpZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvpZ", - "moduleName": "Sentry", - "static": true, - "declAttributes": [ - "Final", - "HasStorage" - ], - "isLet": true, - "hasStorage": true, - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Accessor", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvgZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvgZ", - "moduleName": "Sentry", - "static": true, - "implicit": true, - "declAttributes": [ - "Final" - ], - "accessorKind": "get" - } - ] + "usr": "s:Sq" }, { - "kind": "Var", - "name": "maskedViewClasses", - "printedName": "maskedViewClasses", + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A12ConnectivityO8rawValueACSgSi_tcfc", + "mangledName": "$s6Sentry0A12ConnectivityO8rawValueACSgSi_tcfc", + "moduleName": "Sentry", + "init_kind": "Designated" + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A12ConnectivityO8RawValuea", + "mangledName": "$s6Sentry0A12ConnectivityO8RawValuea", + "moduleName": "Sentry" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A12ConnectivityO8rawValueSivp", + "mangledName": "$s6Sentry0A12ConnectivityO8rawValueSivp", + "moduleName": "Sentry", + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", "children": [ { "kind": "TypeNominal", - "name": "Array", - "printedName": "[Swift.AnyClass]", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A12ConnectivityO8rawValueSivg", + "mangledName": "$s6Sentry0A12ConnectivityO8rawValueSivg", + "moduleName": "Sentry", + "accessorKind": "get" + } + ] + } + ], + "declKind": "Enum", + "usr": "c:@M@Sentry@E@SentryConnectivity", + "mangledName": "$s6Sentry0A12ConnectivityO", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryConnectivity.RawValue", "children": [ { - "kind": "TypeNameAlias", - "name": "AnyClass", - "printedName": "Swift.AnyClass", - "children": [ - { - "kind": "TypeNominal", - "name": "ExistentialMetatype", - "printedName": "any Swift.AnyObject.Type", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Swift.AnyObject", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Builtin.AnyObject", - "children": [ - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "AnyObject" - } - ] - } - ] - } - ] - } - ] + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" } - ], - "usr": "s:Sa" + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryViewScreenshotOptions", + "printedName": "SentryViewScreenshotOptions", + "children": [ + { + "kind": "TypeDecl", + "name": "DefaultValues", + "printedName": "DefaultValues", + "children": [ + { + "kind": "Var", + "name": "enableViewRendererV2", + "printedName": "enableViewRendererV2", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Var", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvpZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvpZ", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvpZ", "moduleName": "Sentry", "static": true, "declAttributes": [ @@ -43615,49 +43664,14 @@ "children": [ { "kind": "TypeNominal", - "name": "Array", - "printedName": "[Swift.AnyClass]", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyClass", - "printedName": "Swift.AnyClass", - "children": [ - { - "kind": "TypeNominal", - "name": "ExistentialMetatype", - "printedName": "any Swift.AnyObject.Type", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Swift.AnyObject", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Builtin.AnyObject", - "children": [ - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "AnyObject" - } - ] - } - ] - } - ] - } - ] - } - ], - "usr": "s:Sa" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Accessor", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvgZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvgZ", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvgZ", "moduleName": "Sentry", "static": true, "implicit": true, @@ -43670,13 +43684,160 @@ }, { "kind": "Var", - "name": "unmaskedViewClasses", - "printedName": "unmaskedViewClasses", + "name": "enableFastViewRendering", + "printedName": "enableFastViewRendering", "children": [ { "kind": "TypeNominal", - "name": "Array", - "printedName": "[Swift.AnyClass]", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "maskAllText", + "printedName": "maskAllText", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "maskAllImages", + "printedName": "maskAllImages", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "maskedViewClasses", + "printedName": "maskedViewClasses", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", "children": [ { "kind": "TypeNameAlias", @@ -43716,8 +43877,8 @@ } ], "declKind": "Var", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvpZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvpZ", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvpZ", "moduleName": "Sentry", "static": true, "declAttributes": [ @@ -43775,8 +43936,8 @@ } ], "declKind": "Accessor", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvgZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvgZ", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvgZ", "moduleName": "Sentry", "static": true, "implicit": true, @@ -43786,69 +43947,188 @@ "accessorKind": "get" } ] - } - ], - "declKind": "Class", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC", - "moduleName": "Sentry", - "hasMissingDesignatedInitializers": true, - "conformances": [ - { - "kind": "Conformance", - "name": "Copyable", - "printedName": "Copyable", - "usr": "s:s8CopyableP", - "mangledName": "$ss8CopyableP" }, { - "kind": "Conformance", - "name": "Escapable", - "printedName": "Escapable", - "usr": "s:s9EscapableP", - "mangledName": "$ss9EscapableP" - } - ] - }, - { - "kind": "Var", - "name": "enableViewRendererV2", - "printedName": "enableViewRendererV2", - "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)enableViewRendererV2", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV2Sbvp", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC", - "HasStorage" - ], - "hasStorage": true, - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "Var", + "name": "unmaskedViewClasses", + "printedName": "unmaskedViewClasses", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" } ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)enableViewRendererV2", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV2Sbvg", + "declKind": "Var", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvpZ", "moduleName": "Sentry", - "implicit": true, + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + } + ], + "declKind": "Class", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC", + "moduleName": "Sentry", + "hasMissingDesignatedInitializers": true, + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + } + ] + }, + { + "kind": "Var", + "name": "enableViewRendererV2", + "printedName": "enableViewRendererV2", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)enableViewRendererV2", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV2Sbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)enableViewRendererV2", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV2Sbvg", + "moduleName": "Sentry", + "implicit": true, "declAttributes": [ "ObjC" ], @@ -44519,432 +44799,135 @@ { "kind": "TypeNominal", "name": "Bool", - "printedName": "Swift.Bool", - "hasDefaultArg": true, - "usr": "s:Sb" - }, - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "hasDefaultArg": true, - "usr": "s:Sb" - }, - { - "kind": "TypeNominal", - "name": "Array", - "printedName": "[Swift.AnyClass]", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyClass", - "printedName": "Swift.AnyClass", - "children": [ - { - "kind": "TypeNominal", - "name": "ExistentialMetatype", - "printedName": "any Swift.AnyObject.Type", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Swift.AnyObject", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Builtin.AnyObject", - "children": [ - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "AnyObject" - } - ] - } - ] - } - ] - } - ] - } - ], - "hasDefaultArg": true, - "usr": "s:Sa" - }, - { - "kind": "TypeNominal", - "name": "Array", - "printedName": "[Swift.AnyClass]", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyClass", - "printedName": "Swift.AnyClass", - "children": [ - { - "kind": "TypeNominal", - "name": "ExistentialMetatype", - "printedName": "any Swift.AnyObject.Type", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Swift.AnyObject", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Builtin.AnyObject", - "children": [ - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "AnyObject" - } - ] - } - ] - } - ] - } - ] - } - ], - "hasDefaultArg": true, - "usr": "s:Sa" - } - ], - "declKind": "Constructor", - "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)initWithEnableViewRendererV2:enableFastViewRendering:maskAllText:maskAllImages:maskedViewClasses:unmaskedViewClasses:", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV20e4FastB9Rendering11maskAllText0jK6Images06maskedB7Classes08unmaskedbO0ACSb_S3bSayyXlXpGAJtcfc", - "moduleName": "Sentry", - "objc_name": "initWithEnableViewRendererV2:enableFastViewRendering:maskAllText:maskAllImages:maskedViewClasses:unmaskedViewClasses:", - "declAttributes": [ - "ObjC" - ], - "init_kind": "Designated" - }, - { - "kind": "Var", - "name": "description", - "printedName": "description", - "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - } - ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)description", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC11descriptionSSvp", - "moduleName": "Sentry", - "overriding": true, - "objc_name": "description", - "declAttributes": [ - "ObjC", - "Dynamic", - "Override" - ], - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - } - ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)description", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC11descriptionSSvg", - "moduleName": "Sentry", - "overriding": true, - "objc_name": "description", - "declAttributes": [ - "Dynamic", - "ObjC", - "Override" - ], - "accessorKind": "get" - } - ] - } - ], - "declKind": "Class", - "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC", - "moduleName": "Sentry", - "declAttributes": [ - "ObjCMembers", - "ObjC" - ], - "superclassUsr": "c:objc(cs)NSObject", - "inheritsConvenienceInitializers": true, - "superclassNames": [ - "ObjectiveC.NSObject" - ], - "conformances": [ - { - "kind": "Conformance", - "name": "SentryRedactOptions", - "printedName": "SentryRedactOptions", - "usr": "c:@M@Sentry@objc(pl)SentryRedactOptions", - "mangledName": "$s6Sentry0A13RedactOptionsP" - }, - { - "kind": "Conformance", - "name": "Copyable", - "printedName": "Copyable", - "usr": "s:s8CopyableP", - "mangledName": "$ss8CopyableP" - }, - { - "kind": "Conformance", - "name": "Escapable", - "printedName": "Escapable", - "usr": "s:s9EscapableP", - "mangledName": "$ss9EscapableP" - }, - { - "kind": "Conformance", - "name": "NSObjectProtocol", - "printedName": "NSObjectProtocol", - "usr": "c:objc(pl)NSObject" - }, - { - "kind": "Conformance", - "name": "Equatable", - "printedName": "Equatable", - "usr": "s:SQ", - "mangledName": "$sSQ" - }, - { - "kind": "Conformance", - "name": "Hashable", - "printedName": "Hashable", - "usr": "s:SH", - "mangledName": "$sSH" - }, - { - "kind": "Conformance", - "name": "CVarArg", - "printedName": "CVarArg", - "usr": "s:s7CVarArgP", - "mangledName": "$ss7CVarArgP" - }, - { - "kind": "Conformance", - "name": "CustomStringConvertible", - "printedName": "CustomStringConvertible", - "usr": "s:s23CustomStringConvertibleP", - "mangledName": "$ss23CustomStringConvertibleP" - }, - { - "kind": "Conformance", - "name": "CustomDebugStringConvertible", - "printedName": "CustomDebugStringConvertible", - "usr": "s:s28CustomDebugStringConvertibleP", - "mangledName": "$ss28CustomDebugStringConvertibleP" - } - ] - }, - { - "kind": "TypeDecl", - "name": "SentryConnectivity", - "printedName": "SentryConnectivity", - "children": [ - { - "kind": "Var", - "name": "cellular", - "printedName": "cellular", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentryConnectivity.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - } - ] - } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityCellular", - "mangledName": "$s6Sentry0A12ConnectivityO8cellularyA2CmF", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "wiFi", - "printedName": "wiFi", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentryConnectivity.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - } - ] - } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityWiFi", - "mangledName": "$s6Sentry0A12ConnectivityO4wiFiyA2CmF", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "none", - "printedName": "none", - "children": [ + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + }, { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", "children": [ { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentryConnectivity.Type", + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", "children": [ { "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] } ] } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityNone", - "mangledName": "$s6Sentry0A12ConnectivityO4noneyA2CmF", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Constructor", - "name": "init", - "printedName": "init(rawValue:)", - "children": [ + ], + "hasDefaultArg": true, + "usr": "s:Sa" + }, { "kind": "TypeNominal", - "name": "Optional", - "printedName": "Sentry.SentryConnectivity?", + "name": "Array", + "printedName": "[Swift.AnyClass]", "children": [ { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] } ], - "usr": "s:Sq" - }, - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" + "hasDefaultArg": true, + "usr": "s:Sa" } ], "declKind": "Constructor", - "usr": "s:6Sentry0A12ConnectivityO8rawValueACSgSi_tcfc", - "mangledName": "$s6Sentry0A12ConnectivityO8rawValueACSgSi_tcfc", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)initWithEnableViewRendererV2:enableFastViewRendering:maskAllText:maskAllImages:maskedViewClasses:unmaskedViewClasses:", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV20e4FastB9Rendering11maskAllText0jK6Images06maskedB7Classes08unmaskedbO0ACSb_S3bSayyXlXpGAJtcfc", "moduleName": "Sentry", - "init_kind": "Designated" - }, - { - "kind": "TypeAlias", - "name": "RawValue", - "printedName": "RawValue", - "children": [ - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" - } + "objc_name": "initWithEnableViewRendererV2:enableFastViewRendering:maskAllText:maskAllImages:maskedViewClasses:unmaskedViewClasses:", + "declAttributes": [ + "ObjC" ], - "declKind": "TypeAlias", - "usr": "s:6Sentry0A12ConnectivityO8RawValuea", - "mangledName": "$s6Sentry0A12ConnectivityO8RawValuea", - "moduleName": "Sentry" + "init_kind": "Designated" }, { "kind": "Var", - "name": "rawValue", - "printedName": "rawValue", + "name": "description", + "printedName": "description", "children": [ { "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "declKind": "Var", - "usr": "s:6Sentry0A12ConnectivityO8rawValueSivp", - "mangledName": "$s6Sentry0A12ConnectivityO8rawValueSivp", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)description", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC11descriptionSSvp", "moduleName": "Sentry", + "overriding": true, + "objc_name": "description", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], "accessors": [ { "kind": "Accessor", @@ -44953,29 +44936,48 @@ "children": [ { "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "declKind": "Accessor", - "usr": "s:6Sentry0A12ConnectivityO8rawValueSivg", - "mangledName": "$s6Sentry0A12ConnectivityO8rawValueSivg", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)description", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC11descriptionSSvg", "moduleName": "Sentry", + "overriding": true, + "objc_name": "description", + "declAttributes": [ + "Dynamic", + "ObjC", + "Override" + ], "accessorKind": "get" } ] } ], - "declKind": "Enum", - "usr": "c:@M@Sentry@E@SentryConnectivity", - "mangledName": "$s6Sentry0A12ConnectivityO", + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC", "moduleName": "Sentry", "declAttributes": [ + "ObjCMembers", "ObjC" ], - "enumRawTypeName": "Int", + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], "conformances": [ + { + "kind": "Conformance", + "name": "SentryRedactOptions", + "printedName": "SentryRedactOptions", + "usr": "c:@M@Sentry@objc(pl)SentryRedactOptions", + "mangledName": "$s6Sentry0A13RedactOptionsP" + }, { "kind": "Conformance", "name": "Copyable", @@ -44990,6 +44992,12 @@ "usr": "s:s9EscapableP", "mangledName": "$ss9EscapableP" }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, { "kind": "Conformance", "name": "Equatable", @@ -45006,32 +45014,24 @@ }, { "kind": "Conformance", - "name": "RawRepresentable", - "printedName": "RawRepresentable", - "children": [ - { - "kind": "TypeWitness", - "name": "RawValue", - "printedName": "RawValue", - "children": [ - { - "kind": "TypeNameAlias", - "name": "RawValue", - "printedName": "Sentry.SentryConnectivity.RawValue", - "children": [ - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" - } - ] - } - ] - } - ], - "usr": "s:SY", - "mangledName": "$sSY" + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" } ] }, diff --git a/sdk_api_V9.json b/sdk_api_V9.json index 7b4bba97548..4f9b0c3b4eb 100644 --- a/sdk_api_V9.json +++ b/sdk_api_V9.json @@ -40439,6 +40439,13 @@ "declKind": "Import", "moduleName": "Sentry" }, + { + "kind": "Import", + "name": "Network", + "printedName": "Network", + "declKind": "Import", + "moduleName": "Sentry" + }, { "kind": "Import", "name": "ObjectiveC", @@ -40463,13 +40470,6 @@ "Exported" ] }, - { - "kind": "Import", - "name": "SystemConfiguration", - "printedName": "SystemConfiguration", - "declKind": "Import", - "moduleName": "Sentry" - }, { "kind": "Import", "name": "UIKit", @@ -40514,260 +40514,309 @@ }, { "kind": "TypeDecl", - "name": "SentryViewScreenshotOptions", - "printedName": "SentryViewScreenshotOptions", + "name": "SentryConnectivity", + "printedName": "SentryConnectivity", "children": [ { - "kind": "TypeDecl", - "name": "DefaultValues", - "printedName": "DefaultValues", + "kind": "Var", + "name": "cellular", + "printedName": "cellular", "children": [ { - "kind": "Var", - "name": "enableViewRendererV2", - "printedName": "enableViewRendererV2", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Var", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvpZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvpZ", - "moduleName": "Sentry", - "static": true, - "declAttributes": [ - "Final", - "HasStorage" - ], - "isLet": true, - "hasStorage": true, - "accessors": [ + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + }, { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryConnectivity.Type", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" } - ], - "declKind": "Accessor", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvgZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvgZ", - "moduleName": "Sentry", - "static": true, - "implicit": true, - "declAttributes": [ - "Final" - ], - "accessorKind": "get" + ] } ] - }, + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityCellular", + "mangledName": "$s6Sentry0A12ConnectivityO8cellularyA2CmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "wiFi", + "printedName": "wiFi", + "children": [ { - "kind": "Var", - "name": "enableFastViewRendering", - "printedName": "enableFastViewRendering", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Var", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvpZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvpZ", - "moduleName": "Sentry", - "static": true, - "declAttributes": [ - "Final", - "HasStorage" - ], - "isLet": true, - "hasStorage": true, - "accessors": [ + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + }, { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryConnectivity.Type", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" } - ], - "declKind": "Accessor", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvgZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvgZ", - "moduleName": "Sentry", - "static": true, - "implicit": true, - "declAttributes": [ - "Final" - ], - "accessorKind": "get" + ] } ] - }, + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityWiFi", + "mangledName": "$s6Sentry0A12ConnectivityO4wiFiyA2CmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "none", + "printedName": "none", + "children": [ { - "kind": "Var", - "name": "maskAllText", - "printedName": "maskAllText", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Var", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvpZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvpZ", - "moduleName": "Sentry", - "static": true, - "declAttributes": [ - "Final", - "HasStorage" - ], - "isLet": true, - "hasStorage": true, - "accessors": [ + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" + }, { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryConnectivity.Type", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" } - ], - "declKind": "Accessor", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvgZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvgZ", - "moduleName": "Sentry", - "static": true, - "implicit": true, - "declAttributes": [ - "Final" - ], - "accessorKind": "get" + ] } ] - }, + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityNone", + "mangledName": "$s6Sentry0A12ConnectivityO4noneyA2CmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ { - "kind": "Var", - "name": "maskAllImages", - "printedName": "maskAllImages", + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryConnectivity?", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "SentryConnectivity", + "printedName": "Sentry.SentryConnectivity", + "usr": "c:@M@Sentry@E@SentryConnectivity" } ], - "declKind": "Var", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvpZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvpZ", - "moduleName": "Sentry", - "static": true, - "declAttributes": [ - "Final", - "HasStorage" - ], - "isLet": true, - "hasStorage": true, - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Accessor", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvgZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvgZ", - "moduleName": "Sentry", - "static": true, - "implicit": true, - "declAttributes": [ - "Final" - ], - "accessorKind": "get" - } - ] + "usr": "s:Sq" }, { - "kind": "Var", - "name": "maskedViewClasses", - "printedName": "maskedViewClasses", + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A12ConnectivityO8rawValueACSgSi_tcfc", + "mangledName": "$s6Sentry0A12ConnectivityO8rawValueACSgSi_tcfc", + "moduleName": "Sentry", + "init_kind": "Designated" + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A12ConnectivityO8RawValuea", + "mangledName": "$s6Sentry0A12ConnectivityO8RawValuea", + "moduleName": "Sentry" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A12ConnectivityO8rawValueSivp", + "mangledName": "$s6Sentry0A12ConnectivityO8rawValueSivp", + "moduleName": "Sentry", + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", "children": [ { "kind": "TypeNominal", - "name": "Array", - "printedName": "[Swift.AnyClass]", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A12ConnectivityO8rawValueSivg", + "mangledName": "$s6Sentry0A12ConnectivityO8rawValueSivg", + "moduleName": "Sentry", + "accessorKind": "get" + } + ] + } + ], + "declKind": "Enum", + "usr": "c:@M@Sentry@E@SentryConnectivity", + "mangledName": "$s6Sentry0A12ConnectivityO", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryConnectivity.RawValue", "children": [ { - "kind": "TypeNameAlias", - "name": "AnyClass", - "printedName": "Swift.AnyClass", - "children": [ - { - "kind": "TypeNominal", - "name": "ExistentialMetatype", - "printedName": "any Swift.AnyObject.Type", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Swift.AnyObject", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Builtin.AnyObject", - "children": [ - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "AnyObject" - } - ] - } - ] - } - ] - } - ] + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" } - ], - "usr": "s:Sa" + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryViewScreenshotOptions", + "printedName": "SentryViewScreenshotOptions", + "children": [ + { + "kind": "TypeDecl", + "name": "DefaultValues", + "printedName": "DefaultValues", + "children": [ + { + "kind": "Var", + "name": "enableViewRendererV2", + "printedName": "enableViewRendererV2", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Var", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvpZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvpZ", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvpZ", "moduleName": "Sentry", "static": true, "declAttributes": [ @@ -40784,49 +40833,14 @@ "children": [ { "kind": "TypeNominal", - "name": "Array", - "printedName": "[Swift.AnyClass]", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyClass", - "printedName": "Swift.AnyClass", - "children": [ - { - "kind": "TypeNominal", - "name": "ExistentialMetatype", - "printedName": "any Swift.AnyObject.Type", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Swift.AnyObject", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Builtin.AnyObject", - "children": [ - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "AnyObject" - } - ] - } - ] - } - ] - } - ] - } - ], - "usr": "s:Sa" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Accessor", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvgZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvgZ", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvgZ", "moduleName": "Sentry", "static": true, "implicit": true, @@ -40839,13 +40853,160 @@ }, { "kind": "Var", - "name": "unmaskedViewClasses", - "printedName": "unmaskedViewClasses", + "name": "enableFastViewRendering", + "printedName": "enableFastViewRendering", "children": [ { "kind": "TypeNominal", - "name": "Array", - "printedName": "[Swift.AnyClass]", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "maskAllText", + "printedName": "maskAllText", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "maskAllImages", + "printedName": "maskAllImages", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "maskedViewClasses", + "printedName": "maskedViewClasses", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", "children": [ { "kind": "TypeNameAlias", @@ -40885,8 +41046,8 @@ } ], "declKind": "Var", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvpZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvpZ", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvpZ", "moduleName": "Sentry", "static": true, "declAttributes": [ @@ -40944,8 +41105,8 @@ } ], "declKind": "Accessor", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvgZ", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvgZ", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvgZ", "moduleName": "Sentry", "static": true, "implicit": true, @@ -40955,69 +41116,188 @@ "accessorKind": "get" } ] - } - ], - "declKind": "Class", - "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC", - "moduleName": "Sentry", - "hasMissingDesignatedInitializers": true, - "conformances": [ - { - "kind": "Conformance", - "name": "Copyable", - "printedName": "Copyable", - "usr": "s:s8CopyableP", - "mangledName": "$ss8CopyableP" }, { - "kind": "Conformance", - "name": "Escapable", - "printedName": "Escapable", - "usr": "s:s9EscapableP", - "mangledName": "$ss9EscapableP" - } - ] - }, - { - "kind": "Var", - "name": "enableViewRendererV2", - "printedName": "enableViewRendererV2", - "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)enableViewRendererV2", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV2Sbvp", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC", - "HasStorage" - ], - "hasStorage": true, - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "Var", + "name": "unmaskedViewClasses", + "printedName": "unmaskedViewClasses", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" } ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)enableViewRendererV2", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV2Sbvg", + "declKind": "Var", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvpZ", "moduleName": "Sentry", - "implicit": true, + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + } + ], + "declKind": "Class", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC", + "moduleName": "Sentry", + "hasMissingDesignatedInitializers": true, + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + } + ] + }, + { + "kind": "Var", + "name": "enableViewRendererV2", + "printedName": "enableViewRendererV2", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)enableViewRendererV2", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV2Sbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)enableViewRendererV2", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV2Sbvg", + "moduleName": "Sentry", + "implicit": true, "declAttributes": [ "ObjC" ], @@ -41688,432 +41968,135 @@ { "kind": "TypeNominal", "name": "Bool", - "printedName": "Swift.Bool", - "hasDefaultArg": true, - "usr": "s:Sb" - }, - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "hasDefaultArg": true, - "usr": "s:Sb" - }, - { - "kind": "TypeNominal", - "name": "Array", - "printedName": "[Swift.AnyClass]", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyClass", - "printedName": "Swift.AnyClass", - "children": [ - { - "kind": "TypeNominal", - "name": "ExistentialMetatype", - "printedName": "any Swift.AnyObject.Type", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Swift.AnyObject", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Builtin.AnyObject", - "children": [ - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "AnyObject" - } - ] - } - ] - } - ] - } - ] - } - ], - "hasDefaultArg": true, - "usr": "s:Sa" - }, - { - "kind": "TypeNominal", - "name": "Array", - "printedName": "[Swift.AnyClass]", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyClass", - "printedName": "Swift.AnyClass", - "children": [ - { - "kind": "TypeNominal", - "name": "ExistentialMetatype", - "printedName": "any Swift.AnyObject.Type", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Swift.AnyObject", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Builtin.AnyObject", - "children": [ - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "AnyObject" - } - ] - } - ] - } - ] - } - ] - } - ], - "hasDefaultArg": true, - "usr": "s:Sa" - } - ], - "declKind": "Constructor", - "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)initWithEnableViewRendererV2:enableFastViewRendering:maskAllText:maskAllImages:maskedViewClasses:unmaskedViewClasses:", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV20e4FastB9Rendering11maskAllText0jK6Images06maskedB7Classes08unmaskedbO0ACSb_S3bSayyXlXpGAJtcfc", - "moduleName": "Sentry", - "objc_name": "initWithEnableViewRendererV2:enableFastViewRendering:maskAllText:maskAllImages:maskedViewClasses:unmaskedViewClasses:", - "declAttributes": [ - "ObjC" - ], - "init_kind": "Designated" - }, - { - "kind": "Var", - "name": "description", - "printedName": "description", - "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - } - ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)description", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC11descriptionSSvp", - "moduleName": "Sentry", - "overriding": true, - "objc_name": "description", - "declAttributes": [ - "ObjC", - "Dynamic", - "Override" - ], - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - } - ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)description", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC11descriptionSSvg", - "moduleName": "Sentry", - "overriding": true, - "objc_name": "description", - "declAttributes": [ - "Dynamic", - "ObjC", - "Override" - ], - "accessorKind": "get" - } - ] - } - ], - "declKind": "Class", - "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions", - "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC", - "moduleName": "Sentry", - "declAttributes": [ - "ObjCMembers", - "ObjC" - ], - "superclassUsr": "c:objc(cs)NSObject", - "inheritsConvenienceInitializers": true, - "superclassNames": [ - "ObjectiveC.NSObject" - ], - "conformances": [ - { - "kind": "Conformance", - "name": "SentryRedactOptions", - "printedName": "SentryRedactOptions", - "usr": "c:@M@Sentry@objc(pl)SentryRedactOptions", - "mangledName": "$s6Sentry0A13RedactOptionsP" - }, - { - "kind": "Conformance", - "name": "Copyable", - "printedName": "Copyable", - "usr": "s:s8CopyableP", - "mangledName": "$ss8CopyableP" - }, - { - "kind": "Conformance", - "name": "Escapable", - "printedName": "Escapable", - "usr": "s:s9EscapableP", - "mangledName": "$ss9EscapableP" - }, - { - "kind": "Conformance", - "name": "NSObjectProtocol", - "printedName": "NSObjectProtocol", - "usr": "c:objc(pl)NSObject" - }, - { - "kind": "Conformance", - "name": "Equatable", - "printedName": "Equatable", - "usr": "s:SQ", - "mangledName": "$sSQ" - }, - { - "kind": "Conformance", - "name": "Hashable", - "printedName": "Hashable", - "usr": "s:SH", - "mangledName": "$sSH" - }, - { - "kind": "Conformance", - "name": "CVarArg", - "printedName": "CVarArg", - "usr": "s:s7CVarArgP", - "mangledName": "$ss7CVarArgP" - }, - { - "kind": "Conformance", - "name": "CustomStringConvertible", - "printedName": "CustomStringConvertible", - "usr": "s:s23CustomStringConvertibleP", - "mangledName": "$ss23CustomStringConvertibleP" - }, - { - "kind": "Conformance", - "name": "CustomDebugStringConvertible", - "printedName": "CustomDebugStringConvertible", - "usr": "s:s28CustomDebugStringConvertibleP", - "mangledName": "$ss28CustomDebugStringConvertibleP" - } - ] - }, - { - "kind": "TypeDecl", - "name": "SentryConnectivity", - "printedName": "SentryConnectivity", - "children": [ - { - "kind": "Var", - "name": "cellular", - "printedName": "cellular", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentryConnectivity.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - } - ] - } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityCellular", - "mangledName": "$s6Sentry0A12ConnectivityO8cellularyA2CmF", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "wiFi", - "printedName": "wiFi", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentryConnectivity.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - } - ] - } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityWiFi", - "mangledName": "$s6Sentry0A12ConnectivityO4wiFiyA2CmF", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "none", - "printedName": "none", - "children": [ + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + }, { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", "children": [ { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentryConnectivity.Type", + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", "children": [ { "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] } ] } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityNone", - "mangledName": "$s6Sentry0A12ConnectivityO4noneyA2CmF", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Constructor", - "name": "init", - "printedName": "init(rawValue:)", - "children": [ + ], + "hasDefaultArg": true, + "usr": "s:Sa" + }, { "kind": "TypeNominal", - "name": "Optional", - "printedName": "Sentry.SentryConnectivity?", + "name": "Array", + "printedName": "[Swift.AnyClass]", "children": [ { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] } ], - "usr": "s:Sq" - }, - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" + "hasDefaultArg": true, + "usr": "s:Sa" } ], "declKind": "Constructor", - "usr": "s:6Sentry0A12ConnectivityO8rawValueACSgSi_tcfc", - "mangledName": "$s6Sentry0A12ConnectivityO8rawValueACSgSi_tcfc", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)initWithEnableViewRendererV2:enableFastViewRendering:maskAllText:maskAllImages:maskedViewClasses:unmaskedViewClasses:", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV20e4FastB9Rendering11maskAllText0jK6Images06maskedB7Classes08unmaskedbO0ACSb_S3bSayyXlXpGAJtcfc", "moduleName": "Sentry", - "init_kind": "Designated" - }, - { - "kind": "TypeAlias", - "name": "RawValue", - "printedName": "RawValue", - "children": [ - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" - } + "objc_name": "initWithEnableViewRendererV2:enableFastViewRendering:maskAllText:maskAllImages:maskedViewClasses:unmaskedViewClasses:", + "declAttributes": [ + "ObjC" ], - "declKind": "TypeAlias", - "usr": "s:6Sentry0A12ConnectivityO8RawValuea", - "mangledName": "$s6Sentry0A12ConnectivityO8RawValuea", - "moduleName": "Sentry" + "init_kind": "Designated" }, { "kind": "Var", - "name": "rawValue", - "printedName": "rawValue", + "name": "description", + "printedName": "description", "children": [ { "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "declKind": "Var", - "usr": "s:6Sentry0A12ConnectivityO8rawValueSivp", - "mangledName": "$s6Sentry0A12ConnectivityO8rawValueSivp", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)description", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC11descriptionSSvp", "moduleName": "Sentry", + "overriding": true, + "objc_name": "description", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], "accessors": [ { "kind": "Accessor", @@ -42122,29 +42105,48 @@ "children": [ { "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "declKind": "Accessor", - "usr": "s:6Sentry0A12ConnectivityO8rawValueSivg", - "mangledName": "$s6Sentry0A12ConnectivityO8rawValueSivg", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)description", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC11descriptionSSvg", "moduleName": "Sentry", + "overriding": true, + "objc_name": "description", + "declAttributes": [ + "Dynamic", + "ObjC", + "Override" + ], "accessorKind": "get" } ] } ], - "declKind": "Enum", - "usr": "c:@M@Sentry@E@SentryConnectivity", - "mangledName": "$s6Sentry0A12ConnectivityO", + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC", "moduleName": "Sentry", "declAttributes": [ + "ObjCMembers", "ObjC" ], - "enumRawTypeName": "Int", + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], "conformances": [ + { + "kind": "Conformance", + "name": "SentryRedactOptions", + "printedName": "SentryRedactOptions", + "usr": "c:@M@Sentry@objc(pl)SentryRedactOptions", + "mangledName": "$s6Sentry0A13RedactOptionsP" + }, { "kind": "Conformance", "name": "Copyable", @@ -42159,6 +42161,12 @@ "usr": "s:s9EscapableP", "mangledName": "$ss9EscapableP" }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, { "kind": "Conformance", "name": "Equatable", @@ -42175,32 +42183,24 @@ }, { "kind": "Conformance", - "name": "RawRepresentable", - "printedName": "RawRepresentable", - "children": [ - { - "kind": "TypeWitness", - "name": "RawValue", - "printedName": "RawValue", - "children": [ - { - "kind": "TypeNameAlias", - "name": "RawValue", - "printedName": "Sentry.SentryConnectivity.RawValue", - "children": [ - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" - } - ] - } - ] - } - ], - "usr": "s:SY", - "mangledName": "$sSY" + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" } ] }, From bc57b1751b16de7e7672fb985b13326a1a0d9aab Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Fri, 5 Sep 2025 11:17:46 -0300 Subject: [PATCH 12/22] Fix build on iOS 16 --- Sources/Swift/Networking/SentryReachability.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/Swift/Networking/SentryReachability.swift b/Sources/Swift/Networking/SentryReachability.swift index 11dd206fb05..a8f68ef0452 100644 --- a/Sources/Swift/Networking/SentryReachability.swift +++ b/Sources/Swift/Networking/SentryReachability.swift @@ -124,7 +124,7 @@ public class SentryReachability: NSObject { currentConnectivity = .none // Clean up NWPathMonitor - if #available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, *) { + if #available(iOS 12.0, macOS 10.14, tvOS 12.0, *) { if let monitor = pathMonitor as? NWPathMonitor { SentrySDKLog.debug("Stopping NWPathMonitor") monitor.cancel() @@ -136,7 +136,7 @@ public class SentryReachability: NSObject { reachabilityQueue = nil } - @available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, *) + @available(iOS 12.0, macOS 10.14, tvOS 12.0, *) private func pathUpdateHandler(_ path: NWPath) { SentrySDKLog.debug("SentryPathUpdateHandler called with path status: \(path.status)") @@ -151,7 +151,7 @@ public class SentryReachability: NSObject { connectivityCallback(connectivity) } - @available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, *) + @available(iOS 12.0, macOS 10.14, tvOS 12.0, *) private func connectivityFromPath(_ path: NWPath) -> SentryConnectivity { guard path.status == .satisfied else { return .none From 3d18bf3c00bc014caea8a385376076fbe3350db2 Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Fri, 5 Sep 2025 11:23:36 -0300 Subject: [PATCH 13/22] Add missing fix --- Sources/Swift/Networking/SentryReachability.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Swift/Networking/SentryReachability.swift b/Sources/Swift/Networking/SentryReachability.swift index a8f68ef0452..7822bfc3687 100644 --- a/Sources/Swift/Networking/SentryReachability.swift +++ b/Sources/Swift/Networking/SentryReachability.swift @@ -211,7 +211,7 @@ public class SentryReachability: NSObject { // MARK: - Test utils #if DEBUG || SENTRY_TEST || SENTRY_TEST_CI -@available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, *) +@available(iOS 12.0, macOS 10.14, tvOS 12.0, *) extension SentryReachability { @objc public func setReachabilityIgnoreActualCallback(_ value: Bool) { SentrySDKLog.debug("Setting ignore actual callback to \(value)") From ef2837b7ecce403858c71bf373cf789a1fb9587e Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Fri, 5 Sep 2025 11:30:14 -0300 Subject: [PATCH 14/22] Add missing fix --- Sources/Swift/Networking/SentryReachability.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Swift/Networking/SentryReachability.swift b/Sources/Swift/Networking/SentryReachability.swift index 7822bfc3687..d5bcc840e05 100644 --- a/Sources/Swift/Networking/SentryReachability.swift +++ b/Sources/Swift/Networking/SentryReachability.swift @@ -71,7 +71,7 @@ public class SentryReachability: NSObject { let reachabilityQueue = DispatchQueue(label: "io.sentry.cocoa.connectivity") self.reachabilityQueue = reachabilityQueue - if #available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, *) { + if #available(iOS 12.0, macOS 10.14, tvOS 12.0, *) { let monitor = NWPathMonitor() pathMonitor = monitor monitor.pathUpdateHandler = pathUpdateHandler From 1761d9202b617ee814d8ca4f2b97aecafce763b8 Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Wed, 10 Sep 2025 01:22:30 -0300 Subject: [PATCH 15/22] Fix SauceLabs tests --- Sources/Sentry/include/SentrySwift.h | 7 ------ .../Swift/Networking/SentryReachability.swift | 24 +++++++++---------- scripts/.swiftlint-version | 2 +- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/Sources/Sentry/include/SentrySwift.h b/Sources/Sentry/include/SentrySwift.h index 34b8bd5c1de..4c60786b3ab 100644 --- a/Sources/Sentry/include/SentrySwift.h +++ b/Sources/Sentry/include/SentrySwift.h @@ -22,13 +22,6 @@ # import "SentryDefines.h" # endif // __has_include() -// Needed or we can't expose reachability functions from Swift -# ifdef __cplusplus -# if SENTRY_HAS_REACHABILITY && __has_include() -# import -# endif -# endif - # if SENTRY_HAS_UIKIT // this is needed to fix a build issue when building iOS-ObjectiveC where the definitions of some // UIKIt enums used from SentryUserFeedbackWidgetConfiguration.swift aren't visible from the diff --git a/Sources/Swift/Networking/SentryReachability.swift b/Sources/Swift/Networking/SentryReachability.swift index d5bcc840e05..b22810f9f23 100644 --- a/Sources/Swift/Networking/SentryReachability.swift +++ b/Sources/Swift/Networking/SentryReachability.swift @@ -1,7 +1,7 @@ import Foundation +import Network #if !os(watchOS) && !((swift(>=5.9) && os(visionOS)) && SENTRY_NO_UIKIT) -import Network // MARK: - SentryConectivity @objc @@ -33,7 +33,7 @@ public class SentryReachability: NSObject { private var reachabilityObservers = NSHashTable.weakObjects() private var currentConnectivity: SentryConnectivity = .none private var pathMonitor: Any? // NWPathMonitor for iOS 12+ - private var reachabilityQueue: DispatchQueue? + private let reachabilityQueue: DispatchQueue = DispatchQueue(label: "io.sentry.cocoa.connectivity", qos: .background, attributes: []) private let observersLock = NSLock() #if DEBUG || SENTRY_TEST || SENTRY_TEST_CI @@ -68,16 +68,17 @@ public class SentryReachability: NSObject { } #endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI - let reachabilityQueue = DispatchQueue(label: "io.sentry.cocoa.connectivity") - self.reachabilityQueue = reachabilityQueue - if #available(iOS 12.0, macOS 10.14, tvOS 12.0, *) { - let monitor = NWPathMonitor() - pathMonitor = monitor - monitor.pathUpdateHandler = pathUpdateHandler - monitor.start(queue: reachabilityQueue) - - SentrySDKLog.debug("Started NWPathMonitor") + // If we don't use the main queue to start the monitor, the app seems to freeze on iOS 14.8 (SauceLabs) + // Also do it async to avoid blocking the main thread + // Right now `SentryDispatchQueueWrapper.dispatchAsyncOnMainQueue` is not used because the SDK starts on the main thread, + // thus the block is executed in the main thread, not async. + DispatchQueue.main.async { [weak self] in + let monitor = NWPathMonitor() + self?.pathMonitor = monitor + monitor.pathUpdateHandler = self?.pathUpdateHandler + monitor.start(queue: self?.reachabilityQueue ?? DispatchQueue.global(qos: .background)) + } } else { // For iOS 11 and earlier, simulate always being connected via WiFi SentrySDKLog.warning("NWPathMonitor not available. Using fallback: always connected via WiFi") @@ -133,7 +134,6 @@ public class SentryReachability: NSObject { } SentrySDKLog.debug("Cleaning up reachability queue.") - reachabilityQueue = nil } @available(iOS 12.0, macOS 10.14, tvOS 12.0, *) diff --git a/scripts/.swiftlint-version b/scripts/.swiftlint-version index 7e750b4ebf3..0b09455034e 100644 --- a/scripts/.swiftlint-version +++ b/scripts/.swiftlint-version @@ -1 +1 @@ -0.60.0 +0.61.0 From 5de0617ccc8b1fc55f979627ecb8a8eb6489516b Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Wed, 10 Sep 2025 17:15:17 -0300 Subject: [PATCH 16/22] Remove `SENTRY_HAS_REACHABILITY` macro and enable SentryReachability to all platforms --- Sources/Sentry/Public/SentryDefines.h | 6 ---- Sources/Sentry/SentryBreadcrumbTracker.m | 14 +-------- Sources/Sentry/SentryDependencyContainer.m | 4 --- Sources/Sentry/SentryHttpTransport.m | 9 +----- .../HybridPublic/SentryDependencyContainer.h | 8 +---- .../Swift/Networking/SentryReachability.swift | 29 ++++++++++++------- 6 files changed, 21 insertions(+), 49 deletions(-) diff --git a/Sources/Sentry/Public/SentryDefines.h b/Sources/Sentry/Public/SentryDefines.h index b037e44c6f7..8b8944753b1 100644 --- a/Sources/Sentry/Public/SentryDefines.h +++ b/Sources/Sentry/Public/SentryDefines.h @@ -65,12 +65,6 @@ -(instancetype)init NS_UNAVAILABLE; \ +(instancetype) new NS_UNAVAILABLE; -#if !TARGET_OS_WATCH && !(TARGET_OS_VISION && SENTRY_NO_UIKIT == 1) -# define SENTRY_HAS_REACHABILITY 1 -#else -# define SENTRY_HAS_REACHABILITY 0 -#endif - @class SentryBreadcrumb; @class SentryEvent; @class SentrySamplingContext; diff --git a/Sources/Sentry/SentryBreadcrumbTracker.m b/Sources/Sentry/SentryBreadcrumbTracker.m index 5264a160242..d59d48760da 100644 --- a/Sources/Sentry/SentryBreadcrumbTracker.m +++ b/Sources/Sentry/SentryBreadcrumbTracker.m @@ -25,10 +25,7 @@ static NSString *const SentryBreadcrumbTrackerSwizzleSendAction = @"SentryBreadcrumbTrackerSwizzleSendAction"; -@interface SentryBreadcrumbTracker () -#if SENTRY_HAS_REACHABILITY - -#endif // !TARGET_OS_WATCH +@interface SentryBreadcrumbTracker () @property (nonatomic, weak) id delegate; @@ -38,12 +35,10 @@ @implementation SentryBreadcrumbTracker { BOOL _reportAccessibilityIdentifier; } -#if SENTRY_HAS_REACHABILITY - (void)dealloc { [SentryDependencyContainer.sharedInstance.reachability removeObserver:self]; } -#endif // !TARGET_OS_WATCH - (instancetype)initReportAccessibilityIdentifier:(BOOL)report { @@ -58,9 +53,7 @@ - (void)startWithDelegate:(id)delegate _delegate = delegate; [self addEnabledCrumb]; [self trackApplicationNotifications]; -#if SENTRY_HAS_REACHABILITY [self trackNetworkConnectivityChanges]; -#endif // !TARGET_OS_WATCH } #if SENTRY_HAS_UIKIT @@ -80,9 +73,7 @@ - (void)stop removeSwizzleSendActionForKey:SentryBreadcrumbTrackerSwizzleSendAction]; #endif // SENTRY_HAS_UIKIT _delegate = nil; -#if SENTRY_HAS_REACHABILITY [self stopTrackNetworkConnectivityChanges]; -#endif // SENTRY_HAS_REACHABILITY } - (void)trackApplicationNotifications @@ -142,7 +133,6 @@ - (void)trackApplicationNotifications #endif // SENTRY_HAS_UIKIT || SENTRY_TARGET_MACOS_HAS_UI } -#if SENTRY_HAS_REACHABILITY - (void)trackNetworkConnectivityChanges { [SentryDependencyContainer.sharedInstance.reachability addObserver:self]; @@ -162,8 +152,6 @@ - (void)connectivityChanged:(BOOL)connected typeDescription:(nonnull NSString *) [self.delegate addBreadcrumb:crumb]; } -#endif // SENTRY_HAS_REACHABILITY - - (void)addBreadcrumbWithType:(NSString *)type withCategory:(NSString *)category withLevel:(SentryLevel)level diff --git a/Sources/Sentry/SentryDependencyContainer.m b/Sources/Sentry/SentryDependencyContainer.m index 8d47c9cecdd..9bd81472939 100644 --- a/Sources/Sentry/SentryDependencyContainer.m +++ b/Sources/Sentry/SentryDependencyContainer.m @@ -112,9 +112,7 @@ + (instancetype)sharedInstance + (void)reset { @synchronized(sentryDependencyContainerInstanceLock) { -#if SENTRY_HAS_REACHABILITY [instance->_reachability removeAllObservers]; -#endif // SENTRY_HAS_REACHABILITY #if SENTRY_HAS_UIKIT [instance->_framesTracker stop]; @@ -182,9 +180,7 @@ - (instancetype)init andRateLimitParser:rateLimitParser currentDateProvider:_dateProvider]; -#if SENTRY_HAS_REACHABILITY _reachability = [[SentryReachability alloc] init]; -#endif // SENTRY_HAS_REACHABILITY isInitialializingDependencyContainer = NO; } diff --git a/Sources/Sentry/SentryHttpTransport.m b/Sources/Sentry/SentryHttpTransport.m index adc3f32a9c0..29b077d085a 100644 --- a/Sources/Sentry/SentryHttpTransport.m +++ b/Sources/Sentry/SentryHttpTransport.m @@ -16,10 +16,7 @@ #import "SentrySerialization.h" #import "SentrySwift.h" -@interface SentryHttpTransport () -#if SENTRY_HAS_REACHABILITY - -#endif // SENTRY_HAS_REACHABILITY +@interface SentryHttpTransport () @property (nonatomic, readonly) NSTimeInterval cachedEnvelopeSendDelay; @property (nonatomic, strong) SentryFileManager *fileManager; @@ -92,14 +89,11 @@ - (id)initWithDsn:(SentryDsn *)dsn [self sendAllCachedEnvelopes]; -#if SENTRY_HAS_REACHABILITY [SentryDependencyContainer.sharedInstance.reachability addObserver:self]; -#endif // SENTRY_HAS_REACHABILITY } return self; } -#if SENTRY_HAS_REACHABILITY - (void)connectivityChanged:(BOOL)connected typeDescription:(nonnull NSString *)typeDescription { if (connected) { @@ -114,7 +108,6 @@ - (void)dealloc { [SentryDependencyContainer.sharedInstance.reachability removeObserver:self]; } -#endif // SENTRY_HAS_REACHABILITY - (void)sendEnvelope:(SentryEnvelope *)envelope { diff --git a/Sources/Sentry/include/HybridPublic/SentryDependencyContainer.h b/Sources/Sentry/include/HybridPublic/SentryDependencyContainer.h index 59500c116bf..935244e68c8 100644 --- a/Sources/Sentry/include/HybridPublic/SentryDependencyContainer.h +++ b/Sources/Sentry/include/HybridPublic/SentryDependencyContainer.h @@ -25,6 +25,7 @@ @class SentryOptions; @class SentrySessionTracker; @class SentryGlobalEventProcessor; +@class SentryReachability; @protocol SentryANRTracker; @protocol SentryRandomProtocol; @@ -54,10 +55,6 @@ @protocol SentryUIDeviceWrapper; #endif // TARGET_OS_IOS -#if !TARGET_OS_WATCH -@class SentryReachability; -#endif // !TARGET_OS_WATCH - NS_ASSUME_NONNULL_BEGIN /** @@ -95,10 +92,7 @@ SENTRY_NO_INIT @property (nonatomic, strong) id rateLimits; @property (nonatomic, strong) id application; @property (nonatomic, strong) SentryThreadsafeApplication *threadsafeApplication; - -#if SENTRY_HAS_REACHABILITY @property (nonatomic, strong) SentryReachability *reachability; -#endif // !TARGET_OS_WATCH #if SENTRY_HAS_UIKIT @property (nonatomic, strong) id uiDeviceWrapper; diff --git a/Sources/Swift/Networking/SentryReachability.swift b/Sources/Swift/Networking/SentryReachability.swift index b22810f9f23..00cc51230e2 100644 --- a/Sources/Swift/Networking/SentryReachability.swift +++ b/Sources/Swift/Networking/SentryReachability.swift @@ -1,15 +1,24 @@ import Foundation import Network -#if !os(watchOS) && !((swift(>=5.9) && os(visionOS)) && SENTRY_NO_UIKIT) - // MARK: - SentryConectivity -@objc +#if DEBUG || SENTRY_TEST || SENTRY_TEST_CI +@objc @_spi(Private) public enum SentryConnectivity: Int { case cellular case wiFi case none - +} +#else +@objc +enum SentryConnectivity: Int { + case cellular + case wiFi + case none +} +#endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI + +extension SentryConnectivity { func toString() -> String { switch self { case .cellular: @@ -68,7 +77,7 @@ public class SentryReachability: NSObject { } #endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI - if #available(iOS 12.0, macOS 10.14, tvOS 12.0, *) { + if #available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, watchOS 5.0, *) { // If we don't use the main queue to start the monitor, the app seems to freeze on iOS 14.8 (SauceLabs) // Also do it async to avoid blocking the main thread // Right now `SentryDispatchQueueWrapper.dispatchAsyncOnMainQueue` is not used because the SDK starts on the main thread, @@ -125,7 +134,7 @@ public class SentryReachability: NSObject { currentConnectivity = .none // Clean up NWPathMonitor - if #available(iOS 12.0, macOS 10.14, tvOS 12.0, *) { + if #available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, watchOS 5.0, *) { if let monitor = pathMonitor as? NWPathMonitor { SentrySDKLog.debug("Stopping NWPathMonitor") monitor.cancel() @@ -136,7 +145,7 @@ public class SentryReachability: NSObject { SentrySDKLog.debug("Cleaning up reachability queue.") } - @available(iOS 12.0, macOS 10.14, tvOS 12.0, *) + @available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, watchOS 5.0, *) private func pathUpdateHandler(_ path: NWPath) { SentrySDKLog.debug("SentryPathUpdateHandler called with path status: \(path.status)") @@ -151,7 +160,7 @@ public class SentryReachability: NSObject { connectivityCallback(connectivity) } - @available(iOS 12.0, macOS 10.14, tvOS 12.0, *) + @available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, watchOS 5.0, *) private func connectivityFromPath(_ path: NWPath) -> SentryConnectivity { guard path.status == .satisfied else { return .none @@ -211,7 +220,7 @@ public class SentryReachability: NSObject { // MARK: - Test utils #if DEBUG || SENTRY_TEST || SENTRY_TEST_CI -@available(iOS 12.0, macOS 10.14, tvOS 12.0, *) +@available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, watchOS 5.0, *) extension SentryReachability { @objc public func setReachabilityIgnoreActualCallback(_ value: Bool) { SentrySDKLog.debug("Setting ignore actual callback to \(value)") @@ -229,5 +238,3 @@ extension SentryReachability { } } #endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI - -#endif // !os(watchOS) && !((swift(>=5.9) && os(visionOS)) && SENTRY_NO_UIKIT) From c535c236662b66612d7d9e43abdc1fe2dd2d544a Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Thu, 11 Sep 2025 15:06:41 -0300 Subject: [PATCH 17/22] Remove async queue requirement --- Sentry.xcodeproj/project.pbxproj | 4 - .../Swift/Networking/SentryReachability.swift | 59 +--- .../SentryReachabilitySwiftTests.swift | 124 ++++++- .../Networking/SentryReachabilityTests.m | 157 --------- sdk_api.json | 322 ------------------ sdk_api_V9.json | 322 ------------------ 6 files changed, 129 insertions(+), 859 deletions(-) delete mode 100644 Tests/SentryTests/Networking/SentryReachabilityTests.m diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index f2fdb92c89d..a332fee8b7d 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -49,7 +49,6 @@ 0A9BF4EB28A127120068D266 /* SentryViewHierarchyIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9BF4EA28A127120068D266 /* SentryViewHierarchyIntegrationTests.swift */; }; 0A9E917128DC7E7000FB4182 /* SentryInternalCDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A9E917028DC7E7000FB4182 /* SentryInternalCDefines.h */; }; 0ADC33F128D9BE940078D980 /* TestSentryUIDeviceWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ADC33EF28D9BE690078D980 /* TestSentryUIDeviceWrapper.swift */; }; - 0AE455AD28F584D2006680E5 /* SentryReachabilityTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AE455AC28F584D2006680E5 /* SentryReachabilityTests.m */; }; 15360CCF2432777500112302 /* SentrySessionTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 15360CCE2432777400112302 /* SentrySessionTracker.m */; }; 15360CD2243277A000112302 /* SentrySessionTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 15360CD12432779F00112302 /* SentrySessionTracker.h */; }; 15360CD62432832400112302 /* SentryAutoSessionTrackingIntegration.m in Sources */ = {isa = PBXBuildFile; fileRef = 15360CD52432832400112302 /* SentryAutoSessionTrackingIntegration.m */; }; @@ -1286,7 +1285,6 @@ 0A9BF4EA28A127120068D266 /* SentryViewHierarchyIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryViewHierarchyIntegrationTests.swift; sourceTree = ""; }; 0A9E917028DC7E7000FB4182 /* SentryInternalCDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryInternalCDefines.h; path = include/SentryInternalCDefines.h; sourceTree = ""; }; 0ADC33EF28D9BE690078D980 /* TestSentryUIDeviceWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSentryUIDeviceWrapper.swift; sourceTree = ""; }; - 0AE455AC28F584D2006680E5 /* SentryReachabilityTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryReachabilityTests.m; sourceTree = ""; }; 15360CCE2432777400112302 /* SentrySessionTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentrySessionTracker.m; sourceTree = ""; }; 15360CD12432779F00112302 /* SentrySessionTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentrySessionTracker.h; path = include/SentrySessionTracker.h; sourceTree = ""; }; 15360CD52432832400112302 /* SentryAutoSessionTrackingIntegration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryAutoSessionTrackingIntegration.m; sourceTree = ""; }; @@ -3547,7 +3545,6 @@ 7B01CE3C271993AB00B5AF31 /* SentryTransportFactoryTests.swift */, 7B5CAF7C27F5AD0600ED0DB6 /* TestNSURLRequestBuilder.h */, 7B5CAF7D27F5AD3500ED0DB6 /* TestNSURLRequestBuilder.m */, - 0AE455AC28F584D2006680E5 /* SentryReachabilityTests.m */, 629690522AD3E060000185FA /* SentryReachabilitySwiftTests.swift */, 0A9415B928F96CAC006A5DD1 /* TestSentryReachability.swift */, D4FC68192DD63465001B74FF /* SentryDispatchQueueWrapperTests.m */, @@ -6235,7 +6232,6 @@ D808FB92281BF6EC009A2A33 /* SentryUIEventTrackingIntegrationTests.swift in Sources */, 7BC6EC04255C235F0059822A /* SentryFrameTests.swift in Sources */, D82DD1CD2BEEB1A0001AB556 /* SentrySRDefaultBreadcrumbConverterTests.swift in Sources */, - 0AE455AD28F584D2006680E5 /* SentryReachabilityTests.m in Sources */, 63FE720420DA66EC00CDBAE8 /* SentryCrashString_Tests.m in Sources */, 62872B632BA1B86100A4FA7D /* LocksTests.swift in Sources */, 849AC40029E0C1FF00889C16 /* SentryFormatterTests.swift in Sources */, diff --git a/Sources/Swift/Networking/SentryReachability.swift b/Sources/Swift/Networking/SentryReachability.swift index 00cc51230e2..4ac7d58f1c1 100644 --- a/Sources/Swift/Networking/SentryReachability.swift +++ b/Sources/Swift/Networking/SentryReachability.swift @@ -2,23 +2,11 @@ import Foundation import Network // MARK: - SentryConectivity -#if DEBUG || SENTRY_TEST || SENTRY_TEST_CI -@objc @_spi(Private) -public enum SentryConnectivity: Int { - case cellular - case wiFi - case none -} -#else -@objc enum SentryConnectivity: Int { case cellular case wiFi case none -} -#endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI -extension SentryConnectivity { func toString() -> String { switch self { case .cellular: @@ -41,9 +29,9 @@ public protocol SentryReachabilityObserver: NSObjectProtocol { public class SentryReachability: NSObject { private var reachabilityObservers = NSHashTable.weakObjects() private var currentConnectivity: SentryConnectivity = .none - private var pathMonitor: Any? // NWPathMonitor for iOS 12+ + private var pathMonitor: NWPathMonitor? private let reachabilityQueue: DispatchQueue = DispatchQueue(label: "io.sentry.cocoa.connectivity", qos: .background, attributes: []) - private let observersLock = NSLock() + private let observersLock = NSRecursiveLock() #if DEBUG || SENTRY_TEST || SENTRY_TEST_CI @objc public var skipRegisteringActualCallbacks = false @@ -77,24 +65,10 @@ public class SentryReachability: NSObject { } #endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI - if #available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, watchOS 5.0, *) { - // If we don't use the main queue to start the monitor, the app seems to freeze on iOS 14.8 (SauceLabs) - // Also do it async to avoid blocking the main thread - // Right now `SentryDispatchQueueWrapper.dispatchAsyncOnMainQueue` is not used because the SDK starts on the main thread, - // thus the block is executed in the main thread, not async. - DispatchQueue.main.async { [weak self] in - let monitor = NWPathMonitor() - self?.pathMonitor = monitor - monitor.pathUpdateHandler = self?.pathUpdateHandler - monitor.start(queue: self?.reachabilityQueue ?? DispatchQueue.global(qos: .background)) - } - } else { - // For iOS 11 and earlier, simulate always being connected via WiFi - SentrySDKLog.warning("NWPathMonitor not available. Using fallback: always connected via WiFi") - reachabilityQueue.async { [weak self] in - self?.connectivityCallback(.wiFi) - } - } + let monitor = NWPathMonitor() + self.pathMonitor = monitor + monitor.pathUpdateHandler = self.pathUpdateHandler + monitor.start(queue: self.reachabilityQueue) } @objc(removeObserver:) @@ -134,18 +108,15 @@ public class SentryReachability: NSObject { currentConnectivity = .none // Clean up NWPathMonitor - if #available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, watchOS 5.0, *) { - if let monitor = pathMonitor as? NWPathMonitor { - SentrySDKLog.debug("Stopping NWPathMonitor") - monitor.cancel() - pathMonitor = nil - } + if let monitor = pathMonitor { + SentrySDKLog.debug("Stopping NWPathMonitor") + monitor.cancel() + pathMonitor = nil } SentrySDKLog.debug("Cleaning up reachability queue.") } - @available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, watchOS 5.0, *) private func pathUpdateHandler(_ path: NWPath) { SentrySDKLog.debug("SentryPathUpdateHandler called with path status: \(path.status)") @@ -160,7 +131,6 @@ public class SentryReachability: NSObject { connectivityCallback(connectivity) } - @available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, watchOS 5.0, *) private func connectivityFromPath(_ path: NWPath) -> SentryConnectivity { guard path.status == .satisfied else { return .none @@ -220,20 +190,19 @@ public class SentryReachability: NSObject { // MARK: - Test utils #if DEBUG || SENTRY_TEST || SENTRY_TEST_CI -@available(iOS 12.0, macOS 10.14, tvOS 12.0, visionOS 1.0, watchOS 5.0, *) extension SentryReachability { - @objc public func setReachabilityIgnoreActualCallback(_ value: Bool) { + func setReachabilityIgnoreActualCallback(_ value: Bool) { SentrySDKLog.debug("Setting ignore actual callback to \(value)") ignoreActualCallback = value } - @objc public func triggerConnectivityCallback(_ connectivity: SentryConnectivity) { + func triggerConnectivityCallback(_ connectivity: SentryConnectivity) { connectivityCallback(connectivity) } } -@_spi(Private) @objc public class SentryReachabilityTestHelper: NSObject { - @objc static public func stringForSentryConnectivity(_ type: SentryConnectivity) -> String { +class SentryReachabilityTestHelper: NSObject { + static func stringForSentryConnectivity(_ type: SentryConnectivity) -> String { type.toString() } } diff --git a/Tests/SentryTests/Networking/SentryReachabilitySwiftTests.swift b/Tests/SentryTests/Networking/SentryReachabilitySwiftTests.swift index 7d1f06cedf2..fad5f8d5970 100644 --- a/Tests/SentryTests/Networking/SentryReachabilitySwiftTests.swift +++ b/Tests/SentryTests/Networking/SentryReachabilitySwiftTests.swift @@ -1,8 +1,120 @@ @_spi(Private) @testable import Sentry import XCTest -final class SentryReachabilitySwiftTests: XCTestCase { +class TestSentryReachabilityObserver: NSObject, SentryReachabilityObserver { + var connectivityChangedInvocations: UInt = 0 + + override init() { + super.init() + connectivityChangedInvocations = 0 + } + + func connectivityChanged(_ connected: Bool, typeDescription: String) { + print("Received connectivity notification: \(connected); type: \(typeDescription)") + connectivityChangedInvocations += 1 + } +} +final class SentryReachabilitySwiftTests: XCTestCase { + + private var reachability: SentryReachability! + + override func setUp() { + super.setUp() + // Ignore the actual reachability callbacks, cause we call the callbacks manually. + // Otherwise, the actual reachability callbacks are called during later unrelated tests causing + // flakes. + reachability = SentryReachability() + reachability.skipRegisteringActualCallbacks = true + reachability.setReachabilityIgnoreActualCallback(true) + } + + override func tearDown() { + reachability.removeAllObservers() + reachability.setReachabilityIgnoreActualCallback(false) + reachability = nil + super.tearDown() + } + + func testConnectivityRepresentations() { + XCTAssertEqual("none", SentryReachabilityTestHelper.stringForSentryConnectivity(.none)) + XCTAssertEqual("wifi", SentryReachabilityTestHelper.stringForSentryConnectivity(.wiFi)) + #if canImport(UIKit) + XCTAssertEqual("cellular", SentryReachabilityTestHelper.stringForSentryConnectivity(.cellular)) + #endif + } + + func testMultipleReachabilityObservers() { + print("[Sentry] [TEST] creating observer A") + let observerA = TestSentryReachabilityObserver() + print("[Sentry] [TEST] adding observer A as reachability observer") + reachability.add(observerA) + + print("[Sentry] [TEST] throwaway reachability callback, setting to reachable") + reachability.triggerConnectivityCallback(.wiFi) // ignored, as it's the first callback + print("[Sentry] [TEST] reachability callback set to unreachable") + reachability.triggerConnectivityCallback(.none) + + print("[Sentry] [TEST] creating observer B") + let observerB = TestSentryReachabilityObserver() + print("[Sentry] [TEST] adding observer B as reachability observer") + reachability.add(observerB) + + print("[Sentry] [TEST] reachability callback set back to reachable") + reachability.triggerConnectivityCallback(.wiFi) + print("[Sentry] [TEST] reachability callback set back to unreachable") + reachability.triggerConnectivityCallback(.none) + + print("[Sentry] [TEST] removing observer B as reachability observer") + reachability.remove(observerB) + + print("[Sentry] [TEST] reachability callback set back to reachable") + reachability.triggerConnectivityCallback(.wiFi) + + XCTAssertEqual(5, observerA.connectivityChangedInvocations) + XCTAssertEqual(2, observerB.connectivityChangedInvocations) + + print("[Sentry] [TEST] removing observer A as reachability observer") + reachability.remove(observerA) + } + + func testNoObservers() { + let observer = TestSentryReachabilityObserver() + reachability.add(observer) + reachability.remove(observer) + + reachability.triggerConnectivityCallback(.wiFi) + + XCTAssertEqual(0, observer.connectivityChangedInvocations) + + reachability.removeAllObservers() + } + + func testReportSameObserver_OnlyCalledOnce() { + let observer = TestSentryReachabilityObserver() + reachability.add(observer) + reachability.add(observer) + + reachability.triggerConnectivityCallback(.wiFi) + + XCTAssertEqual(1, observer.connectivityChangedInvocations) + + reachability.remove(observer) + } + + /** + * We only want to make sure running the actual registering and unregistering callbacks doesn't + * crash. + */ + func testRegisteringActualCallbacks() { + reachability.skipRegisteringActualCallbacks = false + + let observer = TestSentryReachabilityObserver() + + reachability.add(observer) + reachability.remove(observer) + } + func testAddRemoveFromMultipleThreads() throws { let sut = SentryReachability() // Calling the methods of SCNetworkReachability in a tight loop from @@ -11,16 +123,10 @@ final class SentryReachabilitySwiftTests: XCTestCase { // observers are adequately synchronized and not if we call // SCNetworkReachability correctly. sut.skipRegisteringActualCallbacks = true - testConcurrentModifications(writeWork: {_ in - sut.add(TestReachabilityObserver()) + testConcurrentModifications(writeWork: { _ in + sut.add(TestSentryReachabilityObserver()) }, readWork: { sut.removeAllObservers() }) } } - -class TestReachabilityObserver: NSObject, SentryReachabilityObserver { - func connectivityChanged(_ connected: Bool, typeDescription: String) { - // Do nothing - } -} diff --git a/Tests/SentryTests/Networking/SentryReachabilityTests.m b/Tests/SentryTests/Networking/SentryReachabilityTests.m deleted file mode 100644 index e50d68024df..00000000000 --- a/Tests/SentryTests/Networking/SentryReachabilityTests.m +++ /dev/null @@ -1,157 +0,0 @@ -#import "SentryLogC.h" -#import "SentrySwift.h" -#import - -@interface TestSentryReachabilityObserver : NSObject - -@property (assign, nonatomic) NSUInteger connectivityChangedInvocations; - -@end -@implementation TestSentryReachabilityObserver - -- (instancetype)init -{ - if (self = [super init]) { - self.connectivityChangedInvocations = 0; - } - return self; -} - -- (void)connectivityChanged:(BOOL)connected typeDescription:(nonnull NSString *)typeDescription -{ - NSLog( - @"Received connectivity notification: %i; type: %s", connected, typeDescription.UTF8String); - self.connectivityChangedInvocations++; -} - -@end - -#if !TARGET_OS_WATCH -@interface SentryReachabilityTest : XCTestCase -@property (strong, nonatomic) SentryReachability *reachability; -@end - -@implementation SentryReachabilityTest - -- (void)setUp -{ - // Ignore the actual reachability callbacks, cause we call the callbacks manually. - // Otherwise, the actual reachability callbacks are called during later unrelated tests causing - // flakes. - [self.reachability setReachabilityIgnoreActualCallback:YES]; - - self.reachability = [[SentryReachability alloc] init]; - self.reachability.skipRegisteringActualCallbacks = YES; -} - -- (void)tearDown -{ - [self.reachability removeAllObservers]; - [self.reachability setReachabilityIgnoreActualCallback:NO]; - self.reachability = nil; -} - -- (void)testConnectivityRepresentations -{ - XCTAssertEqualObjects( - @"none", [SentryReachabilityTestHelper stringForSentryConnectivity:SentryConnectivityNone]); - XCTAssertEqualObjects( - @"wifi", [SentryReachabilityTestHelper stringForSentryConnectivity:SentryConnectivityWiFi]); -# if SENTRY_HAS_UIKIT - XCTAssertEqualObjects(@"cellular", - [SentryReachabilityTestHelper stringForSentryConnectivity:SentryConnectivityCellular]); -# endif // SENTRY_HAS_UIKIT -} - -- (void)testMultipleReachabilityObservers -{ - NSLog(@"[Sentry] [TEST] creating observer A"); - TestSentryReachabilityObserver *observerA = [[TestSentryReachabilityObserver alloc] init]; - NSLog(@"[Sentry] [TEST] adding observer A as reachability observer"); - [self.reachability addObserver:observerA]; - - NSLog(@"[Sentry] [TEST] throwaway reachability callback, setting to reachable"); - [self.reachability - triggerConnectivityCallback:SentryConnectivityWiFi]; // ignored, as it's the first callback - NSLog(@"[Sentry] [TEST] reachability callback set to unreachable"); - [self.reachability triggerConnectivityCallback:SentryConnectivityNone]; - - NSLog(@"[Sentry] [TEST] creating observer B"); - TestSentryReachabilityObserver *observerB = [[TestSentryReachabilityObserver alloc] init]; - NSLog(@"[Sentry] [TEST] adding observer B as reachability observer"); - [self.reachability addObserver:observerB]; - - NSLog(@"[Sentry] [TEST] reachability callback set back to reachable"); - [self.reachability triggerConnectivityCallback:SentryConnectivityWiFi]; - NSLog(@"[Sentry] [TEST] reachability callback set back to unreachable"); - [self.reachability triggerConnectivityCallback:SentryConnectivityNone]; - - NSLog(@"[Sentry] [TEST] removing observer B as reachability observer"); - [self.reachability removeObserver:observerB]; - - NSLog(@"[Sentry] [TEST] reachability callback set back to reachable"); - [self.reachability triggerConnectivityCallback:SentryConnectivityWiFi]; - - XCTAssertEqual(5, observerA.connectivityChangedInvocations); - XCTAssertEqual(2, observerB.connectivityChangedInvocations); - - NSLog(@"[Sentry] [TEST] removing observer A as reachability observer"); - [self.reachability removeObserver:observerA]; -} - -- (void)testNoObservers -{ - TestSentryReachabilityObserver *observer = [[TestSentryReachabilityObserver alloc] init]; - [self.reachability addObserver:observer]; - [self.reachability removeObserver:observer]; - - [self.reachability triggerConnectivityCallback:SentryConnectivityWiFi]; - - XCTAssertEqual(0, observer.connectivityChangedInvocations); - - [self.reachability removeAllObservers]; -} - -- (void)testReportSameObserver_OnlyCalledOnce -{ - TestSentryReachabilityObserver *observer = [[TestSentryReachabilityObserver alloc] init]; - [self.reachability addObserver:observer]; - [self.reachability addObserver:observer]; - - [self.reachability triggerConnectivityCallback:SentryConnectivityWiFi]; - - XCTAssertEqual(1, observer.connectivityChangedInvocations); - - [self.reachability removeObserver:observer]; -} - -- (void)testReportSameReachabilityState_OnlyCalledOnce -{ - TestSentryReachabilityObserver *observer = [[TestSentryReachabilityObserver alloc] init]; - [self.reachability addObserver:observer]; - - [self.reachability triggerConnectivityCallback:SentryConnectivityWiFi]; - [self.reachability triggerConnectivityCallback:SentryConnectivityWiFi]; - [self.reachability triggerConnectivityCallback:SentryConnectivityWiFi]; - - XCTAssertEqual(1, observer.connectivityChangedInvocations); - - [self.reachability removeObserver:observer]; -} - -/** - * We only want to make sure running the actual registering and unregistering callbacks doesn't - * crash. - */ -- (void)testRegisteringActualCallbacks -{ - self.reachability.skipRegisteringActualCallbacks = NO; - - TestSentryReachabilityObserver *observer = [[TestSentryReachabilityObserver alloc] init]; - - [self.reachability addObserver:observer]; - [self.reachability removeObserver:observer]; -} - -@end -#endif // !TARGET_OS_WATCH diff --git a/sdk_api.json b/sdk_api.json index f8d718e340a..fa8cef83097 100644 --- a/sdk_api.json +++ b/sdk_api.json @@ -43343,286 +43343,6 @@ "declKind": "Import", "moduleName": "Sentry" }, - { - "kind": "TypeDecl", - "name": "SentryConnectivity", - "printedName": "SentryConnectivity", - "children": [ - { - "kind": "Var", - "name": "cellular", - "printedName": "cellular", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentryConnectivity.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - } - ] - } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityCellular", - "mangledName": "$s6Sentry0A12ConnectivityO8cellularyA2CmF", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "wiFi", - "printedName": "wiFi", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentryConnectivity.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - } - ] - } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityWiFi", - "mangledName": "$s6Sentry0A12ConnectivityO4wiFiyA2CmF", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "none", - "printedName": "none", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentryConnectivity.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - } - ] - } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityNone", - "mangledName": "$s6Sentry0A12ConnectivityO4noneyA2CmF", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Constructor", - "name": "init", - "printedName": "init(rawValue:)", - "children": [ - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "Sentry.SentryConnectivity?", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - } - ], - "usr": "s:Sq" - }, - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" - } - ], - "declKind": "Constructor", - "usr": "s:6Sentry0A12ConnectivityO8rawValueACSgSi_tcfc", - "mangledName": "$s6Sentry0A12ConnectivityO8rawValueACSgSi_tcfc", - "moduleName": "Sentry", - "init_kind": "Designated" - }, - { - "kind": "TypeAlias", - "name": "RawValue", - "printedName": "RawValue", - "children": [ - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" - } - ], - "declKind": "TypeAlias", - "usr": "s:6Sentry0A12ConnectivityO8RawValuea", - "mangledName": "$s6Sentry0A12ConnectivityO8RawValuea", - "moduleName": "Sentry" - }, - { - "kind": "Var", - "name": "rawValue", - "printedName": "rawValue", - "children": [ - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" - } - ], - "declKind": "Var", - "usr": "s:6Sentry0A12ConnectivityO8rawValueSivp", - "mangledName": "$s6Sentry0A12ConnectivityO8rawValueSivp", - "moduleName": "Sentry", - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" - } - ], - "declKind": "Accessor", - "usr": "s:6Sentry0A12ConnectivityO8rawValueSivg", - "mangledName": "$s6Sentry0A12ConnectivityO8rawValueSivg", - "moduleName": "Sentry", - "accessorKind": "get" - } - ] - } - ], - "declKind": "Enum", - "usr": "c:@M@Sentry@E@SentryConnectivity", - "mangledName": "$s6Sentry0A12ConnectivityO", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ], - "enumRawTypeName": "Int", - "conformances": [ - { - "kind": "Conformance", - "name": "Copyable", - "printedName": "Copyable", - "usr": "s:s8CopyableP", - "mangledName": "$ss8CopyableP" - }, - { - "kind": "Conformance", - "name": "Escapable", - "printedName": "Escapable", - "usr": "s:s9EscapableP", - "mangledName": "$ss9EscapableP" - }, - { - "kind": "Conformance", - "name": "Equatable", - "printedName": "Equatable", - "usr": "s:SQ", - "mangledName": "$sSQ" - }, - { - "kind": "Conformance", - "name": "Hashable", - "printedName": "Hashable", - "usr": "s:SH", - "mangledName": "$sSH" - }, - { - "kind": "Conformance", - "name": "RawRepresentable", - "printedName": "RawRepresentable", - "children": [ - { - "kind": "TypeWitness", - "name": "RawValue", - "printedName": "RawValue", - "children": [ - { - "kind": "TypeNameAlias", - "name": "RawValue", - "printedName": "Sentry.SentryConnectivity.RawValue", - "children": [ - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" - } - ] - } - ] - } - ], - "usr": "s:SY", - "mangledName": "$sSY" - } - ] - }, { "kind": "TypeDecl", "name": "SentryViewScreenshotOptions", @@ -61400,48 +61120,6 @@ } ] }, - { - "kind": "Var", - "name": "SENTRY_HAS_REACHABILITY", - "printedName": "SENTRY_HAS_REACHABILITY", - "children": [ - { - "kind": "TypeNominal", - "name": "Int32", - "printedName": "Swift.Int32", - "usr": "s:s5Int32V" - } - ], - "declKind": "Var", - "usr": "c:@macro@SENTRY_HAS_REACHABILITY", - "moduleName": "Sentry", - "declAttributes": [ - "Nonisolated" - ], - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Int32", - "printedName": "Swift.Int32", - "usr": "s:s5Int32V" - } - ], - "declKind": "Accessor", - "usr": "s:SC23SENTRY_HAS_REACHABILITYs5Int32Vvg", - "mangledName": "$sSC23SENTRY_HAS_REACHABILITYs5Int32Vvg", - "moduleName": "Sentry", - "declAttributes": [ - "Transparent" - ], - "accessorKind": "get" - } - ] - }, { "kind": "Var", "name": "SENTRY_HAS_UIKIT", diff --git a/sdk_api_V9.json b/sdk_api_V9.json index 4f9b0c3b4eb..cf90400bd1e 100644 --- a/sdk_api_V9.json +++ b/sdk_api_V9.json @@ -40512,286 +40512,6 @@ "declKind": "Import", "moduleName": "Sentry" }, - { - "kind": "TypeDecl", - "name": "SentryConnectivity", - "printedName": "SentryConnectivity", - "children": [ - { - "kind": "Var", - "name": "cellular", - "printedName": "cellular", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentryConnectivity.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - } - ] - } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityCellular", - "mangledName": "$s6Sentry0A12ConnectivityO8cellularyA2CmF", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "wiFi", - "printedName": "wiFi", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentryConnectivity.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - } - ] - } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityWiFi", - "mangledName": "$s6Sentry0A12ConnectivityO4wiFiyA2CmF", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "none", - "printedName": "none", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryConnectivity.Type) -> Sentry.SentryConnectivity", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentryConnectivity.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - } - ] - } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@M@Sentry@E@SentryConnectivity@SentryConnectivityNone", - "mangledName": "$s6Sentry0A12ConnectivityO4noneyA2CmF", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Constructor", - "name": "init", - "printedName": "init(rawValue:)", - "children": [ - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "Sentry.SentryConnectivity?", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryConnectivity", - "printedName": "Sentry.SentryConnectivity", - "usr": "c:@M@Sentry@E@SentryConnectivity" - } - ], - "usr": "s:Sq" - }, - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" - } - ], - "declKind": "Constructor", - "usr": "s:6Sentry0A12ConnectivityO8rawValueACSgSi_tcfc", - "mangledName": "$s6Sentry0A12ConnectivityO8rawValueACSgSi_tcfc", - "moduleName": "Sentry", - "init_kind": "Designated" - }, - { - "kind": "TypeAlias", - "name": "RawValue", - "printedName": "RawValue", - "children": [ - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" - } - ], - "declKind": "TypeAlias", - "usr": "s:6Sentry0A12ConnectivityO8RawValuea", - "mangledName": "$s6Sentry0A12ConnectivityO8RawValuea", - "moduleName": "Sentry" - }, - { - "kind": "Var", - "name": "rawValue", - "printedName": "rawValue", - "children": [ - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" - } - ], - "declKind": "Var", - "usr": "s:6Sentry0A12ConnectivityO8rawValueSivp", - "mangledName": "$s6Sentry0A12ConnectivityO8rawValueSivp", - "moduleName": "Sentry", - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" - } - ], - "declKind": "Accessor", - "usr": "s:6Sentry0A12ConnectivityO8rawValueSivg", - "mangledName": "$s6Sentry0A12ConnectivityO8rawValueSivg", - "moduleName": "Sentry", - "accessorKind": "get" - } - ] - } - ], - "declKind": "Enum", - "usr": "c:@M@Sentry@E@SentryConnectivity", - "mangledName": "$s6Sentry0A12ConnectivityO", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ], - "enumRawTypeName": "Int", - "conformances": [ - { - "kind": "Conformance", - "name": "Copyable", - "printedName": "Copyable", - "usr": "s:s8CopyableP", - "mangledName": "$ss8CopyableP" - }, - { - "kind": "Conformance", - "name": "Escapable", - "printedName": "Escapable", - "usr": "s:s9EscapableP", - "mangledName": "$ss9EscapableP" - }, - { - "kind": "Conformance", - "name": "Equatable", - "printedName": "Equatable", - "usr": "s:SQ", - "mangledName": "$sSQ" - }, - { - "kind": "Conformance", - "name": "Hashable", - "printedName": "Hashable", - "usr": "s:SH", - "mangledName": "$sSH" - }, - { - "kind": "Conformance", - "name": "RawRepresentable", - "printedName": "RawRepresentable", - "children": [ - { - "kind": "TypeWitness", - "name": "RawValue", - "printedName": "RawValue", - "children": [ - { - "kind": "TypeNameAlias", - "name": "RawValue", - "printedName": "Sentry.SentryConnectivity.RawValue", - "children": [ - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" - } - ] - } - ] - } - ], - "usr": "s:SY", - "mangledName": "$sSY" - } - ] - }, { "kind": "TypeDecl", "name": "SentryViewScreenshotOptions", @@ -57928,48 +57648,6 @@ } ] }, - { - "kind": "Var", - "name": "SENTRY_HAS_REACHABILITY", - "printedName": "SENTRY_HAS_REACHABILITY", - "children": [ - { - "kind": "TypeNominal", - "name": "Int32", - "printedName": "Swift.Int32", - "usr": "s:s5Int32V" - } - ], - "declKind": "Var", - "usr": "c:@macro@SENTRY_HAS_REACHABILITY", - "moduleName": "Sentry", - "declAttributes": [ - "Nonisolated" - ], - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Int32", - "printedName": "Swift.Int32", - "usr": "s:s5Int32V" - } - ], - "declKind": "Accessor", - "usr": "s:SC23SENTRY_HAS_REACHABILITYs5Int32Vvg", - "mangledName": "$sSC23SENTRY_HAS_REACHABILITYs5Int32Vvg", - "moduleName": "Sentry", - "declAttributes": [ - "Transparent" - ], - "accessorKind": "get" - } - ] - }, { "kind": "Var", "name": "SENTRY_HAS_UIKIT", From 849d04b22b95be3e37af0a91022235b8b921bede Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Mon, 6 Oct 2025 23:24:03 -0300 Subject: [PATCH 18/22] Add missing import --- Tests/SentryTests/SentryTests-Bridging-Header.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/SentryTests/SentryTests-Bridging-Header.h b/Tests/SentryTests/SentryTests-Bridging-Header.h index 482b4c8f63e..d3177f2ea5a 100644 --- a/Tests/SentryTests/SentryTests-Bridging-Header.h +++ b/Tests/SentryTests/SentryTests-Bridging-Header.h @@ -1,3 +1,4 @@ +#import "SentryDefines.h" #if SENTRY_HAS_METRIC_KIT # import "SentryMetricKitIntegration.h" @@ -102,7 +103,6 @@ #import "SentryDebugMeta.h" #import "SentryDefaultAppStateManager.h" #import "SentryDefaultThreadInspector.h" -#import "SentryDefines.h" #import "SentryDependencyContainer.h" #import "SentryDiscardReason.h" #import "SentryDiscardReasonMapper.h" From b005648004f8557ada245ada6b902fcae7f54993 Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Tue, 7 Oct 2025 09:20:47 -0300 Subject: [PATCH 19/22] Fix typo --- Sources/Swift/Networking/SentryReachability.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Swift/Networking/SentryReachability.swift b/Sources/Swift/Networking/SentryReachability.swift index 4ac7d58f1c1..b231da39f4c 100644 --- a/Sources/Swift/Networking/SentryReachability.swift +++ b/Sources/Swift/Networking/SentryReachability.swift @@ -1,7 +1,7 @@ import Foundation import Network -// MARK: - SentryConectivity +// MARK: - SentryConnectivity enum SentryConnectivity: Int { case cellular case wiFi From 3f579575a8b2dc4be47edb4c7ed8197d6a2b6cf4 Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Tue, 7 Oct 2025 12:37:33 -0300 Subject: [PATCH 20/22] PR comments --- .../Swift/Networking/SentryReachability.swift | 62 +++++++++---------- .../SentryReachabilitySwiftTests.swift | 24 +++++-- 2 files changed, 49 insertions(+), 37 deletions(-) diff --git a/Sources/Swift/Networking/SentryReachability.swift b/Sources/Swift/Networking/SentryReachability.swift index b231da39f4c..9f80084203f 100644 --- a/Sources/Swift/Networking/SentryReachability.swift +++ b/Sources/Swift/Networking/SentryReachability.swift @@ -55,6 +55,7 @@ public class SentryReachability: NSObject { reachabilityObservers.add(observer) if reachabilityObservers.count > 1 { + SentrySDKLog.debug("More than one observer added. Doing nothing.") return } @@ -65,24 +66,22 @@ public class SentryReachability: NSObject { } #endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI - let monitor = NWPathMonitor() - self.pathMonitor = monitor - monitor.pathUpdateHandler = self.pathUpdateHandler - monitor.start(queue: self.reachabilityQueue) + self.pathMonitor = NWPathMonitor() + self.pathMonitor?.pathUpdateHandler = self.pathUpdateHandler + self.pathMonitor?.start(queue: self.reachabilityQueue) } @objc(removeObserver:) public func remove(_ observer: SentryReachabilityObserver) { SentrySDKLog.debug("Removing observer: \(observer)") - observersLock.lock() - defer { observersLock.unlock() } - - SentrySDKLog.debug("Synchronized to remove observer: \(observer)") - reachabilityObservers.remove(observer) - - if reachabilityObservers.count == 0 { - stopMonitoring() + observersLock.synchronized { + SentrySDKLog.debug("Synchronized to remove observer: \(observer)") + reachabilityObservers.remove(observer) + + if reachabilityObservers.count == 0 { + stopMonitoring() + } } } @@ -90,12 +89,11 @@ public class SentryReachability: NSObject { public func removeAllObservers() { SentrySDKLog.debug("Removing all observers.") - observersLock.lock() - defer { observersLock.unlock() } - - SentrySDKLog.debug("Synchronized to remove all observers.") - reachabilityObservers.removeAllObjects() - stopMonitoring() + observersLock.synchronized { + SentrySDKLog.debug("Synchronized to remove all observers.") + reachabilityObservers.removeAllObjects() + stopMonitoring() + } } private func stopMonitoring() { @@ -113,8 +111,6 @@ public class SentryReachability: NSObject { monitor.cancel() pathMonitor = nil } - - SentrySDKLog.debug("Cleaning up reachability queue.") } private func pathUpdateHandler(_ path: NWPath) { @@ -147,16 +143,6 @@ public class SentryReachability: NSObject { #endif // canImport(UIKit) } - private func connectivityShouldReportChange(_ connectivity: SentryConnectivity) -> Bool { - if connectivity == currentConnectivity { - SentrySDKLog.debug("No change in reachability state. ConnectivityShouldReportChange will return false for connectivity \(connectivity.toString()), currentConnectivity \(currentConnectivity.toString())") - return false - } - - currentConnectivity = connectivity - return true - } - fileprivate func connectivityCallback(_ connectivity: SentryConnectivity) { observersLock.lock() defer { observersLock.unlock() } @@ -168,20 +154,30 @@ public class SentryReachability: NSObject { return } - guard connectivityShouldReportChange(connectivity) else { - SentrySDKLog.debug("ConnectivityShouldReportChange returned false for connectivity \(connectivity.toString()), will not report change to observers.") + let previousConnectivity = currentConnectivity + currentConnectivity = connectivity + guard connectivityShouldReportChange(previousConnectivity, currentConnectivity) else { return } let connected = connectivity != .none - SentrySDKLog.debug("Notifying observers...") + SentrySDKLog.debug("Notifying observers with connected: \(connected), connectivity: \(connectivity.toString())") for observer in reachabilityObservers.allObjects { SentrySDKLog.debug("Notifying \(observer)") observer.connectivityChanged(connected, typeDescription: connectivity.toString()) } SentrySDKLog.debug("Finished notifying observers.") } + + private func connectivityShouldReportChange(_ previousConnectivity: SentryConnectivity, _ newConnectivity: SentryConnectivity) -> Bool { + if previousConnectivity == newConnectivity { + SentrySDKLog.debug("No change in reachability state. ConnectivityShouldReportChange will return false for connectivity \(previousConnectivity.toString()), newConnectivity \(newConnectivity.toString())") + return false + } + + return true + } deinit { removeAllObservers() diff --git a/Tests/SentryTests/Networking/SentryReachabilitySwiftTests.swift b/Tests/SentryTests/Networking/SentryReachabilitySwiftTests.swift index fad5f8d5970..3c211334ae4 100644 --- a/Tests/SentryTests/Networking/SentryReachabilitySwiftTests.swift +++ b/Tests/SentryTests/Networking/SentryReachabilitySwiftTests.swift @@ -3,6 +3,7 @@ import XCTest class TestSentryReachabilityObserver: NSObject, SentryReachabilityObserver { var connectivityChangedInvocations: UInt = 0 + var onReachabilityChanged: ((Bool, String) -> Void)? override init() { super.init() @@ -12,6 +13,7 @@ class TestSentryReachabilityObserver: NSObject, SentryReachabilityObserver { func connectivityChanged(_ connected: Bool, typeDescription: String) { print("Received connectivity notification: \(connected); type: \(typeDescription)") connectivityChangedInvocations += 1 + onReachabilityChanged?(connected, typeDescription) } } @@ -102,10 +104,7 @@ final class SentryReachabilitySwiftTests: XCTestCase { reachability.remove(observer) } - /** - * We only want to make sure running the actual registering and unregistering callbacks doesn't - * crash. - */ + /// We only want to make sure running the actual registering and unregistering callbacks doesn't crash. func testRegisteringActualCallbacks() { reachability.skipRegisteringActualCallbacks = false @@ -129,4 +128,21 @@ final class SentryReachabilitySwiftTests: XCTestCase { sut.removeAllObservers() }) } + + /// This tests actually test NWPathMonitor response, if it becomes blaky we can disable it + func testRegisteringActualCallbacks_CallbackIsCalled() { + reachability.skipRegisteringActualCallbacks = false + reachability.setReachabilityIgnoreActualCallback(false) + + let expectation = XCTestExpectation(description: "Callback should be called") + + let observer = TestSentryReachabilityObserver() + observer.onReachabilityChanged = { _, _ in + expectation.fulfill() + } + + reachability.add(observer) + + wait(for: [expectation], timeout: 5) + } } From 11ed170a055a8042fd81af3b9d39ef2e5ad62023 Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Tue, 7 Oct 2025 12:39:35 -0300 Subject: [PATCH 21/22] Update changelog --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2657c4bf89..feced7330e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,11 @@ ### Fixes -Fixes warnings about minimum OS version being lower than Xcode supported version (#5591) +- Fixes warnings about minimum OS version being lower than Xcode supported version (#5591) + +### Improvements + +- Replaces the use of SCNetworkReachabilityFlags with NWPathMonitor (#6019) ## 8.56.2 From 75ca65243f5279ad81416dd211c9a82df3d6d4e5 Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Tue, 7 Oct 2025 13:21:09 -0300 Subject: [PATCH 22/22] Fix linter --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f267332c59f..5fe10416235 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,6 @@ - Replaces the use of SCNetworkReachabilityFlags with NWPathMonitor (#6019) - ## 8.56.2 ### Fixes