一、学习笔记
-
iOS
自定义View
:-
如果一个
view
内部的子控件比较多,可以将其封装为一个自定义view
,基本流程如下:- 重写
- (instancetype)initWithFrame:(CGRect)frame
方法,在该方法中添加子控件(或者使用懒加载),注意此时不需要设置子控件的frame
- 重写
- (void)layoutSubviews
方法,在该方法中设置子控件的frame
,注意必须调用[super layoutSubviews];
- 定义数据模型属性,并重写该属性的
set
方法,在set
方法中取出相应的属性并赋给子控件 - 如果涉及到对子控件的事件处理,则定义
Block
属性,并定义对应的set
方法,在使用该view
的父view
的controller
设置这些Block
属性,作为内控事件的回调
- 重写
-
示例:
// .h文件 #import <UIKit/UIKit.h> #import "CustomUIViewModel.h" @interface CustomUIView : UIView // 数据模型 @property (nonatomic, strong) CustomUIViewModel *model; // 点击回调的Block @property (nonatomic, copy) void(^labelClick)(void); // 设置Block的方法 - (void)setLabelClickWithBlock:(void(^)(void)) labelClickBlock; @end // .m文件 #import "CustomUIView.h" @interface CustomUIView() @property (nonatomic, strong) UILabel *label; @end @implementation CustomUIView // 1.重写initWithFrame:方法,创建子控件并添加到view里 - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { UILabel *label = [[UILabel alloc] init]; // 4.添加TapGesture label.userInteractionEnabled = YES; UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelTapGesture:)]; [label addGestureRecognizer:tap]; self.label = label; [self addSubview:label]; } return self; } // 2.重写layoutSubviews,给子控件设置frame - (void)layoutSubviews { [super layoutSubviews]; CGSize size = self.frame.size; self.label.frame = CGRectMake(0, 0, size.width * 0.5, size.height * 0.5); } // 3.重写数据模型属性的set方法,给子控件赋值 - (void)setModel:(CustomUIViewModel *)model { _model = model; self.label.text = model.name; } // 4.在TapGesture中调用回调的Block - (void)labelTapGesture:(UITapGestureRecognizer *)gestureRecognizer { if (self.labelClick) { self.labelClick(); } } // 4.设置Block - (void)setLabelClickWithBlock:(void(^)(void)) labelClickBlock { _labelClick = labelClickBlock; } @end
-
两个问题:
-
为什么自定义
view
时重写- (instancetype)initWithFrame:(CGRect)frame
而不是- (instancetype)init
?- 因为在创建该自定义
view
的时候,可能使用init
也可能使用initWithFrame
,
- 因为在创建该自定义
-
-