iOS开发中的布局

说在前面的话

一看标题:说的是不是NSLayoutConstraint?不是.那是不是Autoresizing?不是.那是不是XIB中的自动布局(Auto Layout)?不是.那是什么??????恭喜你,你差不多说完了iOS中的布局方式,但是接下来,我所要说的不是这些,当然如果你能用以上3个方法中的其中一种都可以,但是今天我所要介绍的,都会避开以上的3中情况.具体内容,请往下看...

需求

需要做一个如下的界面,不要使用XIB.

效果图

这个界面很简单:
在控制器里面,有一个UITableview.然后自定义了一个简单的cell.
这是再简单不过的界面了,我会介绍如下的东西:

  • 在控制器中,如何创建一个UITableView.
  • 在控制器中,如何布局.
  • 在视图(cel为例l)中,如何创建字控件,又将如何布局.
  • 控制器与视图(cell为例)最好如何关联.

开始

来到事先准备好的控制器(HGSubLayoutViewController)中,最初的代码如下:(什么都木有)

#import "HGSubLayoutViewController.h"

@interface HGSubLayoutViewController ()

@end

@implementation HGSubLayoutViewController


- (void)viewDidLoad {
    [super viewDidLoad];
    
}

@end

  • 定义一个UITableView如下:
@property (nonatomic, strong) UITableView* tableView;

这里有一个问题,这个tableView,是应该定义成strong还是weak?答案是:都可以!但是,我强烈建议:在没有特殊的情况下,尽量定义成weak.代码会显得高大上一些!我暂且定义成strong.

  • 那这个tableView应该在哪里创建呢?首当其冲的会想到在控制器的init方法中吧.那我就实现一下.
// 构造方法
- (instancetype)init {
    self = [super init];
    
    UITableView* tableView = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].bounds];
    tableView.backgroundColor = [UIColor redColor];
    
    [self.view addSubview:tableView];
    self.tableView = tableView;
    
    return self;
}

咋一看,没有问题.运行一下,也没有问题.但是我要告诉你,这段代码是有问题的!

有道理,顺序很重要!

由上图结论得出:上面的那段代码是很危险的!为什么危险?这个问题,我不做过多的解释.如果你知道:1.init方法应该在什么时候调用,2.viewDidLoad方法又是在什么时候调用?3. viewDidLoad的主要用途是什么?你清楚了这3个问题,你就能幻想到上面带密码的危险性了!那么上面的代码中,怎么就调用了viewDidLoad方法呢?我可以直接告诉你:因为你在init方法中调用了self.view.

在init方法中不要调用self.view!!!!!!这是大忌!!!!!!!

那你会说,OK我在viewDidLoad方法中调用self.view,这总算可以吧.恩可以!Verry Good!😍,你也会说,我可否将init里面创建tableView的代码放到一个独立的方法中,在viewDidLoad方法中调用,这也可以.Verry Verry Good!😍.你还可以说, 想使用懒加载,直接早viewDidLoad方法中调用:

// 添加tableView到self.view中.一定要写成:self.tableView,你写成_tableView试试.
[self.view addSubview:self.tableView];

OK了,tableView的创建总算搞定了.

等等,别忘了.这是你将tableView设置成strong的情况.那设置成weak,有该如何呢?换成weak,是我所推荐的,因为我一致坚持:属性能用weak的尽量用weak!无奈之下才会用strong.将刚刚所有的代码delete了.换成如下代码:

#import "HGSubLayoutViewController.h"

@interface HGSubLayoutViewController ()

@property (nonatomic, weak) UITableView* tableView;

@end

@implementation HGSubLayoutViewController

// 创建tableView并添加到self.view中.
- (void)setupTableView {
    UITableView* tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
    tableView.backgroundColor = [UIColor redColor];
    
    [self.view addSubview:tableView];
    self.tableView = tableView;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self setupTableView];
}

@end

很高兴的告诉你,这就是我最终选择的方式!通过以后的解说,如果设置成weak,你只能这么做!为啥?没啥!😍

代理的那些事

代理的全部操作如下:

#import "HGSubLayoutViewController.h"
#import "HGHGSubLayoutCell.h"

@interface HGSubLayoutViewController () <UITableViewDelegate, UITableViewDataSource>

@property (nonatomic, weak) UITableView* tableView;

@end

@implementation HGSubLayoutViewController

// 创建tableView并添加到self.view中.
- (void)setupTableView {
    UITableView* tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
   
 tableView.delegate = self;
    tableView.dataSource = self;
    
    [self.view addSubview:tableView];
    self.tableView = tableView;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self setupTableView];
}

#pragma mark - UITableViewDelegate, UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 30;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 100;
}

- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString* const ID = @"HGHGSubLayoutCell";
    HGHGSubLayoutCell* cell = [tableView dequeueReusableCellWithIdentifier:ID];
    
    if (!cell) {
        [tableView registerClass:[HGHGSubLayoutCell class] forCellReuseIdentifier:ID];
        cell = [tableView dequeueReusableCellWithIdentifier:ID];
    }
    
    // 在实际开发中,这里我会给这个cell弄一个mode
    // cell.mode = mode; // 一个cell对应一个mode
    
    return cell;
}

@end

这段代码,很简单,也很简洁!但是有的地方依然需要说一下:

  • <UITableViewDelegate, UITableViewDataSource>协议应该在.h还是在.m中写?答案是:都可以.但是我强烈建议在.m中写.因为在写代码的时候,在代码的规范上,也应该要坚持代码的封装性!能在.m实现的,不必让外界知道的,尽量放到.m文件中.在.h文件中尽量不要暴露不该暴露的东西!!
  • 关于tableView的声明.同理,强烈建议方到.m文件中!
  • 关于代理:tableView: cellForRowAtIndexPath:.看看我实现的,是不是很简洁,很简单呢?........

显示

细心的同学,都能想到:这个tableView是看不到的.因为没有尺寸!!!那么,我为什么没有在创建tableView的时候给此存呢?我是想在另一个方法中设置.代码如下:

// 布局控制器中控件的位置
- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    
    self.tableView.frame = self.view.bounds;
    
}
这个viewDidLayoutSubviews方法,才是最接近我们的这个主题!对,我的初衷就是想告诉大家,在控制器中,布局控件的的所有操作,尽量都在这个方法里面的做!这个方法的,大家可以查看官方文档.

先来介绍一下要用到的模型

.h文件
#import <Foundation/Foundation.h>

@interface HGHGSubLayoutMode : NSObject

@property (nonatomic, copy) NSString* hgTitle;

@end

.m文件
#import "HGHGSubLayoutMode.h"

@implementation HGHGSubLayoutMode

@end

cell里面的实现

当你看到这里,也就说明了.在控制器里面的布局问题,我已经说完了,接下来,就是UIView种的布局.这里我是借助Cell来说明视图中的布局.
现在我将要在cell里面添加一个简单的UILabel.

  • cell里面的所有代码,如下:
.h文件
#import <UIKit/UIKit.h>
@class HGHGSubLayoutMode;

@interface HGHGSubLayoutCell : UITableViewCell

// cell对应的mode
@property (nonatomic, strong) HGHGSubLayoutMode* mode;

@end


.m文件

#import "HGHGSubLayoutCell.h"
#import "HGHGSubLayoutMode.h"

@interface HGHGSubLayoutCell ()

@property (nonatomic, weak) UILabel* hgLabel;

@end

@implementation HGHGSubLayoutCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    
    // 在构造方法中的只是创建控件与对该控件做固定的操作.
    UILabel* hgLabel = [[UILabel alloc] init];
    hgLabel.textAlignment = NSTextAlignmentCenter;
    hgLabel.textColor = [UIColor redColor];
    hgLabel.backgroundColor = [UIColor grayColor];
    
    // 添加
    [self.contentView addSubview:hgLabel];
    self.hgLabel = hgLabel;
    
    self.selectionStyle = UITableViewCellSelectionStyleNone;
    
    return self;
}

// 在模型的setter方法中将对应的属性与对应的控件链接起来
- (void)setMode:(HGHGSubLayoutMode *)mode {
    _mode = mode;
    
    self.hgLabel.text = mode.hgTitle;
}

// 在视图中,所有子控件的的布局,都放到这个系统方法中.看看这个方法的名字就明白了.
- (void)layoutSubviews {
    [super layoutSubviews];
    
    // 布局
    self.hgLabel.frame = self.contentView.bounds;
}

@end
我个人感觉,我的cell写得还不错的:代码不乱,层次清楚就拿这个cell来说吧.一个cell就三大步:1,构造方法中,只是创建与添加.2,通过模型设置所有的控件.3,就是布局.这就用到视图中的一个系统方法: layoutSubviews.关于我的代码,建议多欣赏!哈哈哈哈,今天我的心情有点怪异,我在嘚瑟!
视图中的这个系统layoutSubviews方法,也很重要,是这个主题的第二个重要方法!具体详细,查看官方文档.

总结:

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

推荐阅读更多精彩内容