高级进阶点

1、各种 Demo和功能框架

链接地址

VC自定义转场动画

2、大神 GitHub地址 都是干货:大神GitBubble

       0》各种干货demo Demo 、OC全面学习干货

       1》Git全面讲解 教程

       2》在线匹配正则(各种正则匹配公式)

       3》正则表达式讲解1正则表达式讲解2

 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、日志收集办法

推荐阅读更多精彩内容