diff --git a/DBDebugToolkit/Classes/CrashReports/DBCrashReportDetailsTableViewController.m b/DBDebugToolkit/Classes/CrashReports/DBCrashReportDetailsTableViewController.m index 65691e5..458f27d 100644 --- a/DBDebugToolkit/Classes/CrashReports/DBCrashReportDetailsTableViewController.m +++ b/DBDebugToolkit/Classes/CrashReports/DBCrashReportDetailsTableViewController.m @@ -26,7 +26,11 @@ #import "DBTextViewViewController.h" #import "DBImageViewViewController.h" #import +#if __has_include() #import +#else +#import +#endif typedef NS_ENUM(NSUInteger, DBCrashReportDetailsTableViewControllerSection) { DBCrashReportDetailsTableViewControllerSectionDetails, diff --git a/DBDebugToolkit/Classes/CrashReports/DBCrashReportsToolkit.m b/DBDebugToolkit/Classes/CrashReports/DBCrashReportsToolkit.m index 633873a..7accec6 100644 --- a/DBDebugToolkit/Classes/CrashReports/DBCrashReportsToolkit.m +++ b/DBDebugToolkit/Classes/CrashReports/DBCrashReportsToolkit.m @@ -27,7 +27,11 @@ #include #include #include +#if __has_include() #import +#else +#import +#endif typedef void (*sighandler_t)(int); diff --git a/DBDebugToolkit/Classes/DBDebugToolkit.m b/DBDebugToolkit/Classes/DBDebugToolkit.m index 1823c9f..2703703 100644 --- a/DBDebugToolkit/Classes/DBDebugToolkit.m +++ b/DBDebugToolkit/Classes/DBDebugToolkit.m @@ -37,14 +37,19 @@ #import "DBCrashReportsToolkit.h" #import "DBTopLevelViewsWrapper.h" #import "UIApplication+DBDebugToolkit.h" +#if __has_include() #import +#else +#import +#endif + static NSString *const DBDebugToolkitObserverPresentationControllerPropertyKeyPath = @"containerView"; @interface DBDebugToolkit () @property (nonatomic, copy) NSArray > *triggers; -@property (nonatomic, strong) DBMenuTableViewController *menuViewController; +@property (nonatomic, strong) UIViewController *menuViewController; @property (nonatomic, assign) BOOL showsMenu; @property (nonatomic, strong) DBPerformanceToolkit *performanceToolkit; @property (nonatomic, strong) DBConsoleOutputCaptor *consoleOutputCaptor; @@ -399,6 +404,13 @@ + (UIViewController *)menuViewController { - (void)showMenu { self.showsMenu = YES; UIViewController *presentingViewController = [self topmostViewController]; + if (@available(iOS 15.0, *)) { + UINavigationBarAppearance *navBarAppearance = [[UINavigationBarAppearance alloc] init]; + navBarAppearance.backgroundColor = [UIColor whiteColor]; + [navBarAppearance configureWithOpaqueBackground]; + [UINavigationBar appearance].standardAppearance = navBarAppearance; + [UINavigationBar appearance].scrollEdgeAppearance = navBarAppearance; + } UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:self.menuViewController]; navigationController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; navigationController.modalPresentationStyle = UIModalPresentationOverFullScreen; @@ -432,7 +444,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N } } -- (DBMenuTableViewController *)menuViewController { +- (UIViewController *)menuViewController { if (!_menuViewController) { _menuViewController = [SwiftUIViewFactory makeMenuListViewWithPerformanceToolkit:self.performanceToolkit @@ -452,24 +464,6 @@ - (DBMenuTableViewController *)menuViewController { } return _menuViewController; - - if (!_menuViewController) { - NSBundle *bundle = [NSBundle debugToolkitBundle]; - UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"DBMenuTableViewController" bundle:bundle]; - _menuViewController = [storyboard instantiateInitialViewController]; - _menuViewController.performanceToolkit = self.performanceToolkit; - _menuViewController.consoleOutputCaptor = self.consoleOutputCaptor; - _menuViewController.networkToolkit = self.networkToolkit; - _menuViewController.userInterfaceToolkit = self.userInterfaceToolkit; - _menuViewController.locationToolkit = self.locationToolkit; - _menuViewController.coreDataToolkit = self.coreDataToolkit; - _menuViewController.crashReportsToolkit = self.crashReportsToolkit; - _menuViewController.deviceInfoProvider = [DBDeviceInfoProvider new]; - _menuViewController.delegate = self; - } - _menuViewController.customVariables = self.customVariables.allValues; - _menuViewController.customActions = self.customActions; - return _menuViewController; } - (UIViewController *)topmostViewController { @@ -521,10 +515,6 @@ - (void)performanceWidgetView:(DBPerformanceWidgetView *)performanceWidgetView d // Only update the presented DBPerformanceTableViewController instance. DBPerformanceTableViewController *performanceTableViewController = (DBPerformanceTableViewController *)navigationController.viewControllers[1]; performanceTableViewController.selectedSection = section; - } else { - // Update navigation controller's view controllers. - [self.menuViewController openPerformanceMenuWithSection:section - animated:shouldAnimateShowingPerformance]; } } diff --git a/DBDebugToolkit/Classes/Menu/DBMenuTableViewController.m b/DBDebugToolkit/Classes/Menu/DBMenuTableViewController.m index 00150e7..39db005 100644 --- a/DBDebugToolkit/Classes/Menu/DBMenuTableViewController.m +++ b/DBDebugToolkit/Classes/Menu/DBMenuTableViewController.m @@ -29,7 +29,11 @@ #import "DBCustomActionsTableViewController.h" #import "DBCustomVariablesTableViewController.h" #import "DBCrashReportsTableViewController.h" +#if __has_include() #import +#else +#import +#endif typedef NS_ENUM(NSUInteger, DBMenuTableViewControllerRow) { DBMenuTableViewControllerRowPerformance, diff --git a/DBDebugToolkit/Classes/Network/URLProtocol/NSURLSessionDelegateSwizzle.m b/DBDebugToolkit/Classes/Network/URLProtocol/NSURLSessionDelegateSwizzle.m index 68e6e7b..511c2b1 100644 --- a/DBDebugToolkit/Classes/Network/URLProtocol/NSURLSessionDelegateSwizzle.m +++ b/DBDebugToolkit/Classes/Network/URLProtocol/NSURLSessionDelegateSwizzle.m @@ -105,180 +105,163 @@ + (void)searchDelegateClasses { } + (void)swizzleIntoDelegateClasses:(Class)className { - // NSURLSessionTaskDelegate - [self exchangeMethodsWithOriginalSelector:@selector(dataTaskWithURL:) - swizzledSelector:@selector(db_dataTaskWithURL:) - className:className]; - [self exchangeMethodsWithOriginalSelector:@selector(dataTaskWithRequest:) - swizzledSelector:@selector(db_dataTaskWithRequest:) - className:className]; - [self exchangeMethodsWithOriginalSelector:@selector(URLSession:dataTask:didReceiveData:) - swizzledSelector:@selector(db_URLSession:dataTask:didReceiveData:) - className:className]; - [self exchangeMethodsWithOriginalSelector:@selector(URLSession:dataTask:didReceiveResponse:completionHandler:) - swizzledSelector:@selector(db_URLSession:dataTask:didReceiveResponse:completionHandler:) - className:className]; - [self exchangeMethodsWithOriginalSelector:@selector(URLSession:task:didCompleteWithError:) - swizzledSelector:@selector(db_URLSession:task:didCompleteWithError:) - className:className]; - [self exchangeMethodsWithOriginalSelector:@selector(URLSession:dataTask:willCacheResponse:completionHandler:) - swizzledSelector:@selector(db_URLSession:dataTask:willCacheResponse:completionHandler:) - className:className]; + // NSURLSessionTaskDelegate + [self exchangeMethodsWithOriginalSelector:@selector(dataTaskWithURL:) + swizzledSelector:@selector(db_dataTaskWithURL:) + className:className]; + [self exchangeMethodsWithOriginalSelector:@selector(dataTaskWithRequest:) + swizzledSelector:@selector(db_dataTaskWithRequest:) + className:className]; + [self exchangeMethodsWithOriginalSelector:@selector(URLSession:dataTask:didReceiveData:) + swizzledSelector:@selector(db_URLSession:dataTask:didReceiveData:) + className:className]; + [self exchangeMethodsWithOriginalSelector:@selector(URLSession:dataTask:didReceiveResponse:completionHandler:) + swizzledSelector:@selector(db_URLSession:dataTask:didReceiveResponse:completionHandler:) + className:className]; + [self exchangeMethodsWithOriginalSelector:@selector(URLSession:task:didCompleteWithError:) + swizzledSelector:@selector(db_URLSession:task:didCompleteWithError:) + className:className]; + [self exchangeMethodsWithOriginalSelector:@selector(URLSession:dataTask:willCacheResponse:completionHandler:) + swizzledSelector:@selector(db_URLSession:dataTask:willCacheResponse:completionHandler:) + className:className]; } + (void)swizzleNSURLSessionCompletion { - SEL selector = @selector(dataTaskWithRequest:completionHandler:); - SEL swizzledSelector = @selector(db_dataTaskWithRequest:completionHandler:); - - Class class = [NSURLSession.sharedSession class]; - typedef void (^NSURLSessionCompletion)( - id dataResponse, NSURLResponse *response, NSError *error); - - typedef NSURLSessionTask * (^NSURLSessionNewMethod)( - NSURLSession *, NSURLRequest *, NSURLSessionCompletion); - - NSURLSessionNewMethod swizzleBlock = - ^NSURLSessionTask *(NSURLSession *slf, NSURLRequest *request, - NSURLSessionCompletion completion) { - NSURLSessionCompletion completionWrapper = ^( - id dataResponse, NSURLResponse *response, NSError *error) { - [[DBNetworkToolkit sharedInstance] saveRequest:request]; - NSData *data = nil; - if ([dataResponse isKindOfClass:[NSURL class]]) { - data = [NSData dataWithContentsOfURL:dataResponse]; - } else if ([dataResponse isKindOfClass:[NSData class]]) { - data = dataResponse; - } - if (error) { - [[DBNetworkToolkit sharedInstance] - saveRequestOutcome:[DBRequestOutcome outcomeWithError:error] - forRequest:request]; - } else { - [[DBNetworkToolkit sharedInstance] - saveRequestOutcome:[DBRequestOutcome - outcomeWithResponse:response - data:data] - forRequest:request]; - } - if (completion) { - completion(dataResponse, response, error); - } - }; - return ((id(*)(id, SEL, id, id))objc_msgSend)( - slf, swizzledSelector, request, completionWrapper); - }; - - [self exchangeMethodsWithOriginalSelector:selector - onClass:class - withBlock:swizzleBlock - swizzledSelector:swizzledSelector]; + SEL selector = @selector(dataTaskWithRequest:completionHandler:); + SEL swizzledSelector = @selector(db_dataTaskWithRequest:completionHandler:); + + Class class = [NSURLSession class]; + typedef void (^NSURLSessionCompletion)(id dataResponse, NSURLResponse *response, NSError *error); + + typedef NSURLSessionTask * (^NSURLSessionNewMethod)(NSURLSession *, NSURLRequest *, NSURLSessionCompletion); + + NSURLSessionNewMethod swizzleBlock = ^NSURLSessionTask *(NSURLSession *slf, NSURLRequest *request, NSURLSessionCompletion completion) { + NSURLSessionCompletion completionWrapper = ^(id dataResponse, NSURLResponse *response, NSError *error) { + [[DBNetworkToolkit sharedInstance] saveRequest:request]; + NSData *data = nil; + if ([dataResponse isKindOfClass:[NSURL class]]) { + data = [NSData dataWithContentsOfURL:dataResponse]; + } else if ([dataResponse isKindOfClass:[NSData class]]) { + data = dataResponse; + } + if (error) { + [[DBNetworkToolkit sharedInstance] saveRequestOutcome:[DBRequestOutcome outcomeWithError:error] forRequest:request]; + } else { + [[DBNetworkToolkit sharedInstance] saveRequestOutcome:[DBRequestOutcome outcomeWithResponse:response data:data] forRequest:request]; + } + if (completion) { + completion(dataResponse, response, error); + } + }; + return ((id(*)(id, SEL, id, id))objc_msgSend)(slf, swizzledSelector, request, completionWrapper); + }; + + [self exchangeMethodsWithOriginalSelector:selector onClass:class withBlock:swizzleBlock swizzledSelector:swizzledSelector]; } + (void)exchangeMethodsWithOriginalSelector:(SEL)originalSelector - onClass:(Class)class - withBlock:(id)block - swizzledSelector:(SEL)swizzledSelector { - Method originalMethod = class_getInstanceMethod(class, originalSelector); - if (!originalMethod) { - return; - } - - IMP implementation = imp_implementationWithBlock(block); - class_addMethod(class, swizzledSelector, implementation, method_getTypeEncoding(originalMethod)); - Method newMethod = class_getInstanceMethod(class, swizzledSelector); - method_exchangeImplementations(originalMethod, newMethod); + onClass:(Class)class + withBlock:(id)block + swizzledSelector:(SEL)swizzledSelector { + Method originalMethod = class_getInstanceMethod(class, originalSelector); + if (!originalMethod) { + return; + } + + IMP implementation = imp_implementationWithBlock(block); + class_addMethod(class, swizzledSelector, implementation, method_getTypeEncoding(originalMethod)); + Method newMethod = class_getInstanceMethod(class, swizzledSelector); + method_exchangeImplementations(originalMethod, newMethod); } + (void)exchangeMethodsWithOriginalSelector:(SEL)originalSelector - swizzledSelector:(SEL)swizzledSelector - className:(Class)className -{ - Class class = className; - Class swizzleClass = [self class]; - Method originalMethod = class_getInstanceMethod(class, originalSelector); - Method swizzledMethod = class_getInstanceMethod(swizzleClass, swizzledSelector); - - IMP originalImp = method_getImplementation(originalMethod); - IMP swizzledImp = method_getImplementation(swizzledMethod); - - class_replaceMethod(class, - swizzledSelector, - originalImp, - method_getTypeEncoding(originalMethod)); - - class_replaceMethod(class, - originalSelector, - swizzledImp, - method_getTypeEncoding(swizzledMethod)); + swizzledSelector:(SEL)swizzledSelector + className:(Class)className { + Class class = className; + Class swizzleClass = [self class]; + Method originalMethod = class_getInstanceMethod(class, originalSelector); + Method swizzledMethod = class_getInstanceMethod(swizzleClass, swizzledSelector); + + if (!originalMethod || !swizzledMethod) { + return; + } + + IMP originalImp = method_getImplementation(originalMethod); + IMP swizzledImp = method_getImplementation(swizzledMethod); + + class_replaceMethod(class, swizzledSelector, originalImp, method_getTypeEncoding(originalMethod)); + class_replaceMethod(class, originalSelector, swizzledImp, method_getTypeEncoding(swizzledMethod)); } + (IMP)replaceMethodWithSelector:(SEL)originalSelector block:(id)block className:(Class)className { - NSCParameterAssert(block); + NSCParameterAssert(block); - Method originalMethod = class_getInstanceMethod(className, originalSelector); - NSCParameterAssert(originalMethod); + Method originalMethod = class_getInstanceMethod(className, originalSelector); + NSCParameterAssert(originalMethod); - IMP newIMP = imp_implementationWithBlock(block); + IMP newIMP = imp_implementationWithBlock(block); - if (!class_addMethod(className, originalSelector, newIMP, method_getTypeEncoding(originalMethod))) { - return method_setImplementation(originalMethod, newIMP); - } else { - return method_getImplementation(originalMethod); - } + if (!class_addMethod(className, originalSelector, newIMP, method_getTypeEncoding(originalMethod))) { + return method_setImplementation(originalMethod, newIMP); + } else { + return method_getImplementation(originalMethod); + } } - (NSURLSessionDataTask *)db_dataTaskWithURL:(NSURL *)url { - return [self db_dataTaskWithURL:url]; + return [self db_dataTaskWithURL:url]; } - (NSURLSessionDataTask *)db_dataTaskWithRequest:(NSURLRequest *)request { - [[DBNetworkToolkit sharedInstance] saveRequest:request]; - return [self db_dataTaskWithRequest:request]; + [[DBNetworkToolkit sharedInstance] saveRequest:request]; + return [self db_dataTaskWithRequest:request]; } - (void)db_URLSession:(NSURLSession *)session - dataTask:(NSURLSessionDataTask *)dataTask - willCacheResponse:(NSCachedURLResponse *)proposedResponse - completionHandler:(void (^)(NSCachedURLResponse * _Nullable cachedResponse))completionHandler -{ - if([self respondsToSelector:@selector(db_URLSession:dataTask:willCacheResponse:completionHandler:)]) { - [self db_URLSession:session dataTask:dataTask willCacheResponse:proposedResponse completionHandler:completionHandler]; - } + dataTask:(NSURLSessionDataTask *)dataTask + willCacheResponse:(NSCachedURLResponse *)proposedResponse + completionHandler:(void (^)(NSCachedURLResponse * _Nullable cachedResponse))completionHandler { + [[DBNetworkToolkit sharedInstance] saveRequest:dataTask.originalRequest]; + if ([self respondsToSelector:@selector(db_URLSession:dataTask:willCacheResponse:completionHandler:)]) { + [self db_URLSession:session dataTask:dataTask willCacheResponse:proposedResponse completionHandler:completionHandler]; + } else { + completionHandler(proposedResponse); // Ensure the completion handler is called + } } - (void)db_URLSession:(NSURLSession *)session - dataTask:(NSURLSessionDataTask *)dataTask + dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response - completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler -{ - [[DBNetworkToolkit sharedInstance] saveRequest:dataTask.originalRequest]; - if([self respondsToSelector:@selector(db_URLSession:dataTask:didReceiveResponse:completionHandler:)]) { - [self db_URLSession:session dataTask:dataTask didReceiveResponse:response completionHandler:completionHandler]; - } + completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler { + [[DBNetworkToolkit sharedInstance] saveRequest:dataTask.originalRequest]; + if ([self respondsToSelector:@selector(db_URLSession:dataTask:didReceiveResponse:completionHandler:)]) { + [self db_URLSession:session dataTask:dataTask didReceiveResponse:response completionHandler:completionHandler]; + } else { + completionHandler(NSURLSessionResponseAllow); // Ensure the completion handler is called + } } - (void)db_URLSession:(NSURLSession *)session - dataTask:(NSURLSessionDataTask *)dataTask - didReceiveData:(NSData *)data -{ - [[DBNetworkToolkit sharedInstance] saveRequestOutcome:[DBRequestOutcome outcomeWithResponse:dataTask.response data:data] forRequest:dataTask.originalRequest]; - if([self respondsToSelector:@selector(db_URLSession:dataTask:didReceiveData:)]) { - [self db_URLSession:session dataTask:dataTask didReceiveData:data]; - } + dataTask:(NSURLSessionDataTask *)dataTask + didReceiveData:(NSData *)data { + [[DBNetworkToolkit sharedInstance] saveRequestOutcome:[DBRequestOutcome outcomeWithResponse:dataTask.response data:data] forRequest:dataTask.originalRequest]; + if ([self respondsToSelector:@selector(db_URLSession:dataTask:didReceiveData:)]) { + [self db_URLSession:session dataTask:dataTask didReceiveData:data]; + } } - (void)db_URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { - if(error != nil) { - [[DBNetworkToolkit sharedInstance] saveRequestOutcome:[DBRequestOutcome outcomeWithError:error] forRequest:task.originalRequest]; - } + if (error != nil) { + [[DBNetworkToolkit sharedInstance] saveRequestOutcome:[DBRequestOutcome outcomeWithError:error] forRequest:task.originalRequest]; + } - if([self respondsToSelector:@selector(db_URLSession:task:didCompleteWithError:)]) { - [self db_URLSession:session task:task didCompleteWithError:error]; - } + if ([self respondsToSelector:@selector(db_URLSession:task:didCompleteWithError:)]) { + [self db_URLSession:session task:task didCompleteWithError:error]; + } } -- (NSURLSessionDataTask *)db_dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler -{ - return [self db_dataTaskWithRequest:request completionHandler:completionHandler]; +- (NSURLSessionDataTask *)db_dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler { + return [self db_dataTaskWithRequest:request completionHandler:completionHandler]; } + @end diff --git a/DBDebugToolkit/Classes/UserInterface/DBUserInterfaceToolkit.m b/DBDebugToolkit/Classes/UserInterface/DBUserInterfaceToolkit.m index 36e3411..d0ac615 100644 --- a/DBDebugToolkit/Classes/UserInterface/DBUserInterfaceToolkit.m +++ b/DBDebugToolkit/Classes/UserInterface/DBUserInterfaceToolkit.m @@ -25,7 +25,11 @@ #import "UIWindow+DBUserInterfaceToolkit.h" #import "NSObject+DBDebugToolkit.h" #import "UIColor+DBDebugToolkit.h" +#if __has_include() #import +#else +#import +#endif NSString *const DBUserInterfaceToolkitColorizedViewBordersChangedNotification = @"DBUserInterfaceToolkitColorizedViewBordersChangedNotification";