在2022年 Apple WWDC 开发者大会中, UIkit框架增加了一些新特性, 本文将介绍 UIkit相关的API.
1. UICalendarView iOS16 新增的日历控件
- 初始化UICalendarView
let calendarView = UICalendarView()
calendarView.frame = CGRect.init(x: 0.0, y: 100.0, width: 375.0, height: 300.0)
calendarView.delegate = self // 设置代理
let gregorianCalendar = Calendar(identifier: .gregorian)
calendarView.calendar = gregorianCalendar // 跟日历有关的属性
view.addSubview(calendarView)
- 单选的模式
let multiDateSection = UICalendarSelectionSingleDate(delegate: self)
multiDateSection.selectedDate = selectDate // 默认选择日期
calendarView.selectionBehavior = multiDateSection
- 多选模式
let multiDateSection = UICalendarSelectionMultiDate(delegate: self)
multiDateSection.selectedDates = [] // 默认选择多个日期
calendarView.selectionBehavior = multiDateSection
- UICalendarViewDelegate 日历控件代理数据源
这里主要返回一个自定义视图, 显示在日历数字下边区域, 跟 UITableView 自定义 cell 差不多
extension CalendarViewController: UICalendarViewDelegate {
func calendarView(_ calendarView: UICalendarView, decorationFor dateComponents: DateComponents) -> UICalendarView.Decoration? {
if dateComponents.day == selectDate.day && dateComponents.year == selectDate.year, dateComponents.month == selectDate.month {
return UICalendarView.Decoration.customView {
let label = UILabel(frame: CGRect(x: 0.0, y: 0.0, width: 50.0, height: 30.0))
label.textColor = .red
label.font = UIFont.systemFont(ofSize: 10.0)
label.text = "今"
return label
}
} else {
return .none
}
}
}
- UICalendarSelectionSingleDateDelegate 单选模式下代理回调
//MARK: - UICalendarSelectionSingleDateDelegate
extension CalendarViewController: UICalendarSelectionSingleDateDelegate {
func dateSelection(_ selection: UICalendarSelectionSingleDate, didSelectDate dateComponents: DateComponents?) {
if let date = dateComponents {
self.selectDate = date
}
print(self.selectDate)
}
}
- UICalendarSelectionMultiDateDelegate 多选模式下代理回调
extension CalendarViewController : UICalendarSelectionMultiDateDelegate {
// 选中某个日期回调 跟 tableView didSeselectCellAtIndexPath 类同
func multiDateSelection(_ selection: UICalendarSelectionMultiDate, didSelectDate dateComponents: DateComponents) {
self.selectDate = dateComponents
print(self.selectDate)
}
// 取消选中某个日期回调 跟 tableView didDeselectCell 类同
func multiDateSelection(_ selection: UICalendarSelectonMultiDate, didDeselectDate dateComponents: DateComponents) {
}
// 某个日期是否可以选中
func multiDateSelection(_ selection: UICalendarSelectionMultiDate, canSelectDate dateComponents: DateComponents) -> Bool {
return true
}
// 某个日期是否可以取消选中
func multiDateSelection(_ selection: UICalendarSelectionMultiDate, canDeselectDate dateComponents: DateComponents) -> Bool {
return true
}
}
2. UIPageControl 新增API特性
var direction: UIPageControl.Direction // 指示器方向 类型 scrollview 垂直/水平布局
open var preferredIndicatorImage: UIImage? //未选中指示器图片
open var preferredCurrentPageIndicatorImage: UIImage? // 当前选中指示器图片
// 指示器排布方向
public enum Direction : Int, @unchecked Sendable {
/// 页面指示器按系统区域设置的自然方向布置。
/// 默认情况下,这相当于 LTR 语言环境中的 @c UIPageControlDirectionLeftToRight,并且
UIPageControlDirectionRightToLeft 在 RTL 语言环境中。
// 大概意思就是如果是从左到右阅读的国家 natural = leftToRight, 如果是从右到左阅读习惯的国家 比如沙特阿拉伯, natural = rightToLeft. 跟文字排版对齐方式 baseLine 区分不同语言文字排版类似
case natural = 0
// 从左到右
case leftToRight = 1
// 从右到左
case rightToLeft = 2
// 从顶部到底部
case topToBottom = 3
// 从底部到顶部
case bottomToTop = 4
}
从左到右排列
从右向左排列
从顶部到底部排列 注意 frame.width 和 frame.height 尺寸 左侧: 从顶部到底部排列 右侧: 从底部到顶部排列
let pageControl = UIPageControl(frame: CGRect(x: 0.0, y: 400.0, width: 375.0, height: 50.0))
pageControl.backgroundColor = .lightGray
pageControl.numberOfPages = 5
pageControl.currentPage = 0
pageControl.preferredIndicatorImage = UIImage(named: "pageControlDot")
pageControl.preferredCurrentPageIndicatorImage = UIImage(named: "pageControlCurrentDot")
view.addSubview(pageControl)
3. 新增 UIPasteControl 类
@available(iOS 16.0, *)
其实这就是一个按钮
@MainActor open class UIPasteControl : UIControl {
配置信息
open var configuration: UIPasteControl.Configuration { get }
目标
weak open var target: UIPasteConfigurationSupporting?
构造方法
public init(configuration: UIPasteControl.Configuration)
public init?(coder: NSCoder)
public init(frame: CGRect)
}
提供了 UIPasteControl 所需要的一些样式
@MainActor open class Configuration : NSObject, NSSecureCoding {
展示方式 文字图片摆放位置
iconAndLabel: 同时显示 label 和 image
iconOnly: 只显示图片
labelOnly: 只显示 label
open var displayMode: UIPasteControl.DisplayMode
open var cornerStyle: UIPasteControl.CornerStyle
背景颜色
open var baseForegroundColor: UIColor?
前景色
open var baseBackgroundColor: UIColor?
}
let button = UIPasteControl()
button.addTarget(self, action: #selector(paseButtonClick), for: .touchUpInside)
button.configuration.displayMode = .iconAndLabel
button.configuration.cornerStyle = .capsule
button.configuration.baseBackgroundColor = .yellow
button.configuration.baseForegroundColor = .green
button.frame = CGRect(x: 100.0, y: 400.0, width: 100.0, height: 50.0)
self.view.addSubview(button)
官方文档也没有讲这个 UIPasteControl 是来做什么的, 猜测跟粘贴板有关, 还有应用顶部粘贴板有内容时 隐私弹窗有关系. 感觉用处不大
4. 在 UIKit 中使用 SwfitUI
WWDC2022很多地方都提到了 SWiftUI, 比如有 70%新提交应用使用了 SWiftUI, iOS 系统 APP 使用了SWiftUI重写, macOS的偏好设置就是用SWiftUI重写的. 从苹果不遗余力的推销SWiftUI 可以看出来, 是时候学习 swiftUI并提高开发效率, 在 what's new in xocde 中有关于 swift 实时预览新特性介绍.
废话不多说 直接上代码 UITableViewCell 支持 SwiftUI 来构造 cell
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "kCellIdentifier", for: indexPath)
// 把 swfitUI 代码 写到 UIHostingConfiguration 闭包内部
cell.contentConfiguration = UIHostingConfiguration(content: {
HStack(alignment: .top) {
Text("Hello world")
Image(systemName: "square")
}
})
return cell
}
同样的 UICollectionView 同样有个contentConfiguration 属性, 不再演示给大家了. 只是想告诉大家, 苹果这次真的重视SwiftUI, 让 iOS 程序员从繁杂的 UI 工作中解脱出来, 只需要关注 app 业务本身, 而不是把时间耗在写 UI 调试 UI 上边.
5. 其他的一些新特性
- 其他还有一些 SF 图片设置颜色 根据进度条显示不同颜色
跟 swift 并发有关的 API
以上内容来源于苹果 WWDC2022 开发者大会 Session, 欢迎大家去收看 developer.apple.com/videos/play…