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. 运行后,用两个手指头在状态栏上同时点击下就可以显示出这个调试的悬浮层。

运行效果

701B8D4445F947915AE73C70AA1E7FA0.png

你值得拥有~


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

#import <UIKit/UIKit.h>
#import <objc/runtime.h>


/*
 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
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 174,883评论 25 709
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,885评论 18 399
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,292评论 19 139
  • 准备了好多的面试技巧,面试方法论,可是在面试的那一天却发现,之前准备的都没有派上用场。背了好多天的题,等到考试那天...
    浆糊郎中阅读 654评论 0 1
  • 多年前认识一位香港籍的朋友,比我年纪稍长,却是三个孩子的母亲,她高中毕业便结婚生子,身为政府公务员的丈夫一人赚钱养...
    点苍阅读 2,038评论 3 13