1.逆向
1.利用
Reveal、LookIn
通过图形界面化的形式查看一些竞品或者一些主流APP的UI结构实现。
2.通过CyCript
代码形式查看一些APP的UI结构实现、也可暂时性的修改一些UI显示。
3.利用Clutch、Dumpdecrypted、Frida-ios-dump
对从AppStore下载的APP进行脱壳,推荐使用Frida-ios-dump
、可以脱壳市场上大部分的APP。
4.利用Theos
通过Hook修改APP的功能、并打包生产插件,逆向别人的APP。
5.把逆向过的APP进行重签名、可以打包发布到蒲公英等分发平台供用户使用。
2.RunLoop
RunLoop是通过内部维护的
事件循序
来对事件/消息
进行管理的一个对象。
RunLoop有事做的时候做事、没事做的时候休息。
没事做的时候用户态->内核态
当接收到消息内核态->用户态
image.png image.png image.png怎样实现一个常驻线程?
1.为当前线程开启一个RunLoop。
2.向该RunLoop种添加一个Port/source等维持RunLoop的事件循环。
3.开启该RunLoop
3.Runtime
1.是oc比较底层的一门语言。
2.主要体现在消息传递和消息转发。
image.png
消息传递主要是isa指针和SuperClass指针。
isa指针负责水平方向-实例对象->类对象->元类对象查找对象和方法。
superClass负责垂直方向由子类到父类寻找。
消息转发:
4个函数
image.png
image.png
+ (BOOL)resolveInstanceMethod:(SEL)sel {
// 如果是test方法,打印日志
if (sel == @selector(testMessage)) {
NSLog(@"resolveInstanceMethod:");
return NO;
} else {
// 返回父类的默认调用
[super resolveInstanceMethod:sel];
}
return YES;
}
- (id)forwardingTargetForSelector:(SEL)aSelector {
NSLog(@"forwardingTargetForSelector:");
return nil;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
if (aSelector == @selector(testMessage)) {
NSLog(@"methodSignatureForSelector:");
// v 代表返回值void类型的 @i代表第一个参数的类型是id 即self
// : 代表第二个参数是SEL类型的,即@selector(testMessage)
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
} else {
return [super methodSignatureForSelector:aSelector];
}
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
NSLog(@"forwardInvocation:");
}
如果经过消息传递和消息转发还没有找到对应的方法就会报常见的unrecoginize message的错误
4.RunLoop UI卡顿
介绍下屏幕成像原理:
水平信号之后在一定频率的时间内同步垂直信号,如果在该频率内未能同步垂直信号、则导致屏幕出现卡顿的现象
CPU:
1.尽量使用轻级的对象 用CALayer代替UIView
2.不要频繁的调用view的相关属性,frame,bounds,transform等、尽量减少不必要的修改
3.Autolayout比frame消耗更过的cpu资源
4.图片的Size尽量和UIImageView的大小保持一致
5.把耗时操作放到子线程
GPU:
1.减少视图的层级和数量
2.减少透明的视图(alpha < 0),不透明的设置为opaque = yes
3.尽量避免出现离屏渲染
4.尽量避免短时间内加载多张图片,尽可能将多张图片合成一张显示
5.GPU不能超过其处理的最大纹理
UITableView 性能优化
1.缓存高度
2.异步绘制
3.按需加载
4.设置view的不透明度为YES.(渲染时系统会进行优化操作)
5.减少Cell上面子控件的数量
6.尽量不要动态的去创建Cell的子控件、通过Hidden隐藏或显示
7.刷新数据时,如果只是刷新某个cell或者section,不需要通过[tableView relodatea]来刷新。
8.Cell上存在图片时,尽量不要加载大的图片。通过后台设置多图的形式避免。
9.将负责耗时的操作放到子线程去执行。
10.复杂的页面尽量避免阴影的操作。
11.懒加载
5.强引用和弱引用
强引用:当前对象被其他对象引用时,会执行retain操作,引用计数器+1。当
retainCount=0时,该对象才会被销毁
。因为我们要进行对象的内存管理,所以这是默认的引用方式。(默认是强引用)
弱引用:当前对象的生命周期不由其他对象引用限制,它
本该什么时候销毁就什么时候被销毁
。即使它的引用没断,但是当它的生存周期到了时就会被销毁。
在定义属性时,若声明为retain类型的,则就是强引用;若声明为assign类型的,则就是弱引用。后来内存管理都由ARC来完成后,若是强引用,则就声明为strong;若是弱引用,则就声明为weak。
weak:对象销毁之后会自动置为nil,防止野指针。
weak变量是怎样添加到弱引用表中的?
当使用如下代码
id __weak obj1 = obj;
经过编译之后会变成:
id obj1;
objc_initWeak(&obj1,obj);
一个被声明为__weak的对象指针,经过编译器的编译之后,会调用objc_initWeak()方法,经过一系列的函数调用栈,最终会在weak_register_no_lock()函数中进行弱引用变量的添加,具体添加的位置是通过Hash算法来进行位置查找的,如果查找过程中已经有了当前对象对应的弱引用数组,就把这个新的弱引用变量添加到这个数组中,如果没有的话,就重新创建一个弱引用数组,把这个新的弱引用变量添加到第0个位置,后面的都置为nil。 其中具体的实现过程可以在苹果官网查看相应的源码实现。
清除weak变量,同时设置置为nil
当一个weak 对象被dealloc之后,dealloc内部会去调用弱引用清除的相关函数,然后调用weak_clear_no-lock()函数,根据当前指针查找弱引用表,找到当前对象相对应的弱引用数组,遍历这个数组的所有弱引用指针,分别置为nil.
内存管理:
https://www.jianshu.com/p/f4aabbb72b04
6. Block
1.block有哪几种类型?
__NSGlobalBlock __ ( _NSConcreteGlobalBlock )
__NSStackBlock __ ( _NSConcreteStackBlock )
__NSMallocBlock __ ( _NSConcreteMallocBlock )
代码展示block的三种类型:
int age = 1;
void (^block1)(void) = ^{
NSLog(@"block1");
};
void (^block2)(void) = ^{
NSLog(@"block2:%d",age);
};
NSLog(@"%@/%@/%@",[block1 class],[block2 class],[^{
NSLog(@"block3:%d",age);
} class]);
输出结果:
__NSGlobalBlock __/__NSMallocBlock __/__NSStackBlock __
2.如何判断block是哪种类型?
1.没有访问auto变量的block是__NSGlobalBlock __ ,放在数据段
2.访问了auto变量的block是__NSStackBlock __
3.[__NSStackBlock __ copy]
操作就变成了__NSMallocBlock __
3.在ARC环境下,编译器会根据情况自动将栈上的block复制到堆上的几种情况?
内存布局.png1.block作为函数返回值时
2.将block赋值给__strong指针时
3.block作为Cocoa API中方法名含有usingBlock的方法参数时
4.block作为GCD API的方法参数时
7. 内存管理
内存管理的三种方式
TaggedPointer
NONPOINTER_ISA
散列表
SideTable:
spinlock_t 自旋锁
RefcountMap 引用计数表
weak_table_t 弱引用表
引用计数: 谁创建,谁释放。
MRC:手动引用计数管理
ARC:自动引用计数管理
自动释放池:
什么是自动释放池?
autorelease是一种支持引用计数的内存管理方式,只要给对象发送一条autorelease消息,会将对象放到一个自动释放池中,当自动释放池被销毁时,会对池子里面的所有对象做一次release操作。 如果对象的引用计数>1如何处理
简述自动释放池的原理?
autorelease实际上只是把对release的调用延迟了,对于每一个autorelease,系统只是把该 Object放入了当前的autorelease pool中,当该pool被释放时,该pool中的所有Object会被调用release。
自动释放池的优点是什么?
不用再关心对象释放的时间
不用再关心什么时候调用release
基本使用
1)方法一:
NSAutoreleasePool *autoreleasePool = [[NSAutoreleasePool alloc] init];
Person *p = [[[Person alloc] init] autorelease];
[autoreleasePool release];
2)方法二:
@autoreleasepool {
// 创建一个自动释放池
Person *p = [[[Person alloc]init] autorelease];
} // 销毁自动释放池(会给池子中所有对象发送一条release消息)
8.响应链和事件传递
响应者:
在iOS中,响应者为能响应事件的UIResponder子类对象,如UIButton、UIView等。
响应链:
响应链是由链接在一起的响应者(UIResponse子类)组成的。默认情况下,响应链是由第一响应者,到application对象以及中间所有响应者一起组成的。
事件传递:
获得响应链后,将事件由第一响应者往application传递的过程即为事件传递。
9.子线程的Runloop是默认关闭的
10.深拷贝和浅拷贝
深拷贝:值类型 -拷贝一个新的对象
浅拷贝:引用类型 -拷贝是指针、指向的是同一块内存
strong、copy
1.不可变类型使用strong、如果使用copy的话会发生崩溃。
2.如果引入指向不可变类型的话,使用strong修饰不可变类型是浅拷贝,使用copy修饰不可变类型是深拷贝,一般修饰不可变会选择copy
网友评论