最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

IOS開發(fā)自定義view方法規(guī)范示例

 更新時間:2022年07月19日 15:44:24   作者:賣報的小畫家Sure  
這篇文章主要為大家介紹了IOS開發(fā)自定義view方法規(guī)范示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

對于接觸業(yè)務開發(fā)的童鞋,自定義View的開發(fā)是進行最頻繁的工作了。但發(fā)現(xiàn)一些童鞋還是沒有以一個好的規(guī)范甚至以一種錯誤的方式來搭建UI控件。由此,本文將以以下目錄來進行講敘,詳細描述關于自定義View的一些書寫注意事項。

  • 關于自定義View的初始化方法
  • 關于addSubview
  • 關于layoutSubviews
  • 關于frame與bounds

一、關于自定義View的初始化方法

通常我們會創(chuàng)建私有方法createUI方法來創(chuàng)建當前自定義View所需要的子View。那上述所說的createUI應該放在自定義View的哪個方法中呢?

1、init?

2、initWithFrame?

3、還是為了考慮外部創(chuàng)建自定義View的方式不同,在init與initWithFrame方法中均調用createUI方法?

我們來一一驗證,首先在CustomView的init方法中調用createUI方法。

- (instancetype)init {
    if (self = [super init]) {
        [self createUI];
    }
    return self;
}
- (void)createUI {
    [self addSubview:self.testView];
}
- (UIView *)testView {
    if (!_testView) {
        _testView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
        _testView.backgroundColor = [UIColor redColor];
    }
    return _testView;
}

外部以init形式創(chuàng)建CustomView

CustomView *customView = [[CustomView alloc] init];
customView.frame = CGRectMake(100, 100, 200, 200);
customView.backgroundColor = [UIColor lightGrayColor];
[self.view addSubview:customView];

可驗證,CustomView與其子視圖均可正常顯示。但有個問題是,如果外部以initWithFrame形式創(chuàng)建,無法調用createUI方法,因此子視圖無法顯示。

第二種初始化形式,單獨在initWithFrame方法中調用createUI方法

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self createUI];
    }
    return self;
}

可驗證結果是,無論外部以init或者initWithFrame方法初始化CustomView,均可以正常顯示CustomView與其子視圖。

最后我們做個實驗,在init與initWithFrame方法中均調用createUI方法。調試createUI方法調用次數(shù)。

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self createUI];
    }
    return self;
}
- (instancetype)init {
    if (self = [super init]) {
        [self createUI];
    }
    return self;
}
- (void)createUI {
    NSLog(@"SubViews Add");
    [self addSubview:self.testView];
}
- (UIView *)testView {
    if (!_testView) {
        _testView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
        _testView.backgroundColor = [UIColor redColor];
    }
    return _testView;
}
@end

外部創(chuàng)建CustomView仍使用init形式 通過打印結果或斷點可驗證createUI方法被執(zhí)行了兩次!

2019-06-26 17:17:51.961744+0800 TestAddSubview[72346:1989647] SubViews Add
2019-06-26 17:17:51.961917+0800 TestAddSubview[72346:1989647] SubViews Add

其實,上述三種假設均和一個問題相關,即自定義View的init方法是否會默認調用initWithFrame方法。

答案是肯定的,通過上述的代碼調試流程,我們可以得到如下結論,關于代碼的調用過程(以外部初始化init為例):

1、動態(tài)查找到CustomView的init方法

2、調用[super init]方法

3、super init方法內部執(zhí)行的的是[super initWithFrame:CGRectZero]

4、若super發(fā)現(xiàn)CustomView實現(xiàn)了initWithFrame方法

5、轉而執(zhí)行self(CustomView)的initWithFrame方法

6、最后在執(zhí)行init的其余部分

這里也可以驗證一個結論:OC中的super實際上是讓某個類去調用父類的方法,而不是父類去調用某個方法,方法動態(tài)調用過程順序是由下而上的(這也是為什么只在init方法中進行createUI不會執(zhí)行多次的原因,因為父類的initWithFrame沒做createUI操作)。

結論: createUI方法最好在initWithFrame中調用,外部使用init或initWithFrame均可以正常執(zhí)行createUI方法。不要在自定義View中同時重寫init與initWithFrame并執(zhí)行相同視圖布局代碼。會導致布局代碼(createUI)執(zhí)行多次。

二、關于addSubview

我們接著問題一自定義View的初始化方法來說,如果同時在init與initWithFrame中同時調用了createUI方法,會有什么影響呢?

顯而易見的是createUI方法執(zhí)行了多次,也就是說重復多次添加了self.testView。那是否會重復添加多個View層呢?

并不會,重復多次添加同一個View并不會產生多層級的情況。 我們看下addSubview的文檔描述

This method establishes a strong reference to view and sets its next responder to the receiver, which is its new superview. Views can have only one superview. If view already has a superview and that view is not the receiver, this method removes the previous superview before making the receiver its new superview.

大概闡述的意思是,View有且僅有一個父視圖,如果新的父視圖與原父視圖不一樣,會將View在原視圖中移除,添加到新視圖上。

因此同一父視圖重復添加同一個View并不會產生多層級。 可以簡單通過代碼驗證,我們在createUI中循環(huán)添加self.testView,最終打印當前視圖的子視圖個數(shù)

- (void)createUI {
    for (NSInteger i = 0; i < 100; i++) {
        [self addSubview:self.testView];
    }
    NSLog(@"subviewsCount = 【%ld】",self.subviews.count);
    for (UIView *view in self.subviews) {
           NSLog(@"subView 【%@】",view);
    }
}

運行可見,視圖的子視圖個數(shù)始終為1

2019-06-28 16:02:50.420144+0800 TestAddSubview[78991:832644] subviewsCount = 【1】
2019-06-28 16:02:50.422151+0800 TestAddSubview[78991:832644] subView 【<UIView: 0x7f80a9c09590; frame = (0 0; 100 100); layer = <CALayer: 0x600003ff0a40>>】

根據打印結果可驗證,CustomView始終只存在一個子視圖(testView)。

新舊父視圖一致,我們可以假設蘋果做了如下處理:

1、在舊父視圖中移除子視圖,再重新將子視圖添加到父視圖上

2、判斷新舊父視圖是否一致,若一致,不做任何操作。

因為無法看到addSubview的源碼,猜測可能會有這兩種情況,個人更偏向第二種處理。(可重寫子視圖layoutSubviews方法,因為addSubviews會調用layoutSubviews方法,我們可以調試layoutSubviews的調用次數(shù),測試后可驗證addSubviews做了上述二的處理)

結論:若父視圖重復添加同一子視圖,并不會產生多層級情況。因為此例中testView是以懶加載的形式創(chuàng)建,所以self每次添加的均為同一個View,但如果在createUI中以UIView *testView = [UIView alloc] initWithFrame的形式創(chuàng)建,那就會創(chuàng)建出多層級的View。

總結:自定義View的子視圖最好以懶加載形式創(chuàng)建,可避免因其他書寫不當導致的異常

三、關于layoutSubviews

關于這一點,主要想聊一聊layoutSubviews的調用時機

1、setNeedsLayout\ layoutIfNeeded

2、addSubview

3、View的大小發(fā)生變化,未變不調用

4、UIScrollView滑動

5、旋轉Screen會觸發(fā)父UIView上的layoutSubviews事件

因此對于layoutSubviews的使用我們需要注意以下幾點:

1、自定義視圖的init方法并不會調用layoutSubviews

2、蘋果聲明不要直接調用layoutSubviews方法,如果需要更新,應該調用setNeedsLayout方法,視圖會在下一次繪制后更新。如果需要立即更新視圖,需要執(zhí)行l(wèi)ayoutIfNeeded方法

3、因為layoutSubviews調用比較頻繁,因此若無特殊需求(文檔所述為執(zhí)行精確的子視圖布局時可使用),不用重寫layoutSubviews方法。

四、關于frame與bounds

眾所周知,在iOS UI控件中有兩個關于位置大小的非常重要的屬性,frame與bounds

UI控件的frame意為相對于該控件父視圖的位置,bounds意為相對于控件本身的位置。 frame、bounds均為結構體CGRect,由CGPoint與CGSize組成,我們可以通過 frame.origin/bounds.origin 與frame.size/bounds.size來進行返回控件左上角位置與大小。

通常給View添加動畫,可以直接操作Frame或者得到Layer設置隱式動畫。

那如果我們直接操作View的bounds會有什么情況出現(xiàn)呢?

有如下例子,有三個View,分別為RedView、BlueView、GreenView,RedView添加在當前視圖控制器上,BlueView為RedView的子視圖,GreenView為BlueView的子視圖,坐標分別為(10,10,200,200)、(10,10,150,150)、(10,10,100,100),其坐標位置如下圖所示:

若修改BlueView的bounds為(0,10,150,150),那么會有什么情況出現(xiàn)呢?

可能我們通常移動View不會通過bounds而是frame,并且也知道bounds是相對于自身的坐標,修改其origin不會對其本身產生什么影響,但這就大錯特錯了,我們來看此情況的結果,三個View的展示情況變成了下圖所示:

BlueView位置并沒有什么變化,GreenView卻因為BlueView的修改,其位置上移了10坐標點!

我們來看下原因,因為調整里BlueView的bounds,導致BlueView相對于自己的坐標上移了10坐標點,GreenView相對于其父視圖的位置也同樣上移了10坐標點。對于GreenView,他的父視圖BlueView的左上角已經不是(0,0),而是(0,10),因此會有上圖的結果。

總結

在CustomView中盡量使用frame來做某些操作,不出于特殊需求,不要修改bounds的origin屬性,會造成難以預期的Bug。(不會影響當前視圖,但是會間接影響其子視圖)

以上就是IOS開發(fā)自定義view方法規(guī)范示例的詳細內容,更多關于IOS開發(fā)自定義view的資料請關注腳本之家其它相關文章!

相關文章

  • iOS保存App中的照片到系統(tǒng)相冊或自建相冊的方法

    iOS保存App中的照片到系統(tǒng)相冊或自建相冊的方法

    這篇文章主要介紹了iOS保存App中的照片到系統(tǒng)相冊或自建相冊的方法,示例代碼為傳統(tǒng)的Objective-C語言寫成,需要的朋友可以參考下
    2016-04-04
  • IOS開發(fā)OC代碼中創(chuàng)建Swift編寫的視圖控制器

    IOS開發(fā)OC代碼中創(chuàng)建Swift編寫的視圖控制器

    這篇文章主要介紹了IOS開發(fā)OC代碼中創(chuàng)建Swift編寫的視圖控制器的相關資料,需要的朋友可以參考下
    2017-06-06
  • iOS如何封裝帶復制功能的UILabel示例代碼

    iOS如何封裝帶復制功能的UILabel示例代碼

    如果是在IOS的應用方面,很多時候我們需要封裝UILabel,下面這篇文章主要給大家介紹了關于iOS如何封裝帶復制功能的UILabel的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2018-08-08
  • 詳解iOS自定義UITabBar與布局

    詳解iOS自定義UITabBar與布局

    本篇文章給大家詳細分析了iOS自定義UITabBar與布局的實際操作過程以及相關代碼分享,一起學習下。
    2018-02-02
  • Objective-C中編程中一些推薦的書寫規(guī)范小結

    Objective-C中編程中一些推薦的書寫規(guī)范小結

    這篇文章主要介紹了Objective-C的一些編程書寫規(guī)范小結,包括類與方法等面向對象編程相關的代碼編寫風格,需要的朋友可以參考下
    2016-04-04
  • 談談iOS中的幾種鎖

    談談iOS中的幾種鎖

    這篇文章主要介紹了談談iOS中的幾種鎖,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2016-11-11
  • iOS去除Webview鍵盤頂部工具欄的方法

    iOS去除Webview鍵盤頂部工具欄的方法

    這篇文章主要給大家介紹了關于iOS去除Webview鍵盤頂部工具欄的相關資料,文中通過示例代碼介紹的非常詳細,對各位iOS開發(fā)者們具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-06-06
  • iOS調用高德地圖SDK的完整步驟

    iOS調用高德地圖SDK的完整步驟

    高德LBS開放平臺將高德最專業(yè)的定位、地圖、搜索、導航等能力,以API、SDK等形式向廣大開發(fā)者免費開放,下面這篇文章主要給大家介紹了關于iOS調用高德地圖SDK的完整步驟,需要的朋友可以參考下
    2021-11-11
  • iOS將視頻錄像切成一張張縮略圖

    iOS將視頻錄像切成一張張縮略圖

    這篇文章主要為大家詳細介紹了iOS將視頻錄像切成一張張縮略圖的相關代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • IOS實現(xiàn)驗證碼倒計時功能(二)

    IOS實現(xiàn)驗證碼倒計時功能(二)

    這篇文章主要介紹了IOS實現(xiàn)驗證碼倒計時功能,點擊獲取驗證碼,進入時間倒計時,感興趣的小伙伴們可以參考一下
    2016-04-04

最新評論

瓦房店市| 永和县| 平原县| 巴彦淖尔市| 商河县| 乐陵市| 大姚县| 庆阳市| 柏乡县| 黄大仙区| 喀喇| 武强县| 略阳县| 囊谦县| 寻乌县| 安陆市| 石城县| 渭源县| 徐闻县| 桑植县| 壤塘县| 尚志市| 仪陇县| 丹阳市| 甘孜县| 陈巴尔虎旗| 富宁县| 乌审旗| 无棣县| 定襄县| 金乡县| 巨鹿县| 桐柏县| 盱眙县| 商洛市| 赞皇县| 肇庆市| 江津市| 渭南市| 广德县| 黔东|