iOS--基础原理笔记

1.事件传递响应机制

1.UITouch 记录手指在屏幕上触摸时产生的一组信息,包含触摸事件,位置等。

2.UIEvent 单次的交互行为,记录事件事件,类型。触摸类还有一组uitouch 事件。

3.事件传递:事件产生后,从UIApplication往下传递,window,view等。pointinside:withEvent:方法,判断点是否在视图内。事件传递给view之后,会调用hitTest:wITHeVENT:方法。

4.响应者链: UIApplication-->UIWindow-->递归找到最合适处理的控件-->控件调用touches方法-->判断是否实现touches方法-->没有实现默认会将事件传递给上一个响应者-->找到上一个响应者-->找不到方法作废

5.适用情景:点击view,view和父view都响应。

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

{
     NSLog(@ "red touches begin" );   //自己的处理
     [ super  touchesBegan:touches withEvent:event];
}
视图绑定了手势识别器,那么touch事件会优先传递给绑定在视图上的手势识别器,然后手势识别器会对手势进行识别,如果识别出了手势,就会调用创建手势时所绑定的回调方法,并且会取消将touch事件继续传递给其所绑定的视图,如果手势识别器没有识别出对应的手势,那么touch事件会继续向手势识别器所绑定的视图传递。
 

 2.UIView && CALayer

  1.定义:UIView : UIResponder;  CALayer : NSObject  所以layer不能响应事件,view可以响应事件。

  2.frame :  layer的frame由position,bounds等决定,view只是返回layer对应的frame。

  3.UIView 主要对显示内容的管理,CALayer 主要侧重显示内容的绘制。  

  4.CALayer 隐式动画。0.25秒,改变属性值时,会平滑的度过。-actionForLayer:forKey: 方法   默认隐含了CABasicAnimation动画实现

 3.分类、类别

  // http://www.cocoachina.com/ios/20180514/23364.html

  实现原理:category_t结构体存放方法、属性、协议等数据,然后将结构体方法列表拷贝到类对象方法列表中。

  分类在运行时加载,实例方法、协议属性添加到类上,类方法添加到元类上

  1.为什么不能添加成员变量:category_t结构体中 无成员变量结构,而类结构体中有_ivar_list_t。在编译时,内存分布已经确定,成员变量存放在实例对象中,而分类中并没有实现get/set方法。

  2.分类中有load方法,并且不会覆盖本类的load方法。先调用类中load,再调用分类中。
  extension: 匿名分类,用于声明私有方法、私有属性、私有成员变量。
 

 4.代理、通知、kvo

  代理: 协议、代理、委托。设置代理,实际上是用id类型指针弱引用对象。

     strong会引起循环引用,assign在对象被释放后,不会将对象置nil,发送消息会产生野指针崩溃,week会置nil,不会崩溃。

   通知: 观察者模式跨层传递消息。 NSNotificationCenter为单例,将观察者注册到调度表中,根据标识符name和object识别出观察者,然后调用相应的方法。
 
       addObserver:selector:name:object: 为同步通知,即要等消息处理之后,才继续之后的代码。
     使用通知队列实现异步通知:NSNotificationQueue   
     NSPostingStyle:发送方式,NSPostWhenIdle,空闲发送;NSPostASAP:尽快发送,当前运行循环完成时;NSPostNow:同步发送
     NSNotificationCoalescing:合并通知,可以保证相同的通知只被发送一次。
 
  KVO:  键值监听。当观察某个对象a时,kvo会动态创建一个a的子类,重写该属性setter方法。NSKVONotifying_A,被观察对象的sia指针指向新类。
     所以使用时必须通过setter方法或则kvc,否则不会触发。
      手动触发:常用是自动触发,设置 +(BOOL)automaticallyNotifiesObserversForKey:(NSString *)key 方法;设置no,则不会触发kvo,在setter方法中调用  willChangeValueForKey:和  didChangevlueForKey:.手动触发。
 

 5.属性关键字

  原子性:atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。

      atomic:系统生成的 getter/setter 会保证 get、set 操作的完整性,不受其他线程影响

      nonatomic:就没有这个保证了,nonatomic返回你的对象可能就不是完整的value。 nonatomic的速度要比atomic的快
 
   retain:    引用计数+1,指针拷贝。
   strong: arc下与retain相同,声明block时,strong等同于copy,retain等同于assign
   assign: 基本数据类型的简单赋值,不更改引用计数,使用之后不会置nil
   week:   弱引用,对象释放后置nil。runtime维护了一个weak哈希表,key是所指对象的地址,value是weak指针的地址数组。代理用weak
   copy:   创建一个新对象,内容拷贝。
        对不可变对象进行copy操作,只是指针复制,mutablecopy是内容复制;
        对可变对象操作,都是内容复制,即深拷贝。
        copy返回的都是不可变对象。
         block 使用copy,block创建时默认在栈区,作用域只在当前上下文,使用copy时,会讲内存移到堆区,就可以在作用域外使用。
 

 6.内存管理

  四个关键字:alloc\new\copy\mutablecopy产生对象就持有对象。

  引用计数: 通过一张散列表管理,键 可以理解为 对象的内存地址;值保存的是 引用计数减一。

  weak表: 全局表,保存所有week引用,对表内对象delloc操作的时候,将指针值设为nil。表中:键 为对象,值为weak_entry_t,保存该对象的所有weak指针。

   获取引用计数: ARC下使用 Runtime _objc_rootRetainCount(id obj)方法获取。
  ARC下内存随时符号:
    __strong:   默认强引用,当没有任何强引用指向时,才会被释放。
     __weak:   弱引用,不影响对象释放,当对象被释放时,所有指向它的弱引用都会被置为nil。当对象被销毁时,会通过他的内存地址,在weak表中查找对应的变量,删除。
          声明__weak后,对象会被自动注册到自动释放池,weak不会对引用计数起变化,可能会在运行过程中被释放,所以将其注册到自动释放池中,并在autoreleasePool销毁时释放对象占用的内存。
          因此,访问__weak修饰的对象,实际上是访问注册到自动释放池的对象,大量使用weak的话,会影响程序性能。
          解决性能:先将其赋给strong变量,再进行访问。
 
    _unsafe_unretain: ios4以前,相当于__weak,纯粹指向对象。
   __autoreleasing:   等同于MRC下调用 autorelease方法。
 
   自动释放池:由一系列的 AutoreleasePoolPage 双向链表组成。 参考这里
         对象调用 autorelease 方法时,会将对象加入 AutoreleasePoolPage 的栈中, objc_autoreleasePoolPush方法,会调用autoreleaseFast(POOL_SENTINEL);方法。
         在每个自动释放池初始化调用 objc_autoreleasePoolPush 的时候,都会把一个 POOL_SENTINEL push 到自动释放池的栈顶,并且返回这个 POOL_SENTINEL 哨兵对象。
        autoreleaseFast方法最终会调用 add(objc)方法,将对象添加到自动释放池中。
        objc_autoreleasePoolPop 方法:最终会调用 objc_release释放对象。
 

 7.Block

    带有自动变量的匿名函数。参考这里

    截获自动变量: 在声明block之后,在内部不能修改局部变量的值。类对象可以修改该对象的属性。

    原理:__main_block_impl_0结构体,将变量已参数的形式传入到了构造函数中,变量被保存在了结构体中,所以不会有变化。

       __block原理: 修饰后变量不再是原类型传入block,而是会变成一个结构体指针__Block_byref_count_0,该结构体保存了变量 和 __forwarding 指针,通过该指针完成对变量的修改。

     循环引用:1.__weak typeof(self) __strong 避免中途释放。2.RAC中 @weakify 和 @strongify。宏定义 3.将内部使用的对象,以参数形式传入 4,使用__block,最后将其置nil。
 
 

 8. GCD

     参考这里
    串行:主队列:dispatch_get_main_queue()
    并发:全剧队列:dispatch_get_global_queue
    1.栅栏方法:dispatch_barrier_async :异步执行两组操作,第一组执行完之后再执行第二组
    2.延时执行:dispatch_after。 并不是在指定时间后开始执行,而是在指定时间之后将任务追加到主队列中。时间并不是准确的
    3.一次性代码: dispatch_once 程序在运行中只执行1次,保证线程安全。
    4.快速迭代: dispatch_apply 按照指定次数将指定的任务追加到队列中。串行队列中 效果等用for循环;并发异步,在多个线程中同时遍历。会等待全部任务执行完毕。
    5.对列组: dispatch_group_async将任务放在队列中,等两个耗时操作都执行完毕之后回到主线程执行任务。dispatch_group_notify 回到主线程。dispatch_group_wait暂停当前线程,等group中任务执行完后,继续往下执行。
          dispatch_group_enter 追加任务到group,dispatch_group_leave 去除任务
 
    NSOperation :封装gcd,面向对象,代码简单可读性高.
    NSOperation  操作,NSOperationQueue 队列。
    主队列:添加到主队列的操作,都会在主线程中执行。
    自定义队列: 会在子线程中执行,包含串行、并发
 

 9.RunLoop

    参考这里

    处理事件循环。一条线程对应一个RunLoop 对象。runloop是一个do-while循环,会监测输入源和定时源 接受事件,然后通知线程处理,在无事件时让线程休眠。

     source,氛围source0 和source1 。source0 主要是uievent,performSelector,等手动触发事件。source1主要是系统内部端口事件
    Timer, NSTimer 定时触发
  
     CFRunLoopModeRef : kCFRunLoopDefaultMode:App的默认运行模式,通常主线程是在这个运行模式下运行
                 UITrackingRunLoopMode:跟踪用户交互事件(用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他Mode影响)
                kCFRunLoopCommonModes 两种模式都被标记
 
     应用: 1.NSTimer   2.imageview 推迟显示,[ self.imageView performSelector:@selector(setImage:) withObject:[UIImageimageNamed:@"tupian"] afterDelay:4.0inModes:NSDefaultRunLoopMode];
        子线程不会主动创建runloop,在手动开启时 会创建  [[NSRunloop currentRunloop] run]
        3.后台常驻线程(下载文件、播放音乐等)        
     

 10.Runtime

    参考这里

    oc 是动态语言,runtime系统使其在运行时执行代码。  

    objc_msgSend 发送消息

    数据结构: typedef struct objc_selector *SEL; SEL 方法选择器,相同名字的方法,即便在不同的类中,选择器相同

          typedef struct objc_object *id; 指向类实例的指针

          isa指针,指向实例对象所属的类,类对象时 指向元类,元类指向根元类,根元类指向自己。

          Method:  方法类型,包括SEL,IMP 等。

          IMP:  函数指针,指向方法的具体实现代码。

     功能: 1.消息转发、重定向 forwardInvocation方法。

         2.method swizzling   class_getInstanceMethod 获得方法, method_exchangeImplementations 交换方法,该方法交换了 两个方法的IMP指针。

           3.关联对象   objc_setAssociatedObject   objc_getAssociatedObject
         4.动态方法:   @dynamic propertyName; 动态修饰属性  +(BOOL) resolveInstanceMethod, 
 
 
 
 

MARK: 学习博客

    1.http://blog.sunnyxx.com sunnyxxx

      2. https://blog.ibireme.com
 
 

转载于:https://www.cnblogs.com/qiangtian/p/9600101.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值