UIKit框架原理探索
# 06.UIKit框架原理探索
# 目录介绍
- 01.UIKit框架概述
- 1.1 UIKit框架说明
- 1.2 UIView视图
- 1.3 ViewController
- 1.4 Window窗口
- 1.5 Layout布局
- 02.常用的基础组件
- 2.1 经常用的组件
- 2.2 偶尔使用的
- 2.3 直接使用类
- 2.4 手势相关类
- 2.5 系统媒体工具
- 03.常用基础组件
- 3.1 UITextView组件
- 3.2 UIImageView组件
- 3.3 UIButton组件
- 04.常用列表组件
- 4.1 UITableView
- 4.2 UICollectionView
- 4.3 UIScrollView
- 05.UIView设计灵魂
- 5.1 UIView属性设计
- 5.2 视图UIView的形变
- 5.3 UIView层次关系
- 5.4 响应用户交互事件
- 06.Window窗口设计思想
- 6.1 UIWindow介绍
- 6.2 UIWindow创建时机
- 6.3 UIWindow层级设计
- 07.Layout布局设计思想
# 01.UIKit框架概述
# 1.1 UIKit框架说明
UIKit是一个基于Cocoa Touch的框架,提供了一套丰富的控件和API,用于创建和管理iOS应用程序的用户界面。它包括以下几个主要部分:
- 视图(Views):用于显示内容和接收用户交互。
- 控制器(ViewControllers):管理视图的生命周期和数据。
- 窗口(Windows):应用程序的顶层容器。
- 布局(Layouts):定义视图的布局和大小。
# 1.2 UIView视图
UIView是UIKit框架里面最基础的视图类,UIView类定义了一个矩形的区域,并管理该矩形区域内的所有屏幕显示。
UIView视图是所有控件的父类,控件用于响应用户的交互,而UIView则负责内容的显示和布局。
- UIView的frame(origin,size)属性:定义了一个矩形,描述一个UIView的大小和在父坐标的位置
- UIView的bounds(origin,size)属性:同样定义了一个矩形,描述一个UIView的大小和自身坐标原点的位置。bounds.origin属性默认值时(0,0),而bounds.size和frame.size是一致的
- UIView的center属性:用于确定一个视图的中心位置,参照其父视图的坐标系统。在对视图进行放大,缩小或者旋转,该属性的值不会改变
UIView视图层次管理方法列表
- insertSubview(view,at:) 在指定的位置插入视图
- insertSubview(UIView, aboveSubview: UIView) 将视图添加到指定视图的上方
- insertSubview(UIView, belowSubview: UIView) 将视图添加到指定视图的下方
- bringSubview(toFront: view1) 将指定的子视图移动到最前面
- bringSubview(toFront: view1) 将指定的子视图移动到最后面
- exchangeSubview(at: 0, withSubviewAt: 1) 交换两个指定位置的子视图在父类的位置
- removeFromSuperview() 将子视图从父类中移除
- addSubview(view) 将一个视图添加为另一个视图的子视图的方法
# 1.3 ViewController
ViewController 是基于 UIViewController 类的自定义类,用于管理一个或多个视图的显示和行为。它可以包含其他视图控制器、视图和控件,以及处理与这些元素相关的逻辑。
- 管理视图的生命周期:视图控制器负责在视图加载、显示、消失和销毁时执行相应的操作。
- 处理用户交互:视图控制器可以响应用户的输入和操作,例如按钮点击、手势识别等。
- 协调视图之间的切换和导航:视图控制器可以管理多个视图之间的切换和导航。
- 管理数据传递:视图控制器可以在不同的视图控制器之间传递数据。
# 1.4 Window窗口
UIKit 提供了 UIWindow 类来表示应用程序的窗口。窗口是 iOS 应用程序中的顶级容器,用于承载应用程序的视图层次结构。
let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = viewController //设置窗口的根视图控制器
window.backgroundColor = UIColor.white //设置窗口的背景颜色
window.isHidden = false //设置窗口的可见性
window.makeKeyAndVisible() //将窗口设置为主窗口
//监听窗口的旋转事件
NotificationCenter.default.addObserver(self, selector: #selector(handleRotation), name: UIDevice.orientationDidChangeNotification, object: nil)
2
3
4
5
6
7
# 1.5 Layout布局
使用 UIKit 进行布局是通过使用视图和布局约束来实现的。UIKit 提供了一组类和方法,用于创建和管理视图层次结构,并定义视图之间的布局关系。
1.使用 Auto Layout 进行布局。使用 NSLayoutConstraint 类来创建布局约束,并使用 NSLayoutConstraint.activate 方法将约束应用到视图上。
//这些约束定义了视图与其父视图之间的关系,如顶部、左侧、右侧的间距以及固定的高度。
view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
view.topAnchor.constraint(equalTo: superview.topAnchor, constant: 20),
view.leadingAnchor.constraint(equalTo: superview.leadingAnchor, constant: 20),
view.trailingAnchor.constraint(equalTo: superview.trailingAnchor, constant: -20),
view.heightAnchor.constraint(equalToConstant: 200)
])
2
3
4
5
6
7
8
2.使用 Stack View 进行布局。使用 UIStackView 类创建一个堆栈视图,并将多个视图添加到其中。我们可以设置堆栈视图的方向(水平或垂直)、间距、对齐方式和分布方式,以实现自动布局。
let stackView = UIStackView(arrangedSubviews: [view1, view2, view3])
stackView.axis = .vertical
stackView.spacing = 10
stackView.alignment = .center
stackView.distribution = .fill
superview.addSubview(stackView)
2
3
4
5
6
# 02.常用的基础组件
# 2.1 经常用的组件
基础 :UIView、UILabel、UIImage、UIColor、UIImageView、UITextField、UIButton、UITextView、UIFont
列表 :UIScrollView、UITableView、UICollectionView、UICollectionViewCell、UITableViewCell
其他 :UIViewController
# 2.2 偶尔使用的
选择器:UIPickerView(数据选择器)、UIDatePicker(时间选择器)、UIPageControl(与轮播图结合使用的小圆点) UISegmentedControl(分栏控制器)
滑动控件:UISlider(滑动控件)、UISwitch(开关)、UIProgressView(进度条)
加载控件:UIActivityIndicatorView(加载菊花)、UIWebView(加载网页)、UIActionSheet、UIAlertView(警告)
Bar组件:UITabBar、UIToolBar、UINavigationBar、UISearchBar
Item组件:UIBarItem、UITabBarItem、UINavigationItem、UIBarButtonItem
功能型控制器:UITabBarController、UINavigationController、UITableViewController、UICollectionViewController
# 2.3 直接使用类
设备:UIDevice(设备)、UIApplication(应用程序)、UIScreen(屏幕)、
窗口:UIWindow(窗口)、UIResponder(响应对象)、UIControl(响应控件)
事件:UIEvent(事件)、UIScreenMode、UITouch(触摸)
# 2.4 手势相关类
UIGestureRecognizer、UILongPressGestureRecognizer、UIPanGestureRecognizer
UIPinchGestureRecognizer、UIRotationGestureRecognizer、UISwipeGestureRecognizer
UITapGestureRecognizer
# 2.5 系统媒体工具
UIImagePickerController(照片)、UIVideoEditorController(视频)
# 03.常用基础组件
Showing Recent Errors Only /Users/yc/ugit/WeCardPay/WecardPayiOS/wecard-pay-test/wecard-pay-app/ViewController.swift:9:8: Could not find module 'SnapKit' for target 'x86_64-apple-ios-simulator'; found: arm64-apple-ios-simulator, at: /Users/yangchong/Library/Developer/Xcode/DerivedData/wecard-pay-app-fosspsnjlwnjpecpahalsholqgwz/Build/Products/Release-iphonesimulator/SnapKit/SnapKit.framework/Modules/SnapKit.swiftmodule
基础控件学习
基础控件Swift版本: 2.UIButton方法/属性详解 :https://www.cnblogs.com/iOSCain/p/4529354.html 基础控件Swift版本: 3.UILabel方法/属性详解 :https://www.cnblogs.com/iOSCain/p/4529353.html 基础控件Swift版本: 4.UIImageView方法/属性详解:https://www.cnblogs.com/iOSCain/category/694174.html 基础控件Swift版本: 5.UIImage方法/属性详解:https://www.cnblogs.com/iOSCain/p/4529351.html 基础控件Swift版本: 6.UITextField方法/属性详解:https://www.cnblogs.com/iOSCain/p/4529350.html
高级控件学习
- 高级控件Swift版本: 1.UIScrollView方法/属性详解:https://www.cnblogs.com/iOSCain/p/4529349.html
- 高级控件Swift版本: 2.UITableView方法/属性详解:https://www.cnblogs.com/iOSCain/p/4529347.html
- 高级控件Swift版本: 3.UITableViewCell方法/属性详解:https://www.cnblogs.com/iOSCain/p/4529346.html
- 高级控件Swift版本: 4.UICollectionView方法/属性详解:https://www.cnblogs.com/iOSCain/p/4529348.html
- 高级控件Swift版本: 5.UITextView方法/属性详解:https://www.cnblogs.com/iOSCain/p/4529345.html
- 高级控件Swift版本: 6.UIAlertView方法/属性详解:https://www.cnblogs.com/iOSCain/p/4529344.html
- 高级控件Swift版本: 7.UIActionSheet方法/属性详解:https://www.cnblogs.com/iOSCain/p/4529343.html
- 基础控件Swift版本: 7.UISwitch方法/属性详解:https://www.cnblogs.com/iOSCain/p/4529342.html
- 高级控件Swift版本: 8.UISegemtedControl方法/属性详解:https://www.cnblogs.com/iOSCain/p/4529341.html
- 高级控件Swift版本: 9.UINavigationController方法/属性详解:https://www.cnblogs.com/iOSCain/p/4529340.html
- 高级控件Swift版本: 10.UIWebView方法/属性详解:https://www.cnblogs.com/iOSCain/p/4529339.html
# 3.1 UITextView组件
# 3.2 UIImageView组件
# 3.3 UIButton组件
# 04.常用列表组件
# 4.1 UITableView
UITableView 是一种用于展示和管理可滚动的列表视图的类。它是 iOS 开发中最常用的界面元素之一,用于显示大量数据或项目列表。
以下是使用 UITableView 的一般步骤:
- 创建 UITableView 实例。并指定了样式为 .plain。还可以选择其他样式,如 .grouped 或 .insetGrouped。
- 设置数据源和代理。将数据源和代理设置为当前视图控制器(或其他适当的对象),以便处理数据和布局相关的操作。
- 实现数据源方法。实现了 UITableViewDataSource 协议中的两个方法,用于提供行数和单元格内容。
- 实现代理方法(可选)。处理行的选中或其他交互操作,可以实现 UITableViewDelegate 协议中的方法。
- 注册单元格类或 NIB 文件。注册了一个自定义的单元格类,以便在 cellForRowAt 方法中使用。
- 添加 UITableView 到视图层次结构。将 UITableView 添加到视图层次结构中,以便它可以显示在界面上。
//1.创建 UITableView 实例
let tableView = UITableView(frame: CGRect.zero, style: .plain)
//2.设置数据源和代理
tableView.dataSource = self
tableView.delegate = self
//3.实现数据源方法
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// 返回每个 section 中的行数
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// 返回指定 indexPath 的单元格
}
//4.实现代理方法(可选)
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// 处理选中行的操作
}
//5.注册单元格类或 NIB 文件
tableView.register(MyCellClass.self, forCellReuseIdentifier: "CellIdentifier")
//6.添加 UITableView 到视图层次结构
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
实际上,UITableView 还提供了许多其他功能,例如分区、头部和尾部视图、编辑模式、滚动到指定行等。
# 4.2 UICollectionView
UICollectionView 是一种用于展示和管理可滚动的、可定制的网格布局的视图。
它类似于 UITableView,但提供了更灵活的布局选项,可以用于创建各种复杂的界面。UICollectionView 的一般步骤:
- 创建 UICollectionView。使用 UICollectionViewFlowLayout 作为布局对象。
- 设置数据源和代理。将数据源和代理设置为当前视图控制器(或其他适当的对象),以便处理数据和布局相关的操作。
- 实现数据源方法。实现了 UICollectionViewDataSource 协议中的两个方法,用于提供单元格的数量和内容。
- 实现布局代理方法(可选)。定义单元格的大小或布局,可以实现 UICollectionViewDelegateFlowLayout 协议中的方法。
- 注册单元格类或 NIB 文件。注册了一个自定义的单元格类,以便在 cellForItemAt 方法中使用。
- 添加 UICollectionView 到视图层次结构。将 UICollectionView 添加到视图层次结构中,以便它可以显示在界面上。
//1.创建 UICollectionView。
let collectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout())
//2.设置数据源和代理,
collectionView.dataSource = self
collectionView.delegate = self
//3.实现数据源方法。
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// 返回每个 section 中的 item 数量
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// 返回指定 indexPath 的单元格
}
//4.实现布局代理方法(可选)
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// 返回指定 indexPath 的单元格大小
}
//5.注册单元格类或 NIB 文件
collectionView.register(MyCellClass.self, forCellWithReuseIdentifier: "CellIdentifier")
//6.添加到视图层次结构
view.addSubview(collectionView)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
UICollectionView 还提供了许多其他功能,例如分区、头部和尾部视图、选择和高亮等。
# 4.3 UIScrollView
# 05.UIView设计灵魂
UIView类(视图类)负责管理屏幕上的一块矩形区域,包括这个区域内的显示样式,比如背景颜色、大小、以及行为动作,例如监测用户点击等触碰事件。总体来讲,视图类的主要作用有以下3个方面。
- 样式显示与动画:负责自身矩形区域内样式的显示,以及某些属性(大小、位置、角度)变化时的动画过渡效果。
- 布局与子视图管理:管理子视图。
- 事件处理:接收并响应用户的触摸事件。
# 5.1 UIView属性设计
UIView继承自UIResponder,因此UIView可以响应用户交互。另外,一些常用控件都继承自UIView。需要特别说明的是,窗口(UIWindow)也是继承自UIView,窗口可以认为是一个特殊的View。
// 最常使用的UIView属性
@property(nonatomic) CGrect frame;
@property(nonatomic) CGrect bounds;
@property(nonatomic) CGPoint center;
@property(nonatomic) CGFloat alpha;
@property(nonatomic) CGAffineTransform transform;
@property(nullable, nonatomic, copy) UIColor *backgroundColor;
@property(nonatomic, getter=isHidden) BOOL hidden;
// UIView管理子视图的常用属性和方法
@property(nullable, nonatomic, readonly) UIView *superview;
@property(nullable, nonatomic, copy) NSArray *subviews;
@property(nullable, nonatomic, readonly) UIWindow *window;
-(void)removeFromSuperview;
-(void)addSubview:(UIView *)view;
-(void)bringSubviewToFront:(UIView *)view;
// UIView有关动画的属性和方法
+(void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
视图UIView的外观是如何设计的
1.基本样式:背景颜色,透明度及是否隐藏
// 背景颜色属性BackgroundColor
@property(nullable, nonatomic, copy) UIColor *backgroundColor;
// 透明度alpha
@property(nonatomic) CGFloat alpha;
// 是否隐藏
@property(nonatomic, getter=isHidden) BOOL hidden;
2.位置与大小:Frame、Bounds、Center
@property(nonatomic) CGRect frame;
@property(nonatomic) CGRect bounds;
@property(nonatomic) CGPoint center;
2
3
4
5
6
7
8
9
10
11
12
Frame:视图在其父视图坐标系中的位置和大小。建议在控件初始化之后,紧接着就去设置Frame,设置完成后,假如涉及修改控件的位置、大小等,就不要再去修改Frame了。
Bounds:视图在其自身的坐标系中的位置和大小。Bounds属性中,视图的bounds.origin始终是(0,0),因此bounds属性最核心的作用是设置视图的大小,即bounds.size,当需要去修改视图大小的时候,可以修改bounds.size。
Center:视图中心点在父视图坐标系中的坐标,当需要修改视图对象的位置时,可以修改Center属性。
# 5.2 视图UIView的形变
1.位移
// 当需要修改视图对象的位置时(上移、下移、左移、右移),可以通过修改视图对象的center属性。
-(IBAction)move:(id)sender {
CGPoint point = self.mvView.center;
point.x -= 10;
self.mvView.center = point;
// 注意:不能直接修改结构体变量的值,即self.myView.center.x -=10是不合法的。
}
2
3
4
5
6
7
2.放大、缩小
// 第一种方法可以修改视图对象的bounds.size属性;第二种方法是直接修改视图对象的transform属性,即让视图对象进行一次形变操作。
CG_EXTERN CGAffineTransform CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy); // sx以及sy是在X轴以及Y轴两个方向上放大的比例。
-(IBAction)scale:(id)sender {
self.myView.transform=CGAffineTransformScale(self.myView.transform, 1.1, 1.1);
}
2
3
4
5
3.旋转
// 通过修改视图对象的transform属性,同样可以实现视图的顺时针旋转以及逆时针旋转
CG_EXTERN CGAffineTransform CGAffineTransformRotate(CGAffineTransform t, CGFloat angle);
CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
-(IBAction)rotate:(id)sender {
self.myView.transform=CGAffineTransformRotate(self.myView.transform, M_PI_4);
}
2
3
4
5
6
4.重置transform属性
// 当需要重置transform属性时,可以使用CGAffineTransformIdentity命令,
// 但需要注意的是:如果之前对视图对象的frame、center、bounds属性进行了修改,若需要完全重置一个视图的样式,
// 除了重置transform属性之外,还需要重置frame、center、bounds属性,因此在对视图进行形变操作之前,有必要保存视图的原始状态以便恢复。
-(IBAction)reset:(id)sender {
self.myView.transform=CGAffineTransformIdentity;
}
2
3
4
5
6
# 5.3 UIView层次关系
// 有关视图层次关系的常用属性
@property(nullable, nonatomic, readonly) UIView *superView; // 父视图
@property(nullable, readonly, copy) NSArray *subViews; // 所有的子视图
@property(nullable, nonatomic, readonly) UIWindow *window; // 视图所在的window
// 有关视图层次关系控制的常用方法
-(void)addSubview:(UIView *)view; // 添加子视图
-(void)bringSubviewToFront:(UIView *)view; // 把子视图移到最前显示
-(void)sendSubviewToBack:(UIView *)view; // 把子视图移到最后显示
-(void)removeFromSuperview; // 从父视图中移除
// 设置层次关系
-(IBAction)changeLayer:(id)sender {
// 从subviews中取出视图
UIView *lastView = (UIView *)[self.view.subviews lastObject];
[self.view sendSubviewToBack:lastView];
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 5.4 响应用户交互事件
1.与用户交互事件相关的属性
// 是否支持用户交互
@property(nonatomic, getter=isUserInteractionEnabled) BOOL userInteractionEnabled;
// 是否支持多点触控
@property(nonatomic, getter=isMultipleTouchEnabled) BOOL multipleTouchEnabled;
2
3
4
2.添加手势
// 获取视图上所有手势
@property(nullable, nonatomic, copy) NSArray *gestureRecongnizers;
// 添加手势
-(void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer;
// 移除手势
-(void)removeGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer;
-(void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.myView];
// 添加长按手势
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressAction)];
[self.myView addGestureRecognizer:longPress];
// 添加点击手势
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction)];
[self.myView addGestureRecognizer:tap];
}
// 长按触发动作
-(void)longPressAction {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"长按" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
}
// 点击触发动作
-(void)tapAction {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"点击" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
3.自定义视图类实现touches系列方法
// 在视图管理范围内开始点击时调用
-(void)touchesBegan:(NSSet *)touches withEvent:(nullable UIEvent *)event;
// 在视图管理区域中移动时反复调用
-(void)touchesMoved:(NSSet *)touches withEvent:(nullable UIEvent *)event;
// 在视图管理范围内结束点击时调用
-(void)touchesEnded:(NSSet *)touches withEvent:(nullable UIEvent *)event;
2
3
4
5
6
# 06.Window窗口设计思想
# 6.1 UIWindow介绍
UIWindow简介如下所示:
- UIWindow是一种特殊的UIView,通常在一个app中至少会有一个UIWindow。
- iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的View,最后将控制器的View添加到UIWindow上,于是控制器的View就显示在屏幕上了。
- 一个iOS程序之所以能显示在屏幕上,完全是因为它有UIWindow,也就是说,没有UIWindow就看不到任何UI界面。
- 状态栏和键盘都是特殊的UIWindow。
那么UIWindow是如何将View显示到屏幕上的呢?这里有三个重要的对象UIScreen,UIWindow,UIView。
- UIScreen对象识别物理屏幕连接到设备
- UIWindow对象提供绘画支持给屏幕
- UIView执行绘画,当窗口要显示内容的时候,UIView绘画出他们的内容并附加到窗口上
# 6.2 UIWindow创建时机
参考:https://juejin.cn/post/6844903444365443079