1、各种 Demo和功能框架
2、大神 GitHub地址 都是干货:大神GitBubble
1》Git全面讲解 教程
0、提升编译速度: iOS - Xcode提高编译速度,增量编译,ccache
1、代理
2、block:内部捕获的局部变量,值拷贝——> 内存地址 不变!同用一个内存地址! 但是 指向该内存的 指针地址 会生成一个新的 指针地址!
——————> block讲解
1、typedef void(^TestBlock)(void);
NSString *test = @"test1111";
NSLog(@"内存地址1:%p 指针地址1: %x",test,&test); // 内存地址1:0x10b654448 指针地址1: e50af2b8
TestBlock b2 = ^(void){
NSLog(@"%@",test); // test1111
NSLog(@"内存地址2:%p 指针地址2: %x",test,&test); }; //内存地址2:0x10b654448 指针地址1: 294c0
test = @"test2222"; b2();
NSLog(@"内存地址3:%p 指针地址3: %x",test,&test); // 内存地址3:0x10b6544c8 指针地址3: e50af2b8
1>什么是 block:block 就是将函数执行上下文封装起来的对象,block的本质就是对象!
2>block 的截获变量特性?
1-【基本数据类型】的局部变量 Block 可以截获其 ”值“(值拷贝)
2-对于【对象类型的局部变量】连同所有权修饰符一起截获 ”浅拷贝“ ——> 内存地址是一样的,指针拷贝
3-【局部静态变量】以 ”指针“ 的形式进行截获
4- 【全局变量和静态全局变量】,block 是不截获的 ——> block 最终调用的时候都是你修改后的值.
3>__block 的理解栈上 block 和堆上 block 的区别?
__block 的理解通过 【__block 修饰的变量】 最终会经系统 编译成为 一个【结构体】,结构体中有一个 isa 指针,和一个值 m 以及 __forwarding 指针,经过修饰以后,我们调用赋值操作其实就会转变为 m._forwarding->m = x,而在 block 内部也会对该__block 对象进行拷贝,故通过__block可以修改被截获变量的值
4>在 MRC和 ARC下有什么需要注意的?
1>全局 Block当我们声明一个block时,如果这个block没有捕获外部的变量,那么这个block就位于全局区,此时对NSGlobalBlock的retain、copy、release操作都无效。ARC和MRC环境下都是如此。
2>栈 Block这里可能有人会问,平时编程的时候很少遇到位于栈区的block,为什么呢?因为在ARC环境下,当我们声明并且定义了一个block,并且没有为Block添加额外的修饰符(默认是__strong修饰符),如果该Block捕获了外部的变量,实质上是有一个从__NSStackBlock__转变到__NSMallocBlock__的过程,只不过是系统帮我们完成了copy操作,将栈区的block迁移到堆区,延长了Block的生命周期。对于栈区block而言,栈block在当函数退出的时候,该空间就会被回收。那什么时候在ARC的环境下出现__NSStackBlock__呢?如果我们在声明一个block的时候,使用了__weak或者__unsafe__unretained的修饰符,那么系统就不会为我们做copy的操作,不会将其迁移到堆区。
3>堆 Block在MRC环境下,我们需要手动调用copy方法才可以将block迁移到堆区,而在ARC环境下,__strong修饰的(默认)block只要捕获了外部变量就会位于堆区,NSMallocBlock支持retain、release,会对其引用计数+1或 -1。声明以及定义位于堆区的block如上图所示。
5>常见循环引用
3、KCO属性监听
4、KVC
5、多线程
1、多线程访问没有加锁处理的属性:会出现访问该属性的值不准确,比如线程4在写入之前是【12】,而此时线程3已经修改了属性为【123】,线程4处理完变成【1234】
2、常驻线程:
self.thread = [[NSThread alloc]initWithTarget:self selector:@selector(run) object:nil]; [self.thread start];
- (void)run{ //只要往RunLoop中添加了 timer、source或者observer就会继续执行,一个Run Loop通常必须包含一个输入源或者定时器来监听事件,如果一个都没有,Run Loop启动后立即退出。
@autoreleasepool {
//1、添加一个input source
[[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode]; [[NSRunLoop currentRunLoop] run]; // 注意!这个run执行后的代码不会执行了!!!!!!
//2、添加一个定时器
// NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(test) userInfo:nil repeats:YES]; // [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; // [[NSRunLoop currentRunLoop] run];
}
}
//利用常驻线程处理事情【如果没有上面的那个监听端口,则这个 action方法不会执行!因为线程执行完就被自动回收释放了!】
[self performSelector:@selector(action) onThread:self.thread withObject:nil waitUntilDone:NO ];
runLoop:高级讲解
6、性能优化
7、数据库
1、数据库升级
2、多线程数据库
8、iOS日志写入和获取
1、使用demo地址
2、日志收集办法
9、单元测试、性能测试
1、系统测试框架:XCTest
网友评论