天天看点

iOS - UIKit相关知识点UIView和Layer的区别UITableView必须实现的delegateframe和bounds++

UIView和Layer的区别

  1. 首先UIView可以响应事件,Layer不可以.

    UIKit使用UIResponder作为响应对象,来响应系统传递过来的事件并进行处理。在 UIResponder中定义了处理各种事件和事件传递的接口。

    UIApplication、UIViewController、UIView、和所有从UIView派生出来的UIKit类(包括UIWindow)都直接或间接地继承自UIResponder类。

    CALayer直接继承 NSObject,并没有相应的处理事件的接口。

    两者最明显的区别是 View可以接受并处理事件,而 Layer 不可以

    UIView主要是对显示内容的管理而CALayer主要侧重显示内容的绘制

  2. UIView是CALayer的delegate(封装映射)
  3. 每个 UIView 内部都有一个 CALayer,也就是说view自带一个layer,这个layer我们叫它根layer。 在背后提供内容的绘制和显示,并且 UIView 的尺寸样式都由内部的 Layer 所提供。 一个View的frame只是简单的各自调用它底层的CALayer的frame,bounds和position方法。两者都有树状层级结构,layer 内部有 SubLayers,View 内部有 SubViews.但是 Layer 比 View 多了个AnchorPoint
  4. CALayer 是默认修改属性支持隐式动画的,在给 UIView 的 Layer 做动画的时候,View 作为 Layer 的代理,Layer 通过 actionForLayer:forKey:向 View请求相应的 action(动画行为)

    对UIView的subLayer(非主Layer)属性进行更改,系统将自动进行动画生成,动画持续时间的缺省值似乎是0.5秒。

  5. layer 内部维护着三分 layer tree,分别是 presentLayer Tree(动画树),modeLayer Tree(模型树), Render Tree (渲染树),在做 iOS动画的时候,我们修改动画的属性,在动画的其实是 Layer 的 presentLayer的属性值,而最终展示在界面上的其实是提供 View的modelLayer
  6. 补充:layer 可以设置圆角显示,例如UIButton的效果,也可以设置阴影显示,但是如果layer树中的某个layer设置了圆角,树中所有layer的阴影效果 都将显示不了了。如果既想有圆角又想要阴影,好像只能做两个重叠的UIView,一个的layer显示圆角,一个的layer显示阴影…
    iOS - UIKit相关知识点UIView和Layer的区别UITableView必须实现的delegateframe和bounds++
CALayer 属性:

   //设置颜色
    tempView.layer.backgroundColor = [UIColor redColor].CGColor;

    //设置边框
    tempView.layer.borderColor = [UIColor orangeColor].CGColor;
    tempView.layer.borderWidth = 5;

     //圆角
    tempView.layer.cornerRadius = 10;

    //设置阴影
    tempView.layer.shadowColor = [UIColor purpleColor].CGColor;
    tempView.layer.shadowOffset = CGSizeMake(20, 20);

    //值越大越模糊
    tempView.layer.shadowRadius = 10;
    tempView.layer.shadowOpacity = 0.5;
    tempView.layer.shadowPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 200, 150)].CGPath;

 	//设置layer的contents 设置图片
	tempView.layer.contents = (__bridge id _Nullable)([UIImage imageNamed:@"me"].CGImage);
           

UIView和CALayer的区别

CALayer和UIView的关系

UITableView必须实现的delegate

UITableViewDelegate的方法有38个

UITableViewDataSource的方法有11个

UITableViewDelegate方法

UITableViewDelegate的38个方法所有的都是可选的(可以实现也可以不实现)

iOS - UIKit相关知识点UIView和Layer的区别UITableView必须实现的delegateframe和bounds++
iOS - UIKit相关知识点UIView和Layer的区别UITableView必须实现的delegateframe和bounds++

UITableViewDataSource方法

UITableViewDataSource的11个方法中有2个是必须实现的

  • (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

  • (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    UITableViewDataSource代理方法
    iOS - UIKit相关知识点UIView和Layer的区别UITableView必须实现的delegateframe和bounds++

执行顺序

#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;


#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;


#pragma mark - Table view data source
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

#pragma mark - Table view delegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;


           

frame和bounds++

iOS - UIKit相关知识点UIView和Layer的区别UITableView必须实现的delegateframe和bounds++

区别

  • frame:该view在父view坐标系统中的位置和大小(参照点是,父亲的坐标系统)
  • bounds:该view在本地坐标系统中的位置和大小(参照点是,本地坐标系统,就相当于ViewB自己的坐标系统,以0,0点为起点)
  • center:该view的中心点在父view坐标系统中的位置和大小。(参照点,父类的坐标系统)
-(CGRect)frame{
    return CGRectMake(self.frame.origin.x,self.frame.origin.y,self.frame.size.width,self.frame.size.height);
}
-(CGRect)bounds{
    return CGRectMake(0,0,self.frame.size.width,self.frame.size.height);
}


           

可以看出,bounds的原点默认是0,0点,就是view本身的坐标系统。而frame的原点却是任意的(相对于父视图中的位置)

bounds属性是参照本地坐标系统来的,每一个view都有一个本地坐标系统。其实本地坐标系统的关键就是要知道他的原点(0,0)在什么位置,通过修改view的bounds属性可以修改本地坐标系统的原点位置。所以,bounds有这么一个特点:它是参考自己坐标系,它可以修改自己坐标系的原点位置,进而影响到”子view“的显示位置。

举例:

UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 200, 200)];
    //[view1 setBounds:CGRectMake(-50, -50, 200, 200)];
    view1.backgroundColor = [UIColor redColor];
    [self.view addSubview:view1];
    NSLog(@"view1 frame:%@======view1 bounds:%@", NSStringFromCGRect(view1.frame), NSStringFromCGRect(view1.bounds));
    
    UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    view2.backgroundColor = [UIColor orangeColor];
    [view1 addSubview:view2];
    NSLog(@"view2 frame:%@======view2 bounds:%@", NSStringFromCGRect(view2.frame), NSStringFromCGRect(view2.bounds));

//输出结果:
2021-08-19 11:53:19.127141+0800 CALayer和UIView[65227:3851739] view1 frame:{{50, 50}, {200, 200}}======view1 bounds:{{0, 0}, {200, 200}}
2021-08-19 11:53:19.127487+0800 CALayer和UIView[65227:3851739] view2 frame:{{0, 0}, {100, 100}}======view2 bounds:{{0, 0}, {100, 100}}
           

底下这句话起到了让view2改变位置的作用:修改了子view的原点

setBounda的作用是:强制将自己(view1)坐标系的左上角改为(-30,-30)。那么view1的原点,自然就向左下方便宜(30,30)

[view1 setBounds:CGRectMake(-50, -50, 200, 200)];

//输出结果:
2021-08-19 11:56:03.494910+0800 CALayer和UIView[65317:3856204] view1 frame:{{50, 50}, {200, 200}}======view1 bounds:{{-50, -50}, {200, 200}}
2021-08-19 11:56:03.495374+0800 CALayer和UIView[65317:3856204] view2 frame:{{0, 0}, {100, 100}}======view2 bounds:{{0, 0}, {100, 100}}
           
iOS - UIKit相关知识点UIView和Layer的区别UITableView必须实现的delegateframe和bounds++

若是我们将view1的bounds改大,例如

[view1 setBounds:CGRectMake(-50, -50, 250, 250)];

//输出结果:
2021-08-19 11:42:04.317671+0800 CALayer和UIView[65060:3842613] view1 frame:{{25, 25}, {250, 250}}======view1 bounds:{{-50, -50}, {250, 250}}
2021-08-19 11:42:04.318008+0800 CALayer和UIView[65060:3842613] view2 frame:{{0, 0}, {100, 100}}======view2 bounds:{{0, 0}, {100, 100}}

           

view1的frame被修改了

frame定义了一个相对父视图的一个框架(容器),bounds则是真实显示区域。如果,bounds比frame小了,可以放到框架(容器)里。如果bounds比frame大,感觉frame被“撑大”了

bounds改变时一中心为轴扩大长宽的。

frame变成了{{25, 25}, {250, 250}}了。25是如何得出的?bounds比frame长,宽各大了50像素,那么四条边平衡一下,各溢出“25”像素。
           

总结

  1. frame不管对位置还是大小,改变的都是自己本身,位置是以父视图坐标系统为参照的(它add到哪个上面) ,大小改变时,左上角不会改变,只是大小发生变化
  2. bounds改变位置时,是相对子系统的坐标位置改变,更改bounds的大小,是中心点不变,长宽进行改变
  3. bounds像是浮于frame之上的。frame是一个框架,bounds是显示子view的东西
  4. 对于bound的point:它不会改变frame的原点,改变的是bounds自己的原点,进而影响到“子view”的显示位置。这个作用更像是移动bounds原点的意思。
  5. 对于bound的size:它可以改变的frame。如果bounds的size比frame的size大。那么frame也会跟着变大,那么frame的原点也会变,但是center不会变。
  6. 看举例吧,举例最直观!笔记本上有。

参考文章