iOS中自定義view的封裝
highlight: a11y-dark theme: cyanosis
「這是我參與11月更文挑戰的第26天,活動詳情查看:2021最後一次更文挑戰」
自定義view的封裝
- 如果一個
view
內部的子控件比較多,一般會考慮自定義一個view
,把它內部的子控件創建並封裝起來,不讓外界看見 - 外界可以傳入對應的數據模型給
view
,view
拿到模型數據後,給內部子控件設置對應的數據
代碼封裝自定義view
-
代碼封裝自定義
view
的步驟- 新建一個繼承
UIView
的類 - 在
initWithFrame:
方法中添加子控件(也可以使用懶加載) - 重寫模型屬性
set
方法,在set
方法中設置模型屬性到子控件上 - 在
layoutSubviews
方法中設置子控件的frame
(一定要調用[super layoutSubviews]
)
- 新建一個繼承
-
關於
layoutSubviews
在以下情況下會被調用init
初始化不會觸發layoutSubviews
addSubview
會觸發layoutSubviews
- 設置
view
的Frame
會觸發layoutSubviews
,當然前提是frame
的值設置前後發生了變化 - 滾動一個
UIScrollView
會觸發layoutSubviews
- 旋轉
Screen
會觸發父UIView
上的layoutSubviews
事件 - 改變一個
UIView
大小的時候也會觸發父UIView
上的layoutSubviews
事件
示例
js
@class ImageData;
@interface ImageDataView : UIView
//設置模型屬性
@property (nonatomic,strong) ImageData *imageData;
@end
```js
import "ImageData.h"
@interface ImageDataView() @property (nonatomic,strong) UIImageView imageView; @property (nonatomic,strong) UILabel label; @end
@implementation ImageDataView - (instancetype)initWithFrame:(CGRect)frame{ if (self = [super initWithFrame:frame]) {
}
return self;
}
pragma mark- 懶加載
- (UIImageView )imageView{ if (_imageView == nil) { UIImageView imageView = [[UIImageView alloc]init]; [imageView setBackgroundColor:[UIColor blueColor]]; [self addSubview:imageView]; _imageView = imageView; } return _imageView; }
- (UILabel )label{ if (_label == nil) { UILabel label = [[UILabel alloc]init]; [label setBackgroundColor:[UIColor redColor]]; label.textAlignment = NSTextAlignmentCenter; [self addSubview:label]; _label = label; } return _label; }
pragma mark- 模型賦值
- (void)setImageData:(ImageData *)imageData{ _imageData = imageData; self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%@",imageData.icon]]; self.label.text = imageData.name; }
pragma mark- 子控件座標
//這個方法專門用於佈局子控件,一般在這裏設置子控件的frame //當控件本身的尺寸發送改變時,系統會自動調用這個方法 - (void)layoutSubviews{ [super layoutSubviews];
CGFloat personW = self.frame.size.width;
CGFloat personH = self.frame.size.height;
self.imageView.frame = CGRectMake(0, 0, personW, personH-20);
self.label.frame = CGRectMake(0, personH-20, personW, 20);
} @end ```
方法調用
js
ImageData *imageData = [[ImageData alloc]initWithDic:dic];
ImageDataView *view = [[ImageDataView alloc]init];
view.imageData = imageData;
view.frame = CGRectMake(shopX, shopY, imageW, imageH);
[bgView addSubview:view];
xib封裝自定義view
- 新建一個繼承
UIView
的類 -
新建一個xib文件(xib的文件名最好和控件名一樣,修改最外面那個控件的
class
為控件類名 ) -
添加子控件、設置子控件屬性
-
加載 xib 文件 ```js [[[NSBundle mainBundle]loadNibNamed:NSStringFromClass([self class]) owner:self options:nil] lastObject] ````
- 重寫模型屬性
set
方法,在set
方法中設置模型屬性到子控件上
示例 ```js
import "ImageDataView.h"
import "ImageData.h"
@interface ImageDataView() @property (weak, nonatomic) IBOutlet UIImageView imageView; @property (weak, nonatomic) IBOutlet UILabel label; @end
@implementation ImageDataView + (instancetype)shareImageDataView{ return [[[NSBundle mainBundle]loadNibNamed:NSStringFromClass([self class]) owner:self options:nil] lastObject]; }
pragma mark- 模型賦值
- (void)setImageData:(ImageData *)imageData{ _imageData = imageData; self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%@",imageData.icon]]; self.label.text = imageData.name; } @end ```
兩種方法封裝自定義view的比較
- 在調整子控件的
frame
時,使用純代碼比 xib 更靈活,子控件可以在layoutSubviews
方法中靈活調整自己的frame
。而用 xib 相對於比較死板,但是更簡單,更方便 - 自定義
view
時,如果該view
一直一個樣式,推薦使用xib,簡單方便 - 而子控件經常隨着父控件變化而變化,推薦使用純代碼,靈活多變
- iOS-屏幕適配(基礎概念)
- Web 開發模式
- Node.js - 在 express 中啟用 cors 跨域資源共享
- 簡單的HTTP協議
- iOS中的Storyboard
- iOS中加載xib
- iOS中自定義view的封裝
- iOS中的事件
- iOS中的定時器(GCD定時器)
- iOS中的定時器(CADisplayLink)
- iOS中的線程鎖(關於NSRecursiveLock)
- iOS中的線程鎖(關於NSConditionLock)
- iOS中的線程鎖(線程鎖的相關概念)
- iOS中的多線程(多線程的競爭)
- iOS中的多線程(關於NSOperationQueue)
- iOS中的多線程(關於NSOperation)
- iOS中的多線程(關於GCD信號量)
- iOS中的多線程(關於GCD的其他方法)
- iOS中的多線程(關於GCD 的隊列組)
- iOS中的多線程(關於GCD的隊列和任務)