本网站(662p.com)打包出售,且带程序代码数据,662p.com域名,程序内核采用TP框架开发,需要联系扣扣:2360248666 /wx:lianweikj
精品域名一口价出售:1y1m.com(350元) ,6b7b.com(400元) , 5k5j.com(380元) , yayj.com(1800元), jiongzhun.com(1000元) , niuzen.com(2800元) , zennei.com(5000元)
需要联系扣扣:2360248666 /wx:lianweikj
iOS中的事件响应链、单例模式、工厂模式、观察者模式
iamitnan · 903浏览 · 发布于2020-05-14 +关注

欢迎关注我的iOS学习总结——每天学一点iOS:https://github.com/practiceqian/one-day-one-iOS-summary

iOS中事件传递和相应机制

  1. iOS中的事件(主要有三类)

    • 触摸事件(touch Event)

    • 运动/加速计事件(motion Event)

    • 远程控制事件(remote-control Event)

  2. UIResponder(响应者对象)

    • //UIResponder类提供了以下四个对象方法来处理触摸事件
      - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
      - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
      - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
      - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
    • iOS中只有继承了UIResponder的类才能接收并处理事件,称之为响应者对象。

    • 为什么继承了UIResponder的类都能够接收并处理事件呢?

  3. 事件响应链

    • UIWindow->UIView->UIResponder

    • UIApplication->UIResponder

    • 可以通过[responder nextResponder]找到当前responder的下一个responder,持续这个过程,最后会找到UIApplication对象

    • 通常情况下,在first responder(即用户所点击的view)就会处理事件请求,进入事件分发机制

    • 所有处理事件响应的类都是UIResponder的子类,响应者链是一个由不同对象组成的层次结构,其中的每个对象依次获得响应事件消息的机会,事件将沿着响应者链一直向下传递,直到该事件被接收并且处理

    • 事件的传递和响应链

      //事件传递是从第一响应者->UIApplication
      View->ViewController->UIWindow->UIApplication->nil
      //事件的响应是从UIApplication->FirstResponder
      UIApplication->UIwindow->ViewController->View
    • 几种继承关系

  4. 事件分发机制

    • UIView的userInteractionEnabled设置为NO(不可交互)

    • UIView的hidden设置为YES(隐藏了UIView,父控件隐藏的话子控件也会被隐藏)

    • alpha透明度<0.01(0~0.01)为透明

    • 调用pointInside:withEvent:方法判断触摸点是否在当前视图内

    • 如果返回no,则hitTest方法返回nil,如果返回yes,则向当前视图的所有子视图发送hitTest:withEvent消息

    • 如果第一次有子视图返回非空对象,那么UIWindow对象调用的histTest:withEvent(UIWindow继承自UIView,UIView含有hitTest方法)方法返回该对象,如果所有的子视图都返回nil,那么histTest:withEvent方法返回自身

    • 第一响应者指的是当前接受触摸的响应者对象(通常是一个UIView对象),表示当前对象正在与用户进行交互,它是响应链的开端,响应链和事件分发机制都是为了找出第一响应者

    • 当发生触摸操作后,系统会将该操作打包成一个UIEvent对象,并将其放入当前活动Application的事件队列(队列的特点是先进先出,先发生的事件先处理)

    • UIApplication会从事件队列中取出事件并将其分发给当前应用的UIWindow对象

    • UIwindow对象首先会使用hitTest:withEvent:方法寻找该触摸事件发生时所在的视图,histTest->view

    • hitTest:withEvent:方法的处理流程

    • 如果histTest:withEvent方法没有找到第一响应者或者第一响应者没有处理该事件,那么该事件就会沿着响应者链向上回溯,如果UIWindow对象和UIApplication对象都不能处理该事件,那么该事件就会被丢弃。

    • 如果对事件响应需要有特殊的操作,那么可以重写hisTest:withEvent方法来实现

    • UIView(或者继承自UIView的子类)不能接收触摸事件的三种情况

  5. UIApplication的几种状态

    • not Running(程序未启动状态)

    • Inactive(未激活)程序在前台运行,但是没有接收到事件,在没有事件需要处理的情况下程序通常处于这个状态

    • active(激活)程序在前台运行,并且接收到了事件

    • Background(后台),程序在后台运行并且可以执行代码,大多数程序挂起到后台都会在这个状态停留一会,一段时间后会进入挂起(Suspended)状态,经过特殊处理的请求可以长期处于这个状态。

    • Suspended(挂起),程序在后台运行但是不能执行代码,系统自动把程序变成这个状态并且不会发出通知,但是还在内存中运行,当系统遇到内存压力时,就会自动将程序从内存中清除,为前台程序提供更多的内存。

iOS中的设计模式

  1. 设计原则

    • 尽量使用合成/聚合,在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分,新的对象通过对这些对象的委派达到复用已有功能的目的(尽量使用合成/聚合,不要使用继承)

    • 一个对象对另一个对象了解的越多,那么他们的耦合度就越高,当修改一个对象时,对另一个对象的影响就越大(一个对象应该对另一个对象保持最少的了解,尽量实现低耦合高内聚)

    • 高层模块不应该依赖底层模块,二者都应该依赖其抽象,抽象不应该依赖细节,细节应该依赖抽象

    • 对象不应被强迫依赖它不使用的方法

    • 子类可以扩展父类的方法,但不应该重写父类的方法

    • 对软件实体的修改,最好使用扩展而非直接修改的方式

    • 对类,函数,如果需要修改,尽量采用继承的方式来扩展类的功能,而不是直接修改类的代码(如果工程不是特别复杂的情况下,那么直接修改类的代码也可以)

    • 一个类只承担一个职责,如果一个类拥有了两种职责,那么需要考虑是否将这个类拆分开来,比如UITableViewCell,如果有多重样式的cell,那么我们应该考虑的是分成几种类型的cell去写,而不是在一个cell中实现多种类型

    • 单一职责原则

    • 开闭原则

    • 里式替换原则

    • 接口隔离原则

    • 依赖倒置原则

    • 迪米特法则

    • 组合/聚合复用原则

  2. iOS开发中几种常用的设计模式

    • 使用NSNotification通知实现

    • 使用KVO(key,value,observer)键值观测实现

    • 类A接口为文件中创建协议,声明@requeired和@optional方法

    • 类A添加一个属性,使用weak修饰(否则会造成循环引用)

      @property (nonatomic,wead) id<协议名>delegate

    • 类B接口文件/类扩展中遵守协议,并在实现文件中实现协议的required/optional方法

    • 类B中创建一个类A对象,类A对象的delegate设置为self(类B自身)

    • 在类A对象中调用[self.delegate 方法]

    • //一个工厂类需要执行多个方法,可以将每个方法衍生出一个类继承自这个工厂类,实例化工厂类时根据传入的参数创建对应方法的实例
      @implementation OperationFactory
      
      + (Operation *) createOperat:(char)operate{
          Operation *oper = nil;
          switch (operate) {
              case '+':
              {
                  oper = [[OperationAdd alloc] init];
                  break;
              }
              case '-':
              {
                  oper = [[OperationSub alloc] init];
                  break;
              }
              case '*':
              {
                  oper = [[OperationMul alloc] init];
                  break;
              }
              case '/':
              {
                  oper = [[OperationDiv alloc] init];
                  break;
              }
              default:
                  break;
          }
          return oper;
      }
      @end
    • //使用@synchronized保证线程安全的懒加载写法,但是由于@synchronized是互斥锁导致性能比较低
      + (Singleton *)sharedInstance { 
          @synchronized (self) {
              if (!instance) { 
                  instance = [[Singleton alloc] init];
              } 
          }
          return instance; 
      }
      //使用GCD中的dispatch_once写法,同时满足了线程安全和静态分析器的要求
      + (Singleton *)sharedInstance { 
          static dispatch_once_t predicate;
          dispatch_once(&predicate, ^{
              instance = [[Singleton alloc] init];
          });
          return instance; 
      }
    • 以上两种单例模式的实现都不能保证SingleTon是唯一的,因为通过[[Single alloc]init]方式创建仍然会创建出新的实例

    • 创建绝对单例的方法

      //通过拦截alloc方法来创建绝对单例
      //new->alloc
      //alloc->allocWithZone
      //alloc方法的内部就是调用了allocWithZone方法,allocWithZone方法的作用就是申请空间创建对象并将创建的对象返回。
      + (instancetype)shareInstance
      {
          if (instance == nil) {
              static dispatch_once_t once;
              dispatch_once(&once, ^{
                  instance = [[Singleton alloc] init];
              });
          }
          return instance;
      }
      
      + (instancetype)allocWithZone:(struct _NSZone *)zone
      {
          if (instance == nil) {
              static dispatch_once_t onceToken;
              dispatch_once(&onceToken, ^{
                  instance = [super allocWithZone:zone];
              });
          }
          return instance;
      }
    • 单例模式(两种实现方法)

    • 工厂模式

    • 委托模式(这里只列出使用步骤,A为委托对象,B为代理对象)

    • 观察者模式(两种方式)

 

相关推荐

android下vulkan与opengles纹理互通

talkchan · 1158浏览 · 2020-11-23 10:37:39
Android 使用RecyclerView实现轮播图

奔跑的男人 · 2166浏览 · 2019-05-09 17:11:13
微软发布新命令行工具 Windows Terminal

吴振华 · 860浏览 · 2019-05-09 17:15:04
Facebook 停止屏蔽部分区块链广告

· 746浏览 · 2019-05-09 17:20:08
加载中

0评论

评论
分类专栏
小鸟云服务器
扫码进入手机网页