别人问你你都觉得这尼玛在说啥的基础问题

来源:互联网 发布:软件下载lvsexz 编辑:程序博客网 时间:2024/04/27 19:55
  1. UIWindow 和 UIView 和 CALayer 的联系和区别?

    UIView 是视图的基类,UIViewController 是视图控制器的基类,UIResponder 是表示一个可以在屏幕上响应触摸事件的对象;
    UIWindow 是 UIView 的子类,UIWindow 的主要作用:一是提供一个区域来显示 UIView,二是将事件(event)的分发给 UIView,一个应用基本上只有一个 UIWindow.
    UIView 和 CALayer 的父类都是 NSObject.UIResponder 是用来响应时间的,也就是可以使 UIView 相应用户事件.

    CALayer 和 UIView 的区别:

    1.1 UIView 的继承结构为:UIResponder:NSObject.
    CALayer 的继承结构为:NSObject.课件 UIResponder 是用来相应事件的,也就是 UIView 可以响应用户事件.
    CALayer 直接从 NSObject 继承,因为缺少了 UIResponder 类,不能响应任何用户事件.
    1.2 所属框架,UIView是在/System/Library/Frameworks/UIKit.framework中定义的,UIKit 主要是用来构建用户界面,并且是可以响应事件的.CALayer 是在/System/Library/Frameworks/QuartzCore.framework定义的.而且 CALayer 作为一个低级的,可以承载挥之内容的底层对象出现在该框架中.
    1.3 UIView 相比 CALayer 最大却别是 UIView 可以响应用户事件,而 CALayer 不可以.UIView 侧重于对显示内容的管理,CALayer 侧重于内容的绘制.UIView 是基于 CALayer 的高层封装.
    1.4 CALayer 的坐标系系统和 UIView 不太一样,它多了一个锚点(anchorPoint)属性,它使用 CGPoint 结构,但是阈值是0-1.也就是按照比例来设置.这个点是各种图形变换的坐标原点,同时会更改 layer 的 position 的位置,它的缺省值是{0.5,0.5},也就是在 layer 的中央.

    相似之处:1.相似的树形结构 2.显示内容绘制方式 3.布局约束

    UIView 是用来显示内容的,可以处理用户事件.CALayer 是用来绘制内容的,对内容进行动画处理依赖于 UIView来进行显示,不能处理用户事件.

  2. property 都有哪些字段? 他们之间的区别?

    stong,weak,retain,assign,copy nomatic,readonly

    assign:简单赋值,不更改引用计数,.一般用于基础数据类
    copy:建立一个引用计数为1的对象,然后释放旧对象.一般用于 NSString
    retain:释放旧对象,将旧对象的值赋予属于对象,再提高输入对象的引用计数, 一般用于,非 NSString 的其他 NSObject 和其子类

    weak 和strong 的区别:weak 和 strong 不同的是,当一个对象不再有 strong 类型的指针指向它的时候,它会被释放,即使还有 weak 指针指向他.

    copy 与 retain
    copy 是建立了一个相同的对象,而 retain 不是,copy 是内容拷贝,retain 是指针拷贝.但是 copy 当拷贝的是 NSArray 时只是 copy 了指向 array 中相对应元素的指针,这便是所谓的”浅复制”.

    atomic 是 OC使用的一种线程保护技术,基本上来讲,是在多线程操作中方式数据错误的一个机制,这种机制是非常耗费系统资源的,所以在 ios 开发中很少使用.

  3. __block 和__weak 的区别

    __block 不管是在 ARC还是 MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型.
    __weak 只能在 ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int).
    __block 对象可以在 block 中被重新赋值,__weak 不可以

  4. 常见的 HTTP状态码有哪些?

    302:请求重定向. 500以上是服务器错误. 400以上是请求链接错误或者找不到服务器.200以上是正确,100以上是请求成功.常见404.

  5. 单例的写法,在单例中使用数组要注意什么?

static ZQSingleton *sharedSingleton;+(instancetype)shareSinglerton{    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        sharedSingleton = [[ZQSingleton alloc]init];    });    return sharedSingleton;}+(instancetype)alloc{    NSAssert(0, @"这是一个单例对象,请使用+(ZYHPayManager *)sharedMamager方法");    return nil;}+(instancetype)allocWithZone:(struct _NSZone *)zone{    return [self alloc];}-(id)copy{    NSLog(@"这是一个单例对象,copy将不起任何作用");    return self;}+(instancetype)new{    return  [self alloc];}

单例使用 NSMutableArray 的时候,防止多个地方对他同时遍历和修改,需要加原子属性.并且 property 用 strong.

6.static 关键字的作用

函数体内 static 变量的作用范围为该函数体,不同于普通变量,该变量内存只能被分配一次;
在模块内的 static 全局变量可以被模块内所有函数访问,但是不能被模块以外的函数访问;

7.iOS 中的事件的传递 :响应者链

(1)事件分类

对于IOS设备用户来说,他们操作设备的方式主要有三种:触摸屏幕、晃动设备、通过遥控设施控制设备。对应的事件类型有以下三种:

1、触屏事件(Touch Event)

2、运动事件(Motion Event)

3、远端控制事件(Remote-Control Event)

今天以触屏事件(Touch Event)为例,来说明在Cocoa Touch框架中,事件的处理流程。首先不得不先介绍响应者链这个概念:

(2)响应者链(Responder Chain)

先来说说响应者对象(Responder Object),顾名思义,指的是有响应和处理事件能力的对象。响应者链就是由一系列的响应者对象构成的一个层次结构。

UIResponder是所有响应对象的基类,在UIResponder类中定义了处理上述各种事件的接口。我们熟悉的UIApplication、 UIViewController、UIWindow和所有继承自UIView的UIKit类都直接或间接的继承自UIResponder,所以它们的实例都是可以构成响应者链的响应者对象。图一展示了响应者链的基本构成:

这里写图片描述
图一

从图一中可以看到,响应者链有以下特点:

1、响应者链通常是由视图(UIView)构成的;

2、一个视图的下一个响应者是它视图控制器(UIViewController)(如果有的话),然后再转给它的父视图(Super View);

3、视图控制器(如果有的话)的下一个响应者为其管理的视图的父视图;

4、单例的窗口(UIWindow)的内容视图将指向窗口本身作为它的下一个响应者

需要指出的是,Cocoa Touch应用不像Cocoa应用,它只有一个UIWindow对象,因此整个响应者链要简单一点;

5、单例的应用(UIApplication)是一个响应者链的终点,它的下一个响应者指向nil,以结束整个循环。

(3)事件分发(Event Delivery)

第一响应者(First responder)指的是当前接受触摸的响应者对象(通常是一个UIView对象),即表示当前该对象正在与用户交互,它是响应者链的开端。整个响应者链和事件分发的使命都是找出第一响应者。

UIWindow对象以消息的形式将事件发送给第一响应者,使其有机会首先处理事件。如果第一响应者没有进行处理,系统就将事件(通过消息)传递给响应者链中的下一个响应者,看看它是否可以进行处理。

iOS系统检测到手指触摸(Touch)操作时会将其打包成一个UIEvent对象,并放入当前活动Application的事件队列,单例的UIApplication会从事件队列中取出触摸事件并传递给单例的UIWindow来处理,UIWindow对象首先会使用hitTest:withEvent:方法寻找此次Touch操作初始点所在的视图(View),即需要将触摸事件传递给其处理的视图,这个过程称之为hit-test view。

UIWindow实例对象会首先在它的内容视图上调用hitTest:withEvent:,此方法会在其视图层级结构中的每个视图上调用pointInside:withEvent:(该方法用来判断点击事件发生的位置是否处于当前视图范围内,以确定用户是不是点击了当前视图),如果pointInside:withEvent:返回YES,则继续逐级调用,直到找到touch操作发生的位置,这个视图也就是要找的hit-test view。
hitTest:withEvent:方法的处理流程如下:
首先调用当前视图的pointInside:withEvent:方法判断触摸点是否在当前视图内;
若返回NO,则hitTest:withEvent:返回nil;
若返回YES,则向当前视图的所有子视图(subviews)发送hitTest:withEvent:消息,所有子视图的遍历顺序是从最顶层视图一直到到最底层视图,即从subviews数组的末尾向前遍历,直到有子视图返回非空对象或者全部子视图遍历完毕;
若第一次有子视图返回非空对象,则hitTest:withEvent:方法返回此对象,处理结束;
如所有子视图都返回非,则hitTest:withEvent:方法返回自身(self)。

这里写图片描述
图二

加入用户点击了View E,下面结合图二介绍hit-test view的流程:

1、A是UIWindow的根视图,因此,UIWindwo对象会首先对A进行hit-test;

2、显然用户点击的范围是在A的范围内,因此,pointInside:withEvent:返回了YES,这时会继续检查A的子视图;

3、这时候会有两个分支,B和C:

点击的范围不再B内,因此B分支的pointInside:withEvent:返回NO,对应的hitTest:withEvent:返回nil;

点击的范围在C内,即C的pointInside:withEvent:返回YES;

4、这时候有D和E两个分支:

点击的范围不再D内,因此D的pointInside:withEvent:返回NO,对应的hitTest:withEvent:返回nil;

点击的范围在E内,即E的pointInside:withEvent:返回YES,由于E没有子视图(也可以理解成对E的子视图进行hit-test时返回了nil),因此,E的hitTest:withEvent:会将E返回,再往回回溯,就是C的hitTest:withEvent:返回E—>>A的hitTest:withEvent:返回E。

至此,本次点击事件的第一响应者就通过响应者链的事件分发逻辑成功的找到了。

不难看出,这个处理流程有点类似二分搜索的思想,这样能以最快的速度,最精确地定位出能响应触摸事件的UIView。

(4)说明

1、如果最终hit-test没有找到第一响应者,或者第一响应者没有处理该事件,则该事件会沿着响应者链向上回溯,如果UIWindow实例和UIApplication实例都不能处理该事件,则该事件会被丢弃;

2、hitTest:withEvent:方法将会忽略隐藏(hidden=YES)的视图,禁止用户操作(userInteractionEnabled=YES)的视图,以及alpha级别小于0.01(alpha<0.01)的视图。如果一个子视图的区域超过父视图的bound区域(父视图的clipsToBounds 属性为NO,这样超过父视图bound区域的子视图内容也会显示),那么正常情况下对子视图在父视图之外区域的触摸操作不会被识别,因为父视图的pointInside:withEvent:方法会返回NO,这样就不会继续向下遍历子视图了。当然,也可以重写pointInside:withEvent:方法来处理这种情况。

0 0
原创粉丝点击