天天看點

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. 看舉例吧,舉例最直覺!筆記本上有。

參考文章