500px技术周报001

概览

Xcode9的无线调试

Facebook开源库fishhook的使用

UIViewController的调试小工具

自定义导航栏的侧滑返回

QGCollectionMenu简介

Xcode9的无线调试

环境:Xcode9-beta5 iOS-beta5

新的Macbook已经将充电接口和usb接口都换成了USB-C,iOS程序调试起来更加麻烦,而且iPhone7以后充电接口和耳机接口合并,又想调试又想听歌已经成为过去式。但是,Xcode9和iOS11给了我们新的福利,那就是无线调试。需要做的就是先线插一次,Xcode->Window->Devices and Simulators->Connect via network.如图 。

iOS无线调试

当链接成功后左侧栏的右侧会有网络图标。快去试试吧

注意:当你电脑中有两个版本的Xcode,如何在打开项目时 默认选中某一个版本的Xcode

sudo xcode-select -switch  /Users/zhangruquan/Downloads/Xcode-beta.app

Facebook开源库fishhook的使用:如何让打印消息只在debug模式下运行

网络上给出的方法如下:在***-Prefix.pch里面添加, 重新定义系统的NSLog,OPTIMIZE 是release 默认会加的宏

#ifndef __OPTIMIZE__
#define NSLog(...) NSLog(__VA_ARGS__)
#else
#define NSLog(...){}
#endif

我也试了一下,可以用,但是如果你将一部分代码封装成静态链接库以pod方式集成进项目,那么这部分代码的NSLog打印的消息是屏蔽不掉的。当然我们可以使用Facebook公司的开源库fishhook来实现此功能,原理就是替换掉Mach-O符号表中某个函数对应的内存地址。

使用方法,将fishhook.h和fishhook.m加入到项目中,此时编译项目应该会报错Unknown type name ‘NSString’ / Expected identifier or ‘(‘等等。这时候需要修改***-Prefix.pch

#ifdef __OBJC__
#import <OOObjectiveCClass.h>
#endif

再次编译应该就没问题了。

具体实现代码如下

#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "fishhook.h"

static void (*orig_NSLog)(NSString *format, ...);
void(new_NSLog)(NSString *format, ...) {
#ifdef DEBUG
    va_list args;
    if(format) {
        va_start(args, format);
        NSString *message = [[NSString alloc] initWithFormat:format arguments:args];
        orig_NSLog(@"%@", message);
        va_end(args);
    }
#endif
}

int main(int argc, char * argv[]) {
    @autoreleasepool {
        rebind_symbols((struct rebinding[1])NSLog, 1);
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
    
    
}

测试后的时候需要修改product->Scheme->Edit Scheme->Build Configuration 修改为Release

UIViewController调试小工具

多人开发,如何快速查看当前页面是调用的哪个UIViewController,又如何检查是不是由于self的循环引用导致的UIViewController没有释放

@interface UIViewController (QGiioo)

@end

@implementation UIViewController (QGiioo)

+ (void)load {
    
    Method viewDidLoad = class_getInstanceMethod(self, @selector(viewDidLoad));
    Method customViewDidLoad = class_getInstanceMethod(self, @selector(customViewDidLoad));
    method_exchangeImplementations(viewDidLoad, customViewDidLoad);
    
    SEL deallocSelector = sel_registerName("dealloc");
    Method dea = class_getInstanceMethod(self, deallocSelector);
    Method logdealloc = class_getInstanceMethod(self, @selector(logDealloc));
    method_exchangeImplementations(dea, logdealloc);
}

-(void)logDealloc
{
    NSLog(@"########88888%@ 类型的viewcontroller进行了释放",NSStringFromClass(self.class));
    [self logDealloc];
}

-(void)customViewDidLoad
{
    #ifdef DEBUG
    NSLog(@"########88888cur viewcontroller type:%@ ---  obj:%@",NSStringFromClass(self.class),self);
    #endif
    [self customViewDidLoad];
}



@end

自定义导航栏的侧滑返回

侧滑返回本来是iOS本身就支持的,但是如果将本身的导航栏隐藏掉,而新定义view为导航栏,则侧滑返回就失效了,想要启用只需要在viewDidAppear函数里执行

if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
        self.navigationController.interactivePopGestureRecognizer.enabled = YES;
    }

在viewDidDisappear里执行

if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
        self.navigationController.interactivePopGestureRecognizer.enabled = NO;
    }

但是如果你的UIViewController里的view中包含scrollview(竖滑动) 就需要额外添加代码,综合上面代码如下

@interface UIViewController (QGiioo)

@end

@implementation UIViewController (QGiioo)

+ (void)load {
    
    Method viewDidLoad = class_getInstanceMethod(self, @selector(viewDidLoad));
    Method customViewDidLoad = class_getInstanceMethod(self, @selector(customViewDidLoad));
    method_exchangeImplementations(viewDidLoad, customViewDidLoad);
    
    Method viewDidAppear = class_getInstanceMethod(self, @selector(viewDidAppear:));
    Method customViewDidAppear = class_getInstanceMethod(self, @selector(customViewDidAppear:));
    method_exchangeImplementations(viewDidAppear, customViewDidAppear);

    
    Method viewDidDisappear = class_getInstanceMethod(self, @selector(viewDidDisappear:));
    Method customViewDidDisappear = class_getInstanceMethod(self, @selector(customViewDidDisappear:));
    method_exchangeImplementations(viewDidDisappear, customViewDidDisappear);

    
    SEL deallocSelector = sel_registerName("dealloc");
    Method dea = class_getInstanceMethod(self, deallocSelector);
    Method logdealloc = class_getInstanceMethod(self, @selector(logDealloc));
    method_exchangeImplementations(dea, logdealloc);
}

-(void)logDealloc
{
    NSLog(@"########88888%@ 类型的viewcontroller进行了释放",NSStringFromClass(self.class));
    [self logDealloc];
}

-(void)customViewDidLoad
{
    #ifdef DEBUG
    NSLog(@"########88888cur viewcontroller type:%@ ---  obj:%@",NSStringFromClass(self.class),self);
    #endif
    [self customViewDidLoad];
}

-(void)customViewDidAppear:(BOOL)animated
{
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
        self.navigationController.interactivePopGestureRecognizer.enabled = YES;
        self.navigationController.interactivePopGestureRecognizer.delegate = self;
    }
    [self customViewDidAppear:animated];
}

-(void)customViewDidDisappear:(BOOL)animated
{
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
        self.navigationController.interactivePopGestureRecognizer.enabled = NO;
        self.navigationController.interactivePopGestureRecognizer.delegate = nil;
    }
    [self customViewDidDisappear:animated];
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer

{
    return YES;
}

@end

如果你的scrollview可以横向滑动那么 还需要下面类似的代码

[c.panGestureRecognizer requireGestureRecognizerToFail:self.navigationController.interactivePopGestureRecognizer];


QGCollectionMenu简介

QGCollectionMenu是用在部落的详情页的Tab控件。上次开会说上面header不能滑动的问题已经修正。

控件的界面结构图如下

Written on August 13, 2017