欢迎光临
我们一直在努力

UIkit的基本框架

使用语言:swift
在Xcode的mian文件中查找控件:command + shift + L

UILabel

//创建一个label
let label:UILabel = UILabel(frame: CGRectMake(20, 100, 280, 100))
// let label = UILabel(frame: CGRect(x: 100, y: 100, width: 150, height: 40))
label.text = "i am a label,i like ios,i like phone"
//设置字体
label.font = UIFont.boldSystemFont(ofSize: 20)
//设置字体颜色
label.textColor = UIColor.red
//设置label的背景颜色
label.backgroundColor = UIColor.blue
//设置文字的居中
label.textAlignment = NSTextAlignment.center
//设置label的阴影
// label.shadowColor = UIColor.orange
// label.shadowOffset = CGSizeMake(10, 10)//向右向下偏移10像素
//设置label行数:在label的尺寸内将长句换行
// 0表示无限行
label.numberOfLines = 2

self.view.addSubview(label)//把标签和视图关联

1.文本的常用字体样式:

普通正文systemFont(ofSize: 16) 或 .body
加粗标题systemFont(ofSize: 18, weight: .bold)
说明小字.caption1 或 systemFont(ofSize: 12)
适配用户字号优先用 preferredFont(forTextStyle:)
自定义字体用 UIFont(name:, size:),记得在 Info.plist 注册

2.背景常用的颜色样式:

在这里插入图片描述

3.常用颜色构造:

1.UIColor(white:alpha:):是一种快速创建灰度颜色的方法,white 是亮度值(0 是黑,1 是白),适合创建背景、灰色文字等
2.UIColor(red:green:blue:alpha:):通过 RGB 值创建自定义颜色

UIButton

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

//创建并设置button类型
/*
case custom = 0 //自定义,无类型
@available(iOS 7.0, *)
case system = 1 //标准的系统类型
case detailDisclosure = 2
case infoLight = 3
case infoDark = 4 //详情的按钮样式
case contactAdd = 5 //添加的按钮样式
*/

let button:UIButton = UIButton(type: .system)
button.frame = CGRect(x: 100, y: 100, width: 100, height: 100)
button.backgroundColor = UIColor.orange

//添加事件
//而 addTarget 传递的 selector 不支持带外部标签的写法,所以必须用 _ 省略标签
button.addTarget(self, action: #selector(click(_:)), for: .touchUpInside)

//设置按钮标题
button.setTitle("an niu", for: .normal)

self.view.addSubview(button)
}
//必须声明这个方法,前面加 @objc才能被Selector调用
//按钮的点击事件需要 Objective-C runtime 支持
@objc func click(_ btn:UIButton){
print("按钮被点击了")
btn.backgroundColor = UIColor.blue
}

常用按钮样式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

UIImageView

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

//创建一个imageview对象
let imageView = UIImageView(frame: CGRectMake(100, 100, 200, 200))
//给imageview设置图片
imageView.image = UIImage(named: "p1.jpg")
//设置imageview的背景颜色
imageView.backgroundColor = UIColor.red

self.view.addSubview(imageView)

//设置imageView的动画效果
var array:Array<UIImage?> = Array()
for i in 14 {
let image:UIImage? = UIImage(named: "p\\(i).jpg")

array.append(image)
}
//设置动画数组
imageView.animationImages = array as? [UIImage]
//设置动画的播放次数
// 0表示循环播放
imageView.animationRepeatCount = 0
//设置播放一轮的时间
imageView.animationDuration = 3
//开始播放动画
imageView.startAnimating()

}

contentMode

contentMode 是 UIImageView 的属性,用来控制图片如何在 UIImageView 的 frame 内缩放、对齐。
在这里插入图片描述

控件的layer属性

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
//layer层专门对控件的视图进行渲染

let imageView:UIImageView = UIImageView(frame: CGRectMake(100, 100, 100, 100))
imageView.backgroundColor = UIColor.red

//设置圆角
//imageView.layer.masksToBounds = true
//imageView.layer.cornerRadius = 50 //此时为圆形了
//设置边框
imageView.layer.borderWidth = 2
imageView.layer.borderColor = UIColor.green.cgColor
//设置阴影
imageView.layer.shadowColor = UIColor.brown.cgColor
imageView.layer.shadowOffset = CGSizeMake(10,10)
imageView.layer.shadowOpacity = 1 //设置为不透明

self.view.addSubview(imageView)

}

searchBar

1.相关属性和UI方面

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
//搜索框控件

//创建一个搜索框
let searchBar:UISearchBar = UISearchBar(frame: CGRect(x: 20 ,y: 100 ,width: 320 ,height: 180))

//设置输入框上的默认提示语
searchBar.placeholder = "请输入关键字"
//设置搜索框上显示的默认文字
searchBar.text = "你好"
//设置搜索框风格
searchBar.barStyle = UIBarStyle.default
//设置搜索框背景文字
searchBar.prompt = "这是背景文字"
//设置相应功能按键的显示与否
// searchBar.showsBookmarkButton = true
searchBar.showsSearchResultsButton = true
//设置渲染颜色
searchBar.tintColor = UIColor.red
//设置搜索框颜色
searchBar.barTintColor = UIColor.blue

// 刷新布局,必写
//让控件根据内部子控件内容,自动重新计算、适配自身宽高尺寸,覆盖你手动设置的frame宽高。
searchBar.sizeToFit()

self.view.addSubview(searchBar)

}

2.与用户交互方面

import UIKit

class ViewController: UIViewController,UISearchBarDelegate {
//创建一个搜索框
var searchBar:UISearchBar = UISearchBar(frame: CGRect(x: 20 ,y: 100 ,width: 320 ,height: 180))

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
//搜索框控件

//设置附件视图
searchBar.scopeButtonTitles = ["1","2","3","4"]
//展示附件视图
searchBar.showsScopeBar = true
searchBar.selectedScopeButtonIndex = 0

//设置输入框上的默认提示语
searchBar.placeholder = "请输入关键字"
//设置搜索框上显示的默认文字
// searchBar.text = "你好"
//设置搜索框风格
searchBar.barStyle = UIBarStyle.default
//设置搜索框背景文字
// searchBar.prompt = "这是背景文字"
//设置相应功能按键的显示与否
searchBar.showsBookmarkButton = true
// searchBar.showsSearchResultsButton = true
//设置渲染颜色
// searchBar.tintColor = UIColor.red
//设置搜索框颜色
// searchBar.barTintColor = UIColor.blue

//设置代理
searchBar.delegate = self

self.view.addSubview(searchBar)

}
//我们点击输入框时会弹出系统键盘,但是默认收不回去了
//点击屏幕时系统键盘收起
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
searchBar.resignFirstResponder()//注销第一响应
}

//代理回调函数
//点击附件视图代理方法的回调
func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
print(selectedScope)
}
//当输入框文字变化时调用的方法
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
// print(searchText)
}
//点击图书按钮时触发的方法
func searchBarBookmarkButtonClicked(_ searchBar: UISearchBar) {
print("点击了图书按钮")
}
//点击结果按钮时触发的方法
func searchBarResultsListButtonClicked(_ searchBar: UISearchBar) {

}
//将要进入编辑状态时触发的方法
//false不能进入编辑状态
func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool {
return true
}
///将要结束编辑状态时触发的方法
func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool {
return true
}
//检测用户的输入文字
func searchBar(_ searchBar: UISearchBar, shouldChangeTextInRanges ranges: [NSValue], replacementText: String) -> Bool {
print(replacementText)
return true
}
//点击取消按钮时触发的方法
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {

}
//点击"搜索"按钮时触发的方法
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {

}
}

UISwitch

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

//创建一个开关控件
//大小是系统固定的,影响的只有位置
let mySwitch:UISwitch = UISwitch(frame: CGRect(x: 100, y: 100, width: 100, height: 100))

//添加触发事件
mySwitch.addTarget(self, action: #selector(click(_:)), for: .valueChanged)

//设置滑块的颜色
mySwitch.thumbTintColor = UIColor.red
//设置开关开启的颜色
mySwitch.onTintColor = UIColor.blue
//开关的渲染颜色
mySwitch.tintColor = UIColor.green

self.view.addSubview(mySwitch)
}

@objc func click(_ sw:UISwitch){
if sw.isOn{
self.view.backgroundColor = UIColor.gray
}else{
self.view.backgroundColor = UIColor.brown
}
}
}

对绑定事件和执行回调的理解

//……

//添加触发事件
mySwitch.addTarget(self, action: #selector(click(_:)), for: .valueChanged)

//回调方法
@objc func click(_ sw:UISwitch){
if sw.isOn{
self.view.backgroundColor = UIColor.gray
}else{
self.view.backgroundColor = UIColor.brown
}
}

1.语法解释

上面的绑定事件:
1、#selector()
Swift 语法:编译期校验方法是否存在,写错函数名 Xcode 直接报错(老式Selector(“字符串”)写错要运行才崩溃)。
2.、click(_ :)
click:绑定的方法名;
_ : 冒号代表这个函数需要接收 1 个参数(对应下面click(_ sw:UISwitch)的入参),有几个参数就写几个::

  • 无参函数:#selector(click)
  • 1 个参数:#selector(click(_ :))(现在的写法)
  • 2 个参数:#selector(click(_ :))

下面的回调函数:
1、@objc
Swift 的 addTarget 底层依赖 Objective-C 运行时,不加 @objc,OC 找不到这个 Swift 方法,点击 / 切换开关就找不到函数、直接崩溃。
作用:把 Swift 函数暴露给 OC 运行环境识别。

2、_ sw:UISwitch

  • _ :省略外部参数标签,调用时不用写参数名,直接 click(控件),对应 selector 写法必须带_:
  • sw:形参名,系统自动把触发事件的 UISwitch 控件传进来,sw.isOn 就是读取开关当前开 / 关状态;
  • UISwitch:限定参数类型只能是开关控件。

2.回调逻辑步骤

第 1 步:你注册 “我要监听这个控件的事件”

switch.addTarget(
self, // 目标:事件来了交给“当前控制器”处理
action: #selector(click(_:)), // 用哪个方法来响应
for: .valueChanged // 监听什么事件:开关“值变了”
)

你在这里没有调用 click,只是告诉系统:将来发生事时帮我调它。

第 2 步:用户动手(滑动开关)

  • 用户手指滑开关 → 开关内部检测到 “值变了”
  • 开关内部触发 UIControlEvent.valueChanged 事件

第 3 步:系统自动执行回调(核心!)
等价于系统帮你写了一句:

self.click(switch)

所以:click(_ :) 是系统调用的,不是你手动调用的。

第 4 步:你的 click(_ :)执行

UISegementControl

1.相关属性和UI方面

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

//创建分段控制器控件
let seg:UISegmentedControl = UISegmentedControl(frame: CGRectMake(20, 100, 280, 40))

//设置按钮
seg.insertSegment(withTitle: "第一第一第一第一第一第一个按钮", at: 0, animated: true)
seg.insertSegment(withTitle: "第二个按钮", at: 1, animated: true)

//添加点击事件
seg.addTarget(self, action: #selector(click(_:)), for: .valueChanged)
//设置分段控制器是否保持选中状态
//true表示无法选中
seg.isMomentary = false
//设置宽度的自适应
// seg.apportionsSegmentWidthsByContent = true
//手动设置某个item的宽度
seg.setWidth(60, forSegmentAt: 0)
//设置内容区域的偏移量
seg.setContentOffset(CGSizeMake(10, 10), forSegmentAt: 1)
//手动设置默认选中item
seg.selectedSegmentIndex = 0
//设置渲染映射
seg.tintColor = UIColor.red

self.view.addSubview(seg)
}

@objc func click(_ seg:UISegmentedControl){
print(seg.selectedSegmentIndex,"按钮被点击")
}

2.切换视图方面

先在Main文件中拖取Navigation Controller视图

import UIKit

class ViewController: UIViewController {

//创建两个视图
let viewBlue:UIView = UIView(frame: CGRectMake(0,0,320, 568))
let viewRed:UIView = UIView( frame: CGRectMake(0,0, 320, 568))

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

let seg: UISegmentedControl = UISegmentedControl(items:
["blue", "red"])

seg.addTarget(self, action: #selector(change(_:)),
for: .valueChanged)

self.navigationItem.titleView = seg
viewBlue.backgroundColor = UIColor.blue
viewRed.backgroundColor = UIColor.red

self.view.addSubview(viewBlue)
self.view.addSubview(viewRed)

//先把蓝色的放在上面,就会把红色挡住
self.view.bringSubviewToFront(viewBlue)
seg.selectedSegmentIndex = 0

}
@objc func change(_ seg:UISegmentedControl){
if seg.selectedSegmentIndex == 0 {
self.view.bringSubviewToFront(viewBlue)
}else{
self.view.bringSubviewToFront(viewRed)
}
}
}

UITextField

1.相关属性和UI方面

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

let textField:UITextField = UITextField(frame:
CGRectMake (20, 100, 280, 40))
//设置输入框风格为line
// textField.borderStyle = UITextField.BorderStyle.line

//设置输入框风格为bezel
textField.borderStyle = UITextField.BorderStyle.bezel
//设置输入框的提示文字
textField.placeholder = "请输入文字"
//设置输入字体颜色
textField.textColor = UIColor.red
//设置输入字体样式
textField.font = UIFont.italicSystemFont(ofSize: 15)
//设置文字的对齐方式
textField.textAlignment = NSTextAlignment.center
//设置背景颜色
// textField.backgroundColor = UIColor.red
//是否每次进入编辑状态时都清空输入框中的文字
textField.clearsOnBeginEditing = true
//是否字体大小自适应
textField.adjustsFontSizeToFitWidth = true
//设置输入框为无效
// textField.isEnabled = false
//设置输入框的左视图
let viewLeft:UIView = UIView(frame: CGRectMake (0,0,40,40))
let viewRight:UIView = UIView(frame: CGRectMake(0,0, 40,40))
viewLeft.backgroundColor = UIColor.blue
viewRight.backgroundColor = UIColor.green
textField.leftView = viewLeft
textField.rightView = viewRight
//设置左右视图的显示模式
textField.leftViewMode = UITextField.ViewMode.always
textField.rightViewMode = UITextField.ViewMode.always

//设置弹出的交互键盘
let board:UIView = UIView(frame: CGRectMake (0,0,320,80))
board.backgroundColor = UIColor.orange
// textField.inputView = board
//设置附键盘视图
textField.inputAccessoryView = board

self.view.addSubview(textField)
}
}

2.与用户交互方面

import UIKit

class ViewController: UIViewController,UITextFieldDelegate {

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

let textField:UITextField = UITextField(frame:
CGRectMake (20, 100, 280, 40))
//设置输入框风格为line
// textField.borderStyle = UITextField.BorderStyle.line

//设置输入框风格为bezel
textField.borderStyle = UITextField.BorderStyle.bezel
//设置输入框的提示文字
textField.placeholder = "请输入文字"
//设置输入字体颜色
textField.textColor = UIColor.red
//设置输入字体样式
textField.font = UIFont.italicSystemFont(ofSize: 15)
//设置文字的对齐方式
textField.textAlignment = NSTextAlignment.center
//设置背景颜色
// textField.backgroundColor = UIColor.red
//是否每次进入编辑状态时都清空输入框中的文字
textField.clearsOnBeginEditing = true
//是否字体大小自适应
textField.adjustsFontSizeToFitWidth = true
//设置输入框为无效
// textField.isEnabled = false
//设置输入框的左视图
let viewLeft:UIView = UIView(frame: CGRectMake (0,0,40,40))
let viewRight:UIView = UIView(frame: CGRectMake(0,0, 40,40))
viewLeft.backgroundColor = UIColor.blue
//viewRight.backgroundColor = UIColor.green
textField.leftView = viewLeft
textField.rightView = viewRight
//设置左右视图的显示模式
textField.leftViewMode = UITextField.ViewMode.always
textField.rightViewMode = UITextField.ViewMode.always

//设置弹出的交互键盘
let board:UIView = UIView(frame: CGRectMake (0,0,320,80))
board.backgroundColor = UIColor.orange
// textField.inputView = board
//设置附键盘视图
textField.inputAccessoryView = board

//设置代理
textField.delegate = self
//设置文本框清除按钮的显示模式
textField.clearButtonMode = UITextField.ViewMode.always

self.view.addSubview(textField)
}
//代理方法
//当输入改变时调用的方法
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
print(string)
return true
}
//已经进入编辑状态时调用的方法
func textFieldDidBeginEditing(_ textField: UITextField) {
print("didBegin")
}
//结束编辑状态时调用的方法
func textFieldDidEndEditing(_ textField: UITextField) {
print("didEnd")
}
//将要进入编辑状态时调用的方法
//false表示不能进入编辑状态
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
print("shouldBegin")
return true
}
//将要结束编辑状态时调用的方法
//false表示不能进入结束编辑状态
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
print("shouldEnd")
return true
}
//设置清除键模式是否生效
func textFieldShouldClear(_ textField: UITextField) -> Bool{
return true
}
//点击键盘中return键触发的方法
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}

UISlider

import UIKit

class ViewController: UIViewController {
//创建一个滑块对象
let slider:UISlider = UISlider(frame: CGRectMake(20,100, 280, 40))
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
//滑块控件UISlider

//添加一个控制方法
slider.addTarget(self, action: #selector(slider(_:)), for: .valueChanged)
//设置滑块的取值范围
slider.maximumValue = 100
slider.minimumValue = 1
//设置是否在滑动时持续触发方法
//false代表停止滑动时才触发方法
slider.isContinuous = true
//设置滑动轴的颜色
slider.minimumTrackTintColor = UIColor.red
slider.maximumTrackTintColor = UIColor.yellow

self.view.addSubview(slider)
}

@objc func slider(_ mysl:UISlider){
print(mysl.value)
}
//点击屏幕滑块到任意位置
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
slider.setValue((Float)(arc4random()%99+1), animated: true)
}
}

UISlider的实操

实现通过滑块的滑动改变图片的大小

import UIKit

class ViewController: UIViewController {
let imageView: UIImageView = UIImageView(frame: CGRectMake(0, 0, 320,400))

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

let slider:UISlider = UISlider(frame: CGRectMake(20, self.view.frame.size.height 60,280, 20)) ;
self.view.addSubview(slider);

slider.addTarget(self, action: #selector(slider(_:)),
for: .valueChanged)

slider.maximumValue = 100
slider.minimumValue = 0

imageView.image = UIImage(named:"p1.jpg")
self.view.addSubview( imageView)
}

@objc func slider(_ mysl:UISlider){
let value:Float = 1mysl.value/100

imageView.bounds = CGRectMake(0, 0,320*(CGFloat) (value), 400*(CGFloat) (value))
}
}

UIActivityIndicatorView

import UIKit

class ViewController: UIViewController {
//创建一个活动提示控件
let act:UIActivityIndicatorView = UIActivityIndicatorView(frame: CGRect(x: 320/210, y: 568/2, width: 20, height: 20))
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

// UIActivityIndicatorView — 加载时出现的小圈圈

self.view.backgroundColor = UIColor.gray

//设置提示圈颜色
act.color = UIColor.red

//使用时要设置开始动画
act.startAnimating()

self.view.addSubview(act)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
//停止活动
act.stopAnimating()
}
}

UIProgressView

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

//进度条控件

let progress:UIProgressView = UIProgressView(progressViewStyle: UIProgressView.Style.default)

progress.frame = CGRect(x: 20, y: 100, width: 280, height: 20)

//设置进度条进度 0-1
progress.progress = 0.5
//设置走过的进度颜色
progress.progressTintColor = UIColor.red
//设置没走过的进度颜色
progress.trackTintColor = UIColor.green

self.view.addSubview(progress)
}
}

UIPageControl

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

//创建一个分页控制器
let page:UIPageControl = UIPageControl(frame: CGRect(x: 150, y: 100, width: 100, height: 30))

self.view.backgroundColor = UIColor.red

//设置分页页数
page.numberOfPages = 4
//设置当前页码,下标从0开始
page.currentPage = 3
//设置只有一页时,是否自动隐藏
//true代表会自动隐藏
page.hidesForSinglePage = false
//设置分页控制器的当前页颜色
page.currentPageIndicatorTintColor = UIColor.blue
//设置分页点颜色
page.pageIndicatorTintColor = UIColor.purple

//添加方法
page.addTarget(self, action: #selector(change(_:)), for: .valueChanged)

self.view.addSubview(page)
}

@objc func change(_ pg:UIPageControl){
print(pg.currentPage) //打印当前页号
}

}

UIStepper

import UIKit

class ViewController: UIViewController {

let label:UILabel = UILabel(frame: CGRect(x: 100, y: 300, width: 100, height: 100))

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

//创建一个Stepper步进控制器
let steper:UIStepper = UIStepper(frame: CGRect(x: 100, y: 100, width: 100, height: 40))

label.text = String(format: "%f", steper.value)

//设置最大值和最小值。默认是[0,100]
steper.maximumValue = 10
steper.minimumValue = 0

//设置步长
steper.stepValue = 2
//是否连续触发响应函数
steper.isContinuous = false
//值是否持续改变
//false表示长按后松手值不会改变
steper.autorepeat = false
//设置到达最值后是否可以循环触发
steper.wraps = true

//设置控件的颜色
steper.tintColor = UIColor.red //err

//添加方法
steper.addTarget(self, action: #selector(change(_:)), for: .valueChanged)

self.view.addSubview(steper)
self.view.addSubview(label)
}

@objc func change(_ steper:UIStepper){
//改变值时显示在标签里
label.text = String(format: "%f", steper.value)
}
}

UIAlertController

1.UIAlertController = 弹窗本身
就是你看到的那个白色框、标题、消息。
2.UIAlertAction = 弹窗里的按钮
就是 “确定”“取消”“删除” 这些可点击的按钮。
3.addAction = 把按钮加到弹窗里

1.AlertView

import UIKit

class ViewController: UIViewController,UIAlertViewDelegate {

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

//使用旧方法创建警告框
// let alertView:UIAlertView = UIAlertView(title: "alert", message: "look me", delegate: self, cancelButtonTitle: "cancel", otherButtonTitles: "sure")
//
// //设置alertView的风格
// alertView.alertViewStyle = UIAlertViewStyle.loginAndPasswordInput
//
// alertView.show()

}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
//使用新方法创建警告框
//UIAlertController不用代理,靠闭包 handler 接收点击事件。
let alertView:UIAlertController = UIAlertController(title: "alert", message: "look me", preferredStyle: UIAlertController.Style.alert)
//添加了一个封装了操作逻辑的按钮
let alertActionOne:UIAlertAction = UIAlertAction(title: "cancel", style: UIAlertAction.Style.destructive, handler: {
(alert) -> Void in print("cancel")
})
//添加一个输入框
alertView.addTextField(configurationHandler: {
(textField) -> Void in textField.placeholder = "hello world"
})
alertView.addAction(alertActionOne)
//弹出警告框
self.present(alertView, animated: true)
}

//代理回调方法
// func alertView(alertView:UIAlertView, clickedButtonAtIndex buttonIndex:Int){
// print(buttonIndex)
// }
}

为什么使用新方法创建警告框要重写在touchesBegan里,不能直接写在viewDidLoad?
1、viewDidLoad 阶段页面还没渲染、控制器还没完成挂载到屏幕上,不能执行 present 弹窗;
2、touchesBegan 是点击屏幕后、页面已经完全加载完毕,此时可以正常弹窗。

2.ActionSheet

import UIKit

class ViewController: UIViewController ,UIActionSheetDelegate{

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

//警告弹窗

//使用旧的方法创建actionSheet
// let sheet: UIActionSheet = UIActionSheet(title: "actionSheet",delegate: self, cancelButtonTitle: "cancel",
// destructiveButtonTitle: "delete")
//
// sheet.show(in: self.view

}
//使用xin的方法创建actionSheet
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
//创建一个警告弹窗
let actionSheet:UIAlertController = UIAlertController(title:"actionSheet", message: "look me", preferredStyle:
UIAlertController.Style.actionSheet)

let actionAction:UIAlertAction = UIAlertAction(title:"one",style: UIAlertAction.Style.default) {(action) -> Void in
print("helle world")
}

let actionActionOther:UIAlertAction = UIAlertAction(title:"cancel", style: UIAlertAction.Style.cancel) { (action) -> Void in print("cancel")
}

actionSheet.addAction(actionAction)
actionSheet.addAction (actionActionOther)

//弹出警告框
self.present(actionSheet, animated: true)
}

//代理方法,点击按钮时触发
// func actionSheet(actionSheet: UIActionSheet, clickedButtonAtIndex buttonIndex: Int) {
// print(buttonIndex)
// }
}

UIScrollView

一共包含两个部分:
相关属性和UI方面+与用户交互方面(代理方法)

import UIKit

class ViewController: UIViewController,UIScrollViewDelegate {

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

//滚动视图
let scrollView:UIScrollView = UIScrollView(frame: self.view.frame )

let view:UIView = UIView(frame:
CGRectMake (100,100,100, 100))
view.backgroundColor = UIColor.red
scrollView.addSubview(view)
//设置scrollerView的内容尺寸
scrollView.contentSize = CGSizeMake(self.view.frame.size.width*2, self.view.frame.size.height*2)
//设置回弹效果
scrollView.bounces = true
//设置指示条的位置
scrollView.scrollIndicatorInsets = UIEdgeInsets(top: 10.0, left: 10.0, bottom: 20.0, right: 20.0)
//设置指示条是否显示
scrollView.showsHorizontalScrollIndicator = true
//设置是否翻页效果
scrollView.isPagingEnabled = true

//设置拉伸和缩放的比值
scrollView.minimumZoomScale = 0.5
scrollView.maximumZoomScale = 2;

//设置代理
scrollView.delegate = self

self.view.addSubview(scrollView)
}
//设置拉伸和缩放操作,返回进行缩放的视图
func viewForZooming(in scrollView: UIScrollView) -> UIView?
{
return scrollView.subviews.first
}
//scrollView减速结束时触发的代理方法
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {

}
//scrollView停止拖拽时触发的方法
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {

}
//scrollView停止动画的时候触发的方法
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {

}
//scrollView停止缩放效果时触发的方法
func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {

}
//scrollView进行缩放效果时触发的方法
func scrollViewDidZoom(_ scrollView: UIScrollView) {

}
//scrollView开始滑动时触发的方法
func scrollViewDidScroll(_ scrollView: UIScrollView) {

}
//scrollVie滑动到顶部时触发的方法
func scrollViewDidScrollToTop(_ scrollView: UIScrollView) {

}
//scrollVie将要滑动到顶部时触发的方法
//false代表不能进行回到顶部的操作
func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool {
return true
}
}

UITableView

UITableView的创建流程+头尾视图的创建+编辑状态的变化+相关代理方法。

1.UITableView的创建的步骤

1.控制器遵守两个协议(必加)
dataSource:提供单元格数据;delegate:处理点击,缺少就空白
2.绑定数据源与代理
3.数据源的三个核心方法
设置分区,设置每个分区的行数,设置每行单元格

2.头尾视图的创建的步骤

首先说明,plain 样式默认没有 Header/Footer 视图。
1.设置头视图的高度
2.必须返回一个view视图,空白占位也要创建View,nil=系统默认空白不生效

3.改变编辑状态的两个步骤

1.设置具体的编辑状态
2.点击左侧删除圆圈触发

import UIKit

//1. 控制器遵守两个协议(必加)
//dataSource:提供单元格数据;delegate:处理点击,缺少就空白
class ViewController: UIViewController ,UITableViewDataSource, UITableViewDelegate{

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

//创建tableView 风格可以是普通和分组两种
let tableView:UITableView = UITableView(frame: self.view.frame,style: UITableView.Style.grouped)
//2.绑定数据源与代理
tableView.dataSource = self
tableView.delegate = self

//重新刷新数据
tableView.reloadData()

//设置tableView的回弹效果
tableView.bounces = false

//设置tableView的编辑状态
tableView.isEditing = true

self.view.addSubview(tableView)
}
//3.数据源的三个核心方法
//分区数
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
// 行数
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10 // 一共10行
}
// 每行单元格
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
cell.textLabel?.text = "第\\(indexPath.row)行"
return cell
}

//plain 样式默认没有 Header/Footer 视图
//必须同时实现【高度方法 + 返回 header 视图】
//1.设置头视图的高度
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 100
}
//2.必须返回一个view,空白占位也要创建View,nil=系统默认空白不生效
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = UIView()
header.backgroundColor = UIColor.red //上色就能直观看到高度
return header
}
//设置尾视图的高度
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 100
}
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footer = UIView()
footer.backgroundColor = UIColor.blue
return footer
}
//设置cell的高度,默认时44
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 60
}

//相关代理方法
//点击cell触发的方法
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("%d, %d", indexPath.section, indexPath.row)
}
//取消选中某个cell触发的方法
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {

}

//1.设置具体的编辑状态
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
return UITableViewCell.EditingStyle.delete
}
//2.点击左侧删除圆圈触发
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
//1.先删除数据源
//xxxx.remove(at: indexPath.row)
//2.再删除单元格
//xxxx.deleteRows(at: [indexPath], with: .automatic)
}else if editingStyle == .insert{
//xxx.append()
}
}

//设置tableView的移动
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
// let str = dataArray?[sourceIndexPath.row]
// dataArray?. removeAtIndex(sourceIndexPath.row)
// dataArray?.insert(str!, atIndex: destinationIndexPath.row)
}
}

UITextView

特点:文字链接化,还包括电话,地址,日历等类型

import UIKit

class ViewController: UIViewController,UITextViewDelegate {

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

let textVew:UITextView = UITextView(frame: CGRectMake(20, 100,280, 100))
textVew.backgroundColor = UIColor.gray

//设置字体
textVew.font = UIFont.systemFont(ofSize: 25)
//设置文字颜色
textVew.textColor = UIColor.red
//设置对齐模式
textVew.textAlignment = NSTextAlignment.center
//设置是否可编辑
textVew.isEditable = true
//设置内容
// textVew.text = "你好,我是textView\\n 网址:www.baidu.coml"
//设置链接化类型
textVew.dataDetectorTypes = UIDataDetectorTypes.link

//设置代理
textVew.delegate = self

self.view.addSubview(textVew)
}
//输入字符时调用
//false代表此时不能输入
func textView(_ textView: UITextView, shouldChangeTextInRanges ranges: [NSValue], replacementText text: String) -> Bool {
return false
}
//开始编辑时调用
func textViewDidBeginEditing(_ textView: UITextView) {

}
//结束编辑时调用
func textViewDidEndEditing(_ textView: UITextView) {

}
//输入改变时调用
func textViewDidChange(_ textView: UITextView) {

}
//改变选中文字时调用
func textViewDidChangeSelection(_ textView: UITextView) {

}
//将要开始编辑时调用
func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
return true
}
//将要结束编辑时调用
func textViewShouldEndEditing(_ textView: UITextView) -> Bool {
return true
}

}

UIPickerView

import UIKit

class ViewController: UIViewController,UIPickerViewDelegate,UIPickerViewDataSource {
var dataArray:Array<String>?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

//UIPickerView类似于UITableView,只不过UIPickerView的表现形式是滚动形式
let pickerView:UIPickerView = UIPickerView(frame: CGRect(x: 100, y: 100, width: 200, height: 150))

//设置数据源和代理
pickerView.delegate = self
pickerView.dataSource = self

dataArray = ["one","two","three","four","five"]

self.view.addSubview(pickerView)
}
//设置分区数
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 2
}
//设置每个分组的行数
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return dataArray!.count
}
//设置每一行的内容
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return dataArray?[row]
}
//设置每个分区的宽度
func pickerView(_ pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat {
return 100
}
}

UIDatePicker

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

//系统帮我们封装好的有关时间的操作

let datePicker:UIDatePicker = UIDatePicker(frame:
CGRectMake (100, 100, 200, 200))
//设置显示模式
datePicker.datePickerMode = UIDatePicker.Mode.dateAndTime

//继承了UIControl,可以添加绑定方法
datePicker.addTarget(self, action: #selector(changeDate(_:)), for: .valueChanged)

self.view.addSubview(datePicker)

}
@objc func changeDate(_ sp:UIDatePicker){
let date = sp.date
print(date)
}

}

UIWebView

要导入头文件 import WebKit

import UIKit
import WebKit

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

//网页视图,类似于一种简洁的网页浏览器
let webView:WKWebView = WKWebView(frame:self.view.bounds)
// 规范URL写法:https(现在苹果禁用http明文)
guard let url = URL(string: "https://www.baidu.com") else { return }

let req = URLRequest(url: url)
webView.load(req)

self.view.addSubview(webView)
}
}

UICollectionView

1.UICollectionView创建的步骤

1.控制器遵守协议
UICollectionViewDataSource:提供 item 个数、创建 cell;
UICollectionViewDelegateFlowLayout:布局、尺寸、边距、头尾部尺寸
布局类:必须搭配UICollectionViewFlowLayout(流式布局,格子排布规则)

2.绑定代理、注册 Cell
创建布局对象
创建collectionView
绑定数据源、代理
注册cell(必填,复用标识)

3.数据源的三个核心数据源方法
设置分区,设置每个分区的行数,设置每行单元格

import UIKit

class ViewController: UIViewController,UICollectionViewDelegateFlowLayout,UICollectionViewDataSource {

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

//有点类似于UITableView,但是比UITableView更强大,不仅仅能设计表格类的布局,还能自定义布局(元素的大小,元素的排列方式)

let layout:UICollectionViewFlowLayout =
UICollectionViewFlowLayout()
//设置布局方向
layout.scrollDirection = UICollectionView.ScrollDirection.horizontal
//设置每个元素的大小
layout.itemSize = CGSizeMake (80, 80)
//设置元素间距
layout.minimumInteritemSpacing = 10
//设置行间距
layout.minimumLineSpacing = 30

let collectionView:UICollectionView = UICollectionView(frame:
self.view.frame, collectionViewLayout: layout)

collectionView.delegate = self
collectionView.dataSource = self

//注册普通 Item 单元格
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cellID")

self.view.addSubview(collectionView)
}

func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 100
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell:UICollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellID", for: indexPath)

cell.backgroundColor = UIColor.red

return cell
}

//可以自定义色块的大小
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let tmp = indexPath.row%3 //0 1 2
if tmp == 0{
return CGSize(width: 50, height: 50)
}else if tmp == 1{
return CGSize(width: 100, height: 100)
}else{
return CGSize(width: 50, height: 50)
}
}
}

其他代理方法:
didSelectItemAt:
它是 UICollectionViewDelegate 协议的核心方法,当用户点击相册中的某张照片 / 视频单元格时,系统会自动调用这个方法。这段代码的核心逻辑是:根据用户点击的资源,调用 toggleSelection 方法来切换选中状态。

trailingSwipeActionsConfigurationForRowAt:处理单元格左滑操作。

contextMenuConfigurationForRowAt:处理单元格长按弹出菜单

2.UICollectionView的实操

做出来一个随机颜色的UICollectionView布局

在这里插入图片描述

自定义布局类MyLayout

import UIKit

class MyLayout: UICollectionViewFlowLayout {

var itemCount:Int? //元素个数
var attributeArray:Array<UICollectionViewLayoutAttributes>? //存放layout中的布局属性

override func prepare(){
super.prepare()
attributeArray = Array()
//计算每个元素的宽度
let Width = (UIScreen.main.bounds.size.width self.minimumInteritemSpacing) / 2
//循环设置每个元素的布局属性
var l = 0 //左边 列高
var r = 0 //右边 列高
for i in 0..<itemCount!{
let indexPath = NSIndexPath(item: i, section: 0)
let atti = UICollectionViewLayoutAttributes(forCellWith: indexPath as IndexPath)
//哪一个列高更小元素放在那一边
let height = (Int)(arc4random()%140 + 50) //随机高度
var tmp = 0//记录元素放在哪一列,0是第一列,1是第二列
var H = 0
if(l <= r){
H = l
l += (height + (Int)(self.minimumLineSpacing))
tmp = 0

}else{
H = r
r += (height + (Int)(self.minimumLineSpacing))
tmp = 1

}
//每个元素块的放置位置和大小
atti.frame = CGRect(x: Int((CGFloat)(tmp) * (Width + self.minimumInteritemSpacing)), y: (Int)(H), width: (Int)(Width), height: height)
attributeArray?.append(atti)
}
if l <= r{
self.itemSize = CGSize(width: Width, height: CGFloat((r * 2 / itemCount!)) self.minimumLineSpacing)
}else{
self.itemSize = CGSize(width: Width, height: CGFloat((l * 2 / itemCount!)) self.minimumLineSpacing)
}
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return attributeArray
}
}

ViewController.swift

import UIKit

class ViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDataSource {

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

let myLayout = MyLayout()
myLayout.itemCount = 100

let collectionView:UICollectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: myLayout)

collectionView.delegate = self
collectionView.dataSource = self

collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cellID")

self.view.addSubview(collectionView)

}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 100
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellID", for: indexPath)

//给cell设置随机色
cell.backgroundColor = UIColor(red: CGFloat((CFloat)(arc4random()%255)/255.0), green: CGFloat((CFloat)(arc4random()%255)/255.0), blue: CGFloat((CFloat)(arc4random()%255)/255.0), alpha: 1)

return cell
}
}

UIStackView

用来垂直排列所有卡片的容器,它的好处是自动处理间距,不用手动给每个卡片加垂直约束。

一、核心布局属性(最常用)

1.axis:排列方向(主轴)

可选值:
.horizontal:水平排列(默认)
.vertical:垂直排列
作用:决定子视图是一行排开,还是一列排开。

stackView.axis = .vertical

2.distribution:主轴方向分布方式
主轴:axis 指定的方向(水平 / 垂直)。
可选值(5 种):

.fill(默认)
拉伸子视图填满主轴空间
按 Content Hugging/Compression Resistance 决定谁被拉伸
.fillEqually
所有子视图等宽 / 等高(平分空间)
.fillProportionally
按子视图固有内容大小比例分配空间
.equalSpacing
子视图尺寸不变,间距自动相等
首尾也有空白间距
.equalCentering
子视图中心间距相等
视图不拉伸,适合图标 + 文字均匀分布

在这里插入图片描述
3.alignment:交叉轴对齐方式
交叉轴:与 axis 垂直的方向。

可选值:
.fill(默认):子视图填满交叉轴
.leading / .top:靠起始边(水平→上对齐;垂直→左对齐)
.trailing / .bottom:靠结束边
.center:居中对齐

// 水平stackView,子视图垂直居中
stackView.alignment = .center

4.spacing:子视图之间的间距

单位:pt
默认:0
作用:相邻子视图之间的最小间距Apple Developer
注意:distribution = .equalSpacing 时,spacing 是最小间距,实际会更大。

stackView.spacing = 10

二、边距与基线相关(常用)

5.isLayoutMarginsRelativeArrangement
核心作用:

  • 控制 StackView 的子视图是否以 layoutMargins 作为边界来布局。
  • 默认值:false,子视图直接贴着 StackView 的边缘排列,不会留出内边距。

开启 true 时的效果:

  • 子视图会自动和 layoutMargins 保持距离,不会顶到边缘;
  • 你可以通过 stackView.layoutMargins 设置上下左右的内边距,子视图会自动适应。

典型用法:

stackView.isLayoutMarginsRelativeArrangement = true
stackView.layoutMargins = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)

开启后,子视图就会和 StackView 边缘保持 16pt 的边距,不用再给每个子视图单独设置 leading/trailing 约束。

6.isBaselineRelativeArrangement
核心作用:

  • 控制 垂直方向 子视图之间的间距,是按「视图顶部」计算,还是按「文字基线」计算。
  • 默认值:false,间距是按子视图的 frame 边界计算的。

开启 true 时的效果

  • 垂直 StackView 中,两个带文字的控件(比如两个 UILabel)之间的间距,会从上一行文字的基线,算到下一行文字的基线,而不是从控件的顶部 / 底部计算。
  • 这样多行文本的排版会更整齐,视觉上的间距也更均匀。

举个直观例子
比如两个高度不同的 UILabel:

  • false:间距按控件底部到下一个控件顶部计算,文字可能看起来挤在一起;
  • true:间距按文字基线计算,两行文字的距离会更一致,排版更舒服。

适用场景:

  • 垂直排列多行文本、标签、按钮,希望文字对齐更自然。
  • 表单、说明文字、多行列表等排版场景。

小建议:

  • 做卡片 / 列表:isLayoutMarginsRelativeArrangement = true 基本是必开的;
  • 做多行文本:isBaselineRelativeArrangement = true 能让排版好看很多。

三、子视图管理属性

7.arrangedSubviews

var arrangedSubviews: [UIView] { get }

只读数组:当前被 StackView 管理的子视图。
区别:

  • addArrangedSubview(view):加入 arrangedSubviews,自动布局
  • addSubview(view):仅添加到视图层级,不自动布局

8.addArrangedSubview(_ :) / removeArrangedSubview(_ :)

func addArrangedSubview(_ view: UIView)
func removeArrangedSubview(_ view: UIView)

  • 添加 / 移除受管理的子视图
  • removeArrangedSubview 不会把 view 从父视图移除(只是不再管理布局)

UIViewController

Controller是将view和逻辑结合的控制器层。
本节学习的是ViewController的生命周期的相关方法。

先在main文件里再拖拽一个ViewController2界面,创建一个ViewController2.swift文件与这个界面关联,在第一个ViewController界面中放入一个“跳转”按钮,与第二个界面关联。

下面代码是在ViewController2.swift文件里写的:

import UIKit

class ViewController2: UIViewController {

var tmp:Int = 0

override func loadView() {
super.loadView()
tmp += 1
print(tmp, "loadView")
}

override func viewDidLoad() {
super.viewDidLoad()
tmp += 1
print(tmp, "viewDidLoad")

// Do any additional setup after loading the view.
}
//视图将要展示时调用的方法
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
tmp += 1
print(tmp, "viewWillAppear")
}
//将要布局子视图
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
tmp += 1
print(tmp, "viewWillLayoutSubviews")
}
//已经布局子视图完成
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tmp += 1
print(tmp, "viewDidLayoutSubviews")
}
//视图已经展示
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
tmp += 1
print(tmp, "viewDidAppear")
}
//视图将要消失
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
tmp += 1
print(tmp, "viewWillDisappear")
}
//视图已经消失
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
tmp += 1
print(tmp, "viewDidDisappear")
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
//返回上一个controller
self.dismiss(animated: true, completion: nil)
}

从点击“跳转”到结束过程如下:
在这里插入图片描述

UINavigationController

UINavigationController 就是一个 “栈管理器”。
它用 栈(先进后出)结构 来管理一堆 UIViewController,是层级结构,负责:
1.压入页面(push)
2.弹出页面(pop)
3.显示顶部页面
4.自动生成导航栏(返回按钮、标题)

main文件准备

拖拽到导航界面

在这里插入图片描述

把View Controller界面与ViewController类关联

ViewController.swift文件

1、NavigationController页面与ViewController的切换
2、导航栏设置
导航栏标题规则:导航栏永远读取当前栈顶控制器的 title

  • 首页在栈顶 → 显示首页
  • push 新页面后新 VC 变成栈顶 → 显示新 VC 的 title(没赋值就空白)

iOS15之后的导航栏不显示且无色,要强制显示并设置背景颜色。
3、导航栏按键的自定义

import UIKit

//导航栏标题规则:导航栏永远读取当前栈顶控制器的 title
//-首页在栈顶 → 显示首页
//-push 新页面后新 VC 变成栈顶 → 显示新 VC 的 title(没赋值就空白)

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

// 内容自动从导航栏下方开始
edgesForExtendedLayout = []
// 强制显示导航栏
navigationController?.setNavigationBarHidden(false, animated: false)
// iOS15+强制显示导航栏底色(默认导航栏透明无底色)
let app = UINavigationBarAppearance()
app.backgroundColor = .gray
navigationController?.navigationBar.standardAppearance = app
navigationController?.navigationBar.scrollEdgeAppearance = app

self.title = "首页"

let label:UILabel = UILabel(frame: CGRect(x: 100, y: 100, width: 100, height: 30))
label.backgroundColor = UIColor.red
label.text = "hello world"

let button:UIButton = UIButton(frame: CGRect(x: 100, y: 200, width: 100, height: 30))
button.backgroundColor = UIColor.green
button.setTitle("切换", for: .normal)
button.addTarget(self, action: #selector(changeController(_:)), for: .touchUpInside)

//自定义导航栏按钮
let barButtonItem:UIBarButtonItem = UIBarButtonItem(title: "返回", style: .plain, target: self, action:#selector(back))

//只能对UI方面进行修改,无法触发方法
//self.navigationItem.backBarButtonItem = barButtonItem

self.navigationItem.leftBarButtonItem = barButtonItem
//使用系统的左右按键样式
let barR1 = UIBarButtonItem(barButtonSystemItem:
UIBarButtonItem.SystemItem.bookmarks, target:self, action:#selector(action1))

let barR2 = UIBarButtonItem(barButtonSystemItem:
UIBarButtonItem.SystemItem.camera, target: self, action:#selector(action2))
self.navigationItem.rightBarButtonItems = [barR1, barR2]

//系统的工具栏
//self.navigationController?.isToolbarHidden = false
//self.toolbarItems = [barR1, barR2]

self.view.addSubview(label)
self.view.addSubview(button)
}
@objc func changeController(_ bnt:UIButton){
let viewController:UIViewController = UIViewController()
//给新添加的页面设背景色
viewController.view.backgroundColor = UIColor.white
viewController.title = "标题2"
// 关键:自定义返回按钮文字(在上一页设置,不是新页面)
let backItem = UIBarButtonItem(title:"首页", style:.plain, target:nil, action:nil)
navigationItem.backBarButtonItem = backItem

self.navigationController?.pushViewController(viewController, animated: true)
}
@objc func back(){
print("返回")
}
@objc func action1() {
print("action1")
}
@objc func action2 () {
print("action2")
}

}

NavigationController的常用属性

一、最最常用

1.navigationBar
导航条本身(顶部那一条)

navigationController?.navigationBar

你可以设置它的颜色、字体、背景、高度、隐藏分割线等。
2.viewControllers
栈里所有控制器(数组)

navigationController?.viewControllers

  • 第一个 = 根控制器
  • 最后一个 = 当前显示的控制器

3.topViewController
当前最顶部的控制器

navigationController?.topViewController

4.visibleViewController
当前正在显示的控制器(和 top 基本一样)

二、显示 / 隐藏导航栏

5.isNavigationBarHidden
隐藏 / 显示导航条

navigationController?.isNavigationBarHidden = true // 隐藏
navigationController?.isNavigationBarHidden = false // 显示

带动画隐藏:

navigationController?.setNavigationBarHidden(true, animated: true)

三、导航栏外观(最常用)

6.navigationBar.tintColor

导航条上按钮颜色(返回键、文字图标)

navigationController?.navigationBar.tintColor = .red

7.navigationBar.barTintColor
导航条背景颜色

navigationController?.navigationBar.barTintColor = .white

8.navigationBar.titleTextAttributes
导航标题字体、颜色

navigationController?.navigationBar.titleTextAttributes = [
.foregroundColor: UIColor.black,
.font: UIFont.systemFont(ofSize: 17, weight: .bold)
]

9.isTranslucent
导航条半透明(默认 true)

navigationController?.navigationBar.isTranslucent = false

  • true:内容会从导航栏底下穿过
  • false:内容从导航栏底部开始

10.去掉导航栏底部分割线(超级常用)

navigationController?.navigationBar.shadowImage = UIImage()
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)

四、手势(侧滑返回)

11.interactivePopGestureRecognizer
侧滑返回手势

// 关闭侧滑返回
navigationController?.interactivePopGestureRecognizer?.isEnabled = false

五、页面切换(方法)

12.pushViewController 进入下一页

navigationController?.pushViewController(vc, animated: true)

13.popViewController 返回上一页

navigationController?.popViewController(animated: true)

14.popToRootViewController 回到根控制器

navigationController?.popToRootViewController(animated: true)

UITabBarController

UITabBarController = 底部导航栏容器控制器

  • 它是一个容器,专门管理多个并列页面
  • 屏幕底部那一排可点击的按钮,就是它自带的 UITabBar
  • 点击按钮 → 自动切换不同页面

关键点:

  • 永远只显示一个子页面(当前选中的)
  • 子页面之间是并列关系,不是栈
  • 每个子页面最好套一层导航控制器(UINavigationController),这样才能 push 跳转

/////////////////////////////////////////////////////////////////////////////////////////////

UIStoryboard

在这里插入图片描述

UIStoryboard(name:bundle:) 是 iOS 中用来加载 Storyboard 文件的初始化方法。
参数:
name:要加载的 Storyboard 文件名(不带 .storyboard 后缀)
bundle:要从哪个「资源包」里找这个文件,一般传 nil 表示从当前 App 的主 Bundle 中加载

约束constraint

在 iOS 里,AutoLayout(自动布局)= 用 “约束公式” 代替 frame。

1.写法

piece.leadingAnchor.constraint(equalTo: cornerContainer.leadingAnchor, constant: x)
piece.topAnchor.constraint(equalTo: cornerContainer.topAnchor, constant: y)
piece.widthAnchor.constraint(equalToConstant: )

这叫 Layout Anchors(锚点约束),是苹果推荐的、最简洁的写法。

最容易混的:equalTo 到底 “等于” 谁?

【谁.锚点】.constraint(equalTo:【和谁.锚点】, constant: 偏移)
左边:我自己(要布局的控件)
equalTo 右边:参照物(父 view 或别的控件)
constant:我相对于参照物的偏移

1.位置约束:leadingAnchor / topAnchor

piece.leadingAnchor.constraint(equalTo: cornerContainer.leadingAnchor, constant: x)

  • leadingAnchor = 左边那条线
  • equalTo: 父视图的 leadingAnchor = 和父视图左边对齐
  • constant: x = 向右偏移 x 个点(x 为负就向左)

同理:

  • topAnchor = 上边那条线,constant: y 就是向下偏移 yApple Developer。

一句话:

  • leading + top 就是用来定 “左上角坐标” 的。

2.大小约束:widthAnchor / heightAnchor

piece.widthAnchor.constraint(equalToConstant: length)
piece.heightAnchor.constraint(equalToConstant: width)

  • equalToConstant: 数值 = 固定宽 / 高,不依赖别的 view。
  • 横线:width = 长,height = 粗
  • 竖线:width = 粗,height = 长

一句话:

  • width + height 就是用来定 “矩形尺寸” 的。

2.关键点

1.关掉 autoresizing(必须!)

piece.translatesAutoresizingMaskIntoConstraints = false

意思:不用旧的 frame 布局,全权交给约束。

2.约束要激活

// 写法1:单个激活
c.isActive = true

// 写法2:批量激活(推荐)
NSLayoutConstraint.activate([
piece.leadingAnchor.constraint(),
piece.topAnchor.constraint()
])

不激活 = 约束只是创建了,没生效。

3.父子关系要先建立

cornerContainer.addSubview(piece)

必须先 addSubview,再加约束,否则崩溃。

3.总结

leadingAnchor / topAnchor → 定坐标(x,y)
widthAnchor / heightAnchor → 定宽高
equalTo: → 相对另一个 view
equalToConstant: → 固定数值
必须:translatesAutoresizingMaskIntoConstraints = false + 激活约束。

CAShapeLayer

一、CAShapeLayer 是什么?

CAShapeLayer = 专门用来画矢量图形的图层

  • CAShapeLayer:矢量绘图层(CALayer 子类),只负责渲染形状、线条、颜色
  • UIBezierPath:路径容器,定义点、线、圆、圆弧、多边形等轮廓

和普通 UIView 区别:

  • UIView:靠 frame 画矩形、图片
  • CAShapeLayer:画任意形状(圆、弧、线、多边形、曲线)

二、使用步骤

1.使用UIBezierPath创建路径(path)
2.创建 CAShapeLayer对象layer
3.layer.path = path.cgPath
4.设置颜色、线宽
5.加到视图 layer 上(layer.addSublayer)

// 1. 构造路径
let path = UIBezierPath()
// 2. 构造绘图层
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath // 关键:转 CGPath
// 3. 样式配置
shapeLayer.strokeColor = UIColor.xxx.cgColor
shapeLayer.fillColor = UIColor.xxx.cgColor
shapeLayer.lineWidth = 数值
// 4. 添加到视图
view.layer.addSublayer(shapeLayer)

三、CAShapeLayer 最常用属性

1.path

  • 形状路径
  • 必须传 CGPath
  • 用 UIBezierPath 生成

shapeLayer.path = path.cgPath

2.strokeColor

  • 线条颜色
  • 必须是 CGColor

shapeLayer.strokeColor = UIColor.blue.cgColor

3.fillColor

  • 填充颜色
  • 只想画线,必须设为透明

shapeLayer.fillColor = UIColor.clear.cgColor

4.lineWidth

  • 线条宽度(pt)

shapeLayer.lineWidth = 4

5.lineCap

  • 线头样式

.butt 默认直角
.round 圆头
.square 方头

shapeLayer.lineCap = .round

6.lineJoin

  • 线条拐角样式

.miter 直角
.round 圆角
.bevel 斜角

shapeLayer.lineJoin = .round

7.lineDashPattern

  • 画虚线(常用)

//→ 实线 5pt + 空 3pt
shapeLayer.lineDashPattern = [5,3] as [NSNumber]

8.strokeStart / strokeEnd

  • 控制线条画多少
  • 做扫描动画、进度条、路径动画必备

四、UIBezierPath 常用方法(画形状用)

1.基础移动 & 直线(画单条线、折线、L 型)

let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: 0)) // 抬起画笔,移动到起点
path.addLine(to: CGPoint(x: 50, y: 0))// 画直线
path.addLine(to: CGPoint(x: 50, y: 50))// 折角,组成 L 型

2.圆弧 / 圆形(圆环、圆角拐角、整圆)
① 整圆(快门按钮、圆形图标)

let center = CGPoint(x: 40, y: 40) // 圆心
let path = UIBezierPath(
arcCenter: center,
radius: 30, // 圆半径
startAngle: 0, // 起始角度(弧度)
endAngle: 2 * .pi, // 结束角度,2π = 360° 整圆
clockwise: true // 是否顺时针绘制
)

clockwise: true:顺时针绘制圆弧
clockwise: false:逆时针绘制圆弧
它决定了画笔从 startAngle 到 endAngle 是往哪个方向走,直接影响圆弧的形状和位置。

② 局部圆弧(做圆角拐角核心)

// 画 90° 圆弧(L型拐角圆角)
path.addArc(
withCenter: CGPoint(x: 20, y: 20), // 圆弧圆心
radius: 8, // 圆角半径
startAngle: .pi/2, // 起始角度
endAngle: 0, // 结束角度
clockwise: true
)

角度速记(弧度):
0 → 向右
.pi/2 → 向下
.pi → 向左
-.pi/2 → 向上

3.圆角矩形(卡片、带圆角边框)

let rect = CGRect(x: 0, y: 0, width: 200, height: 100)
let path = UIBezierPath(roundedRect: rect, cornerRadius: 12)

4.虚线

let path = UIBezierPath()
path.move(to: CGPoint(x: 10, y: 20))
path.addLine(to: CGPoint(x: 200, y: 20))

let layer = CAShapeLayer()
layer.path = path.cgPath
layer.lineDashPattern = [4,4] // 实线4pt,间隔4pt

五、CAShapeLayer 使用场景

1.画圆角 L 型角(你现在的扫描框)
直角 → 圆角
用路径 + 圆弧实现
2.画圆环(快门按钮)
多层圆环
填充透明,只画线
3.圆角矩形卡片
比 cornerRadius 更流畅、不耗性能
4.虚线、分隔线

lineDashPattern = [4,4]

5.扫描动画、波浪动画、圆弧进度条
靠 strokeEnd 从 0→1 动画
6.任意不规则图形
曲线、箭头、标签气泡、图标
7.带圆角的线条
比如你现在的圆滑边角

UIGraphicsGetCurrentContext

一、核心作用

  • 获取当前的图形上下文(CGContext)
  • 你在draw(_:)里画线条、形状、文字、图片时,必须先拿到这个上下文
  • 本质上是一个全局状态指针,记录当前绘制的画布、画笔样式、坐标系统等信息

二、基础用法(标准场景:UIView 的 draw 方法)

override func draw(_ rect: CGRect) {
// 1. 获取当前上下文(必须在 draw 方法里调用)
guard let ctx = UIGraphicsGetCurrentContext() else { return }

// 2. 开始绘制
// 示例:画一个红色圆形
ctx.setFillColor(UIColor.red.cgColor)
ctx.addEllipse(in: CGRect(x: 50, y: 50, width: 100, height: 100))
ctx.fill()
}

UIGraphicsGetCurrentContext() 就是获取当前 “画布” 的入口,是所有自定义绘制代码的起点,没有它就无法执行任何 Core Graphics 绘制操作。

赞(0)
未经允许不得转载:171主机测评 » UIkit的基本框架
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址