iOS自带悬浮窗调试工具

[九九Tips]- http://www.jianshu.com/users/bab86b3e8aa3/latest_articles

参考的博客:
https://wellphone.me/post/2017/use_uidebugginginformationoverlay_to_debug_ui/

使用步骤(简化版):

  1. 先把文件UIDebuggingInformationOverlay+Enable.m放在拖到工程里,这个文件内容放在文章的结尾处。

  2. didFinishLaunchingWithOptions方法中粘贴下面一段代码

#ifdef DEBUG 
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
    id overlayClass = NSClassFromString(@"UIDebuggingInformationOverlay");
    [overlayClass performSelector:NSSelectorFromString(@"prepareDebuggingOverlay")];
#pragma clang diagnostic pop
    
#endif
  1. 运行后,用两个手指头在状态栏上同时点击下就可以显示出这个调试的悬浮层。

运行效果

iOS自带悬浮窗调试工具_第1张图片
701B8D4445F947915AE73C70AA1E7FA0.png

你值得拥有~


下面的代码为附件文件,请保存为 UIDebuggingInformationOverlay+Enable.m 格式拖到工程目录下:

#import 
#import 


/*
 In iOS 11, Apple added additional checks to disable this overlay unless the
 device is an internal device. To get around this, we swizzle out the
 -[UIDebuggingInformationOverlay init] method (which returns nil now if
 the device is non-internal) and +[UIDebuggingInformationOverlay prepareDebuggingOverlay]
 method.
 
 Usage:
  1.Copy this file to your project.
  2.Add the following code to [AppDelegate application:didFinishLaunchingWithOptions:]
 
 #if DEBUG
 id overlayClass = NSClassFromString(@"UIDebuggingInformationOverlay");
 [overlayClass performSelector:NSSelectorFromString(@"prepareDebuggingOverlay")];
 #endif
 
 */


#if defined(DEBUG) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wincomplete-implementation"
#pragma clang diagnostic ignored "-Wundeclared-selector"
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"

@interface UIWindow (PrivateMethods)
- (void)_setWindowControlsStatusBarOrientation:(BOOL)orientation;
@end

@interface FakeWindowClass : UIWindow
@end

@implementation FakeWindowClass

- (instancetype)initSwizzled {
    self = [super init];
    if (self) {
        [self _setWindowControlsStatusBarOrientation:NO];
    }
    return self;
}

@end

@implementation NSObject (UIDebuggingInformationOverlayEnable)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class cls = NSClassFromString(@"UIDebuggingInformationOverlay");
        [FakeWindowClass swizzleSelector:@selector(init) newSelector:@selector(initSwizzled) forClass:cls isClassMethod:NO];
        [self swizzleSelector:@selector(prepareDebuggingOverlay) newSelector:@selector(prepareDebuggingOverlaySwizzled) forClass:cls isClassMethod:YES];
    });
}

+ (void)swizzleSelector:(SEL)originalSelector newSelector:(SEL)swizzledSelector forClass:(Class)class isClassMethod:(BOOL)isClassMethod {
    Method originalMethod = NULL;
    Method swizzledMethod = NULL;
    
    if (isClassMethod) {
        originalMethod = class_getClassMethod(class, originalSelector);
        swizzledMethod = class_getClassMethod([self class], swizzledSelector);
    } else {
        originalMethod = class_getInstanceMethod(class, originalSelector);
        swizzledMethod = class_getInstanceMethod([self class], swizzledSelector);
    }
    method_exchangeImplementations(originalMethod, swizzledMethod);
}

+ (void)prepareDebuggingOverlaySwizzled {
    id overlayClass = NSClassFromString(@"UIDebuggingInformationOverlayInvokeGestureHandler");
    id handler = [overlayClass performSelector:NSSelectorFromString(@"mainHandler")];
  
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:handler action:@selector(_handleActivationGesture:)];
    tapGesture.numberOfTouchesRequired = 2;
    tapGesture.numberOfTapsRequired = 1;
    tapGesture.delegate = handler;
  
    UIView *statusBarWindow = [[UIApplication sharedApplication] valueForKey:@"statusBarWindow"];
    [statusBarWindow addGestureRecognizer:tapGesture];
}

@end
#pragma clang diagnostic pop

#endif

你可能感兴趣的:(iOS自带悬浮窗调试工具)