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.如图 。
当链接成功后左侧栏的右侧会有网络图标。快去试试吧
注意:当你电脑中有两个版本的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不能滑动的问题已经修正。
控件的界面结构图如下