iOS 开发中的一些简单总结

ObjC

属性

  • @property 的本质是生成setter方法和getter方法以及一个带下划线的成员变量,经过autosynthesis添加到类中的。ios

  • 一般的关键字为:objective-c

    • nonatomic & atomicsegmentfault

      这是表明原子性 可是atomic不能彻底保证线程安全 它只保证了setter和getter方法的线程安全,具体的状况:当A线程进行写操做的时候,B线程会等待。当A线程写完,B线程进行写操做,而后A线程读取的将是B线程中的值,若是C线程在A线程读写前将对象release了还会形成程序崩溃api

    • strong & retain数组

      strong至关于ARC下的retain 会强引用对象 使得对象的引用计数加一缓存

    • weak & assign安全

      assign多被用来修饰基本数据类型,是指针赋值,不会对引用计数操做,使用以后不会自动置nil,可能会致使野指针。A对象的指针赋值给B,此时B只是保存了A的指针,不会持有A,因此当A被释放的时候再访问B可能会出现野指针错误。bash

      weak表示弱引用,它既不会设置新值,也不会保存旧值。不会对引用计数操做,当指向的对象被释放以后,自身也会被置nil多线程

    • copy异步

      copy是对对象的引用计数加一,它对应的setter方法不会保存新值,而是将其拷贝一份,一般NSString以及具备可变类型的集合类型可使用copy修饰,拷贝一份出来,以保证不会再使用的过程当中被其余地方的操做所改变

      block也使用copy来修饰,这是MRC遗留下的传统,提示开发者block是从栈上复制到堆上的。

    • readwrite&readonly

      读写,只读

    • setter= & getter=

      指定setter方法和getter方法

    • 默认

      基本数据类型默认是assign, atomic,readwirte

      对象类型strong,atomic, readwrite

@synthesize 自动生成setter getter方法

@dynamic不须要编译器生成,手动生成

默认是@synthesize var = _var

对象copy

  • 拷贝的本质是生成一份独立的副本

  • 对不可变对象来讲 copy是浅拷贝,由于该对象自己就是不可变的了。而mutablecopy是深拷贝由于须要拷贝出来一份可变的对象,因此须要进行深拷贝,拷贝内存中的内容。

  • 对可变对象来讲,copy和mutable拷贝都是深拷贝,copy生成的对象是不可变的,mutablecopy会生成可变对象

copy & mutableCopy

  • 自定义对象想要进行copy操做须要实现NSCopying协议

    • 实现copyWithZone或者mutableCopyWithZone方法

      - (id)copyWithZone:(NSZone *)zone {
          Person *p = [[Person allocWithZone:zone] init];
          //属性也要拷贝赋值
          p.name = [self.name mutableCopy];
          p.age = self.age;
          return p;
      }
      复制代码
    • 若是Person中有其余自定义对象,那么该自定义对象也须要实现遵循并实现 NSCopying协议。

类和对象

  • NSObject 实例本质是一个结构体
  • NSObect对象的大小是一个C语言结构体的大小
  • 实例对象的isa指针指向类对象,类对象的isa指向元类对象。
  • 每一个类中只有一个类对象,类对象中存放了对象的方法列表,协议列表等本质是一个object_class结构体
  • 每个类中只有一个元类对象,元类对象的结构跟类对象是同样只不过用途不同。能够经过 runtime 的 class_isMetaClass 来验证某个类是否是元类,其本质是一个 objc_class 的结构体。
  • 有继承关系的对象的结构体中存放着其父类的结构体

+ initialize 与 +load

  • 调用时机
    • + initialize第一次初始化这个类以前调用,咱们经常使用来初始化静态变量,是runtime负责的。
    • +load 方法会在加载类的时候就被调用,也就是 ios 应用启动的时候,就会加载全部的类,就会调用每一个类的 + load 方法。load经过指针直接找到函数地址直接调用没有经过消息机制
  • 大量使用load会致使App启动速度变慢

Category

可使用Category为类添加新方法,使用Category为类添加新方法在必定程度上比使用继承添加方法的释放耦合度低。

category是不支持直接使用属性的,能够经过runtime的属性绑定来实现。声明一个属性,实现setter和getter方法。在setter方法中使用objc_setAssociatedObject第二个参数标记能够用``@selector([getter method name]),getter方法中使用objc_getAssociatedObject获取属性值,第二个参数使用_cmd`

category 中实现的方法是在运行时添加到类中的。category是按照编译顺序排列的,因此后编译的cat中取出的方法、属性和协议列表,分别放在mlist、proplists和protolists的最前面。

Block

block的本质是封装了函数调用和函数调用环境的OC对象

  1. Block对变量的捕获:

    • auto变量 值捕获
    • static 引用捕获
    • 全局变量不会捕获
  2. block类型

    MRC下 当block访问了auto类型变量的时候是stackblock 其余状况下是globalblock

    ARC下会将stackblock从栈上copy到堆上,固然这是编译器帮咱们作的

  3. ARC下的block会在一下状况自动调用copy方法

    • block做为返回值的时候
    • 当block被强指针引用的时候
    • cocoa api中 做为usingBlock 或者GCD的参数的时候
  4. 对象类型的捕获

    • 会根据对象的修饰词对变量进行retain或者弱引用,当block从堆中移除的时候对应的dispose方法释放对象
  5. __weak

    ARC下一般使用__weak来解决block的循环引用问题,使用它修饰的对象在被block捕获的时候,在block内部也会使用__weak来修饰,而使用__weak修饰的对象会被弱引用。

  6. __block

    在block内部修改auto变量的时候一般会报错,这个时候须要使用__block修饰。__block修饰的变量,在block内部会生成一个结构体,结构体中存放有isa指针__forwarding指针,变量等信息,当改变变量的值得时候会经过__forwarding指针找到这个结构体,改变其中变量的值。

KVO KVC

  1. KVO是键值监听,当对一个对象进行KVO的时候,runtime会建立一个新的对象做为以前对象的子类,这个子类中重写了变量的setter方法,class方法和dealloc方法,调用Foundation中的_NSSetIntValueAndNotify函数,它会在赋值以前调用willChangeValueForKey,以后调用didChangeValueForKey来监听值得改变。
  2. KVC是键值编码
    • 设置值的时候会按照setKey,_setKey的顺序查找setter方法,若是找到则直接调用设置值,找不到则查看+ (BOOL)accessInstanceVariablesDirectly方法的返回值,若是返回值是NO则调用setValue:forUndefinedKey方法,若是没有实现会抛出异常。若是是YES,则会按照_key,_isKey,key,isKey的顺序查找成员变量赋值
    • 获取值的时候会按照getKeykeyisKey_key的顺序查找对应的方法,若是找到则展开调用,若是找不到那么查看+ (BOOL)accessInstanceVariablesDirectly返回值,YES的话会按照_key,_isKey,key,isKey的顺序查找成员变量,返回NO的话就会调用- (id)valueForUndefinedKey:(NSString *)key,若是没有实现会抛出异常
    • + (BOOL)accessInstanceVariablesDirectly默认为YES

内存

iOS 使用引用计数的方式管理内存,内存管理的原则是谁建立,谁释放 。 谁引用,谁管理

使用new、alloc、copy或者mutable copy,引用计数为初始值1,再使用retain的话,引用计数为+1,使用release或者autorelease会使引用计数-1。

自动释放池,OC对象调用autorelase方法以后,会将对象放到离本身最近的自动释放池内,Run Loop在每一个事件循环结束后会去自动释放池,会将释放池内全部的对象都作一次release操做。

MRC下的setter方法

先释放旧值再引用新值

- (void)setAge:(NSString *)age {
		if (_age != age) {
      	[_age release];
      	[age retain];
        _age = age;
		}
}
复制代码

循环引用

  • Block
  • NSTimer
  • self 加到array中
  • delegate

多线程

iOS的多线程方案:

  1. GCD :GCD中有四种队列:主队列、串行队列、并行队列、全局队列。全局队列是一种特殊的并行队列,它没有标识。同步只能在当前线程中执行,不会开辟新线程,且都是串行执行任务。异步线程在主队列中不会建立线程,在并行队列中会开启新线程并行执行任务,串行队列会建立线程串行执行任务。
  2. 线程间通讯可使用performSelector:onThread...
  3. 队列组
  4. NSOperation 是GCD的OC封装,它是一个抽象类,不能直接使用,须要使用其子类。NSOperation能够提供 OC Api操做线程,还能够指定依赖关系,而且可使用KVO监放任务的执行状况
  5. 信号量
    • OSSpinLock 自旋锁,会处于忙等的状态
      • OSSpinLock & OSSpinUnLock
    • os_unfair_lock 用来代替OSSpinLock 属于互斥锁会进入休眠状态
      • os_unfair_lock_lock & os_unfair_lock_unlock
    • pthread_mutex 属于pthread的api
      • 递归锁 & 条件锁
    • NSLock 对 pthread_mutex的封装
    • @synchronized 对mutex递归锁的封装
    • dispatch_barrier_async 要求线程必须是dispatch_queue_cretate建立的,读写操做的时候可使用栅栏函数隔离写操做。

runtime

  • 更换系统字体
  • 为category添加属性
  • 字典转模型
  • NSCoding协议

objcMsgSend

首先会在方法缓存中查找方法的实现,若是没有找到则查找父类的实现,父类没有实现会进入动态方法解析,为该类添加一个方法的实现。若是动态方法解析尚未实现,那么会进入消息转发,将消息转发给一个能够相应该方法的target。若是这一步尚未实现则会进行方法签名,返回一个方法签名,并调用forwardInvacation返回一个target处理该消息,若是尚未实现则会报方法找不到错误。

runloop

  1. 首先会通知监听者Observers:即将处理Timers

  2. 通知监听者Observers:即将处理Sources

  3. 处理blocks

  4. 处理source0,若是处理完了会再次处理blocks

  5. 若是存在source1,则跳到handle_msg处理,若是没有则通知监听器即将进入休眠

  6. 休眠时期等待消息来唤醒当前线程

  7. 若是有消息唤醒则进入handle_msg处理计时器,gcd,source1这些信息

  8. 再次处理blocks

  9. 获取返回值retVal

  10. 进入do-while(),若是retVal == 0 则循环持续进行。不然返回给CFRunLoopRunSpecific函数,退出RunLoop

UI

UITableView

  1. 优化
    1. 尽可能不要使用透明的颜色
    2. 不要动态的添加控件
    3. 注意重用id
    4. 在model中缓存高度
    5. 尽可能一次将控件添加到cell上使用hidden来控制显隐
    6. 圆角处理避免离屏渲染
  2. 重用机制
    1. 首先会按照屏幕显示建立cell,存放在visiableCells数组中
    2. 滑动出屏幕的cell会放到reuseableCells的数组中,从visiableCells中移除
    3. 重用的时候回检查reuseableCells中是否有相同id的cell
  3. reload
    1. reloadData:猜想是将visiableCells中全部cell移入reusableTableCellsvisiableCells清空。cellForRowAtIndexPath调用后,再把reuse的cell从reusableTableCells取出来,放入到visiableCells
    2. reloadRowsAtIndex: 若是调用时reusableTableCells为空,那么cellForRowAtIndexPath调用后,是新建立cell,新的cell加入到visiableCells。老的cell移出visiableCells,加入到reusableTableCells

响应者链

iOS响应者链完全掌握

其余

HTTP&HTTPS

  1. client向server发送请求https://baidu.com,而后链接到server的443端口。

  2. 服务端必需要有一套数字证书,能够本身制做,也能够向组织申请。区别就是本身颁发的证书须要客户端验证经过,才能够继续访问,而使用受信任的公司申请的证书则不会弹出提示页面,这套证书其实就是一对公钥和私钥。

  3. 传送证书 这个证书其实就是公钥,只是包含了不少信息,如证书的颁发机构,过时时间、服务端的公钥,第三方证书认证机构(CA)的签名,服务端的域名信息等内容。

  4. 客户端解析证书 这部分工做是由客户端的TLS来完成的,首先会验证公钥是否有效,好比颁发机构,过时时间等等,若是发现异常,则会弹出一个警告框,提示证书存在问题。若是证书没有问题,那么就生成一个随即值(秘钥)。而后用证书对该随机值进行加密。

  5. 传送加密信息 这部分传送的是用证书加密后的秘钥,目的就是让服务端获得这个秘钥,之后客户端和服务端的通讯就能够经过这个随机值来进行加密解密了。

  6. 服务段加密信息 服务端用私钥解密秘密秘钥,获得了客户端传过来的私钥,而后把内容经过该值进行对称加密。

  7. 传输加密后的信息 这部分信息是服务端用私钥加密后的信息,能够在客户端被还原。

  8. 客户端解密信息

    客户端用以前生成的私钥解密服务端传过来的信息,因而获取了解密后的内容。

上述文字出自HTTP和HTTPS协议,看一篇就够了

源码

相关文章
相关标签/搜索