控制器加载过程及UI初始化

控制器加载过程

项目过程中,控制器可以看作是UIView的管理者,而且UIView可以看作是CALayer的管理者
一、控制器 初始化方法(是否有xib)
代码和xib的区别(普通代码构建,直接使用代码CODE而不用翻译XIB中的数据(xml),省了一个步骤)
1. init 和 initWithNibName
init底层执行了initWithNibName(默认加载)
首先去找有没有相关的xib文件,没有就执行loadview创建view, 有就不创建
2. loadview方法 (底层实现)
注意:xib的情况下,在viewDidLoad里面加载的view还是xib上大小的view,执行完才会适配(两种autolayout, autosize)
self.view 如果view 为空,那么self.view的get方法,会进入一个死循环

  • -(instancetype)init;
  • -(instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;
  • -(void)loadView;
  • -(void)viewDidLoad;
  • -(void)viewWillAppear:(BOOL)animated;
  • -(void)viewDidAppear:(BOOL)animated;

注:

  1. init 封装了initWithNibName方法
  2. 创建类的时候使用eocViewCtl = [[EOCViewContrl alloc] initWithNibName:nil bundle:nil]代替 eocViewCtl = [[EOCViewContrl alloc] init];可以跳过init方法中的一些逻辑而直接通过initWithNibName方法进行创建。
    initWithNibName方法中name和bundle都传nil时,name会默认找与类名相同的nib文件,而bundle则是默认在mainBundle中去寻找。
  3. 如果是通过xib文件创建的控制器,则最好不要重写loadView方法,因为只要你重写,就会走这个方法,也就会覆盖掉你在xib中进行的操作。如果重写了loadView方法过后,想要加载Xib,就必须指定xib文件。

SecondViewCtr *vctr = [[SecondViewCtr alloc] initWithNibName:@"SecondViewCtr" bundle:nil];

  1. 就算我们不重写loadView,系统也肯定会走,只是当它发现有xib的时候,他就通过xib来进行创建,如果没有就通过别的方式进行创建。
  2. self.view 是懒加载的模式,懒加载在view的get方法中执行了loadview和viewDidLoad,如果你重写loadView,并且在viewDidLoad中又用到self.view,则会形成循环,无限走loadView和viewDidLoad,直至崩溃。类似于这样的代码。
    if (!_view) {
        [self loadView];
        [self viewDidLoad];
    }
return _view;
  1. 当我们需要进行项目拆分的时候,可以重写loadView方法,在里面将控制器的View替换成我们自定义的View,从而在View中实现一些业务逻辑。

UI初始化

二、UI的初始化
代码初始化:
init initWithFrame init封装了initWithFrame
xib初始化:
initWithCoder awakeFromNib

layoutSubviews 什么时候掉用(没有superview是不会掉用,除第一条例外)
1 第一次addsubview(加载到界面)的时候,提前条件有frame
2 修改本身frame的时候(前提是frame的值前后发生了变化)
3 修改子视图的frame的时候(前提是frame的值前后发生了变化)
3 添加子视图的时候
4 滚动一个scrollview的时候
5 旋转屏幕
6 init初始化不会触发layoutSubviews
7 直接调用setLayoutSubviews

layoutSubviews 的实用(UIButton的复用,改变文字和图片的位置)

UILabel 初始化过程, 完成之后_UILabelContentLayer 覆盖了上面所有的子视图层,view管理着CALayer层
UI稳定的点

IB_DESIGNABLE
IBInspectable

drawRect
CALayer

无Xib情况

  • -(id)init
  • -(id)initWithFrame:(CGRect)frame
  • -(void)layoutSubviews

view在initWithFrame中的frame值是不准确的,我们不能在这里面设置它的frame值,只能做一些添加子控件和一些初始化的操作等。只有当view走完initWithFrame方法,才有一个完整的结构。

在label初始化的方法initWithFrame中,添加一个子view

- (id)initWithFrame:(CGRect)frame{
    
    NSLog(@"%s", __func__);
    self = [super initWithFrame:frame];
    if (self) {
        
        UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
        view.backgroundColor = [UIColor blueColor];
        [self addSubview:view];
    }
    return self;
}

而在初始化label的时候,将背景色设置为其他颜色

    eocLabel = [[EOCLabel alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    eocLabel.backgroundColor = [UIColor yellowColor];
    [self.view addSubview:eocLabel];

就会发现先添加的blue view被yellow覆盖


这就说明在initWithFrame走完过后,label的layer层才渲染完成,也即是说当走完initWithFrame方法后,view才会有一个完整的结构。但是试了UIButton一些空间,blue并没有被yellow覆盖,这应该是控件的底层实现有些不同。

有Xib情况

  • -(id)initWithCoder:(NSCoder *)aDecoder
  • -(void)awakeFromNib
  • -(void)layoutSubviews
  • -(void)drawRect:(CGRect)rect

initWithCoder:相当于我们用代码创建时的initWithFrame方法,只要对象是从文件解析来的, 就会调用这个方法。

awakeFromNib:从xib或者storyboard加载完毕就会调用,但是我们一般不在这里面做操作,当使用一个controller控制多个nib文件时,awakeFromNib方法会被多次调用。因此,当不使用awakeFromNib方法来完成nib对象的初始化时,需要注意此方法的多次调用对其他nib文件造成的影响。

layoutSubviews:不管是用代码创建的View还是用Xib创建的View,我们一般在这个方法里面做很多操作,比如设置准确的frame值等,但是这个方法只要当子控件frame发生变化,或者添加子控件,滚动tableView等,都会调用,所以不应做太复杂和占内存的操作。

drawRect:
以下情况会被调用:

  1. 如果在UIView初始化时没有设置rect大小,将直接导致drawRect不被自动调用。drawRect 掉用是在Controller->loadView, Controller->viewDidLoad 两方法之后掉用的.所以不用担心在 控制器中,这些View的drawRect就开始画了.这样可以在控制器中设置一些值给View(如果这些View draw的时候需要用到某些变量 值).
  2. 该方法在调用sizeToFit后被调用,所以可以先调用sizeToFit计算出size。然后系统自动调用drawRect:方法。
  3. 通过设置contentMode属性值为UIViewContentModeRedraw。那么将在每次设置或更改frame的时候自动调用drawRect:。
  4. 直接调用setNeedsDisplay,或者setNeedsDisplayInRect:触发drawRect:,但是有个前提条件是rect不能为0。
    以上1,2推荐;而3,4不提倡

方法使用注意点:

  1. 若使用UIView绘图,只能在drawRect:方法中获取相应的contextRef并绘图。如果在其他方法中获取将获取到一个invalidate 的ref并且不能用于画图。drawRect:方法不能手动显示调用,必须通过调用setNeedsDisplay 或 者 setNeedsDisplayInRect,让系统自动调该方法。
  2. 若使用calayer绘图,只能在drawInContext: 中(类似鱼drawRect)绘制,或者在delegate中的相应方法绘制。同样也是调用setNeedDisplay等间接调用以上方法
  3. 若要实时画图,不能使用gestureRecognizer,只能使用touchbegan等方法来掉用setNeedsDisplay实时刷新屏幕

Xib可视化

在代码中用到IB_DESIGNABLE和IBInspectable两个关键字,即可使Xib的控件属性,实时的显示在Xib上,而不必每次运行看效果。但是此属性改变最好写在drawRect方法中,应该改变的其实是layer层。

#import <UIKit/UIKit.h>

IB_DESIGNABLE

@interface EOCView : UIView{
    
}

@property (nonatomic, strong)IBInspectable UIColor *eocColor;
@property (nonatomic, assign)IBInspectable float widthStroke;

@end

.m文件中

- (void)drawRect:(CGRect)rect{
    
    NSLog(@"%s", __func__);
  
    CGFloat centerX = (self.bounds.size.width - self.bounds.origin.x) / 2;
    CGFloat centerY = (self.bounds.size.height - self.bounds.origin.y) / 2;

    UIBezierPath *path = [[UIBezierPath alloc] init];
    // 添加一个圆形
    [path addArcWithCenter:CGPointMake(centerX, centerY) radius:50 startAngle:0 endAngle:360 clockwise:YES];
    
    // 设置线条宽度
    path.lineWidth = _widthStroke;
    // 设置线条颜色
    [_eocColor setStroke];
    // 绘制线条
    [path stroke];
    
}

这里即便多了两个属性值,我们可以改变这里实时看到效果图

参考文章:
UIView的layoutSubviews和drawRect方法何时调用
awakeFromNib 整理摘录

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容