SwiftUI和UIkit方面的问题
我是初学者,简单的用法问题,我已精简了程序,这一段程序放入就可运行。程序是一个年月日时分选择器,但是在选择月份的时候,日期始终是31天,没有改变。
我也做了调试,发现返回行数那个函数三次后读取的数值就变成初始值了,也就是8月,8月就是31天,这是为什么?为什么值会变(return parent.myDate.GetDays(yy: parent.myDate.year, mm: parent.myDate.month)这里面的month变了)。我试着在里面读取所选行数selectedRow,代码我注释了,这样能得到正确的结果,但这不是好的处理方式。因为这样处理也有问题,就是阴阳历转换的时候,你没办法从所选的索引读出是阳历还是阴历,最终还是要把参数传进来。
求告知,多谢。
import SwiftUI
import UIKit
// `SimplePicker` 是一个 SwiftUI 视图,它使用 `UIViewRepresentable` 协议将 `UIPickerView` 包装成 SwiftUI 视图。
struct SimplePicker2: UIViewRepresentable {
@Binding var myDate: MyDateStruct2
let minYear: Int = 1900
let maxYear: Int = 2100
// 创建并返回 `UIPickerView` 实例
func makeUIView(context: Context) -> UIPickerView {
let pickerView = UIPickerView()
pickerView.delegate = context.coordinator // 设置代理
pickerView.dataSource = context.coordinator // 设置数据源
pickerView.selectRow(myDate.year - myDate.minYear, inComponent: 0, animated: false)
pickerView.selectRow(myDate.month - 1, inComponent: 1, animated: false)
pickerView.selectRow(myDate.day - 1, inComponent: 2, animated: false)
pickerView.selectRow(myDate.hour - 1, inComponent: 3, animated: false)
pickerView.selectRow(myDate.minute - 1, inComponent: 4, animated: false)
return pickerView
}
// 当 SwiftUI 需要更新视图时调用,这里不需要更新视图,所以为空实现
func updateUIView(_ uiView: UIPickerView, context: Context) {
uiView.reloadAllComponents()
uiView.selectRow(myDate.year - myDate.minYear, inComponent: 0, animated: false)
uiView.selectRow(myDate.month - 1, inComponent: 1, animated: false)
uiView.selectRow(myDate.day - 1, inComponent: 2, animated: false)
uiView.selectRow(myDate.hour - 1, inComponent: 3, animated: false)
uiView.selectRow(myDate.minute - 1, inComponent: 4, animated: false)
}
// 创建并返回 `Coordinator` 实例
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
// `Coordinator` 类负责处理 `UIPickerView` 的委托和数据源方法
class Coordinator: NSObject, UIPickerViewDelegate, UIPickerViewDataSource {
var parent: SimplePicker2
// 初始化 `Coordinator` 实例,保存对 `SimplePicker` 的引用
init(_ pickerView: SimplePicker2) {
self.parent = pickerView
}
// 返回选择器的列数 年月日时分 所有五列
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 5 // parent.data.count
}
// 返回某列的行数
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
switch component {
case 0: // 年
return parent.maxYear - parent.minYear + 1
case 1: // 月
return 12
case 2: // 日
//let month = pickerView.selectedRow(inComponent: 1) + 1
return parent.myDate.GetDays(yy: parent.myDate.year, mm: parent.myDate.month)
case 3: // 时
return 24
case 4: // 分
return 60
default: // 秒或者错误 其实没有秒的
return 60
}
}
// 返回某列某行的标题
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
switch component {
case 0: // 年
return "\(row + parent.minYear)"
case 1: // 月
return "\(row + 1)月"
case 2: // 日
return "\(row + 1)日"
case 3: // 时
return "\(row)"
case 4: // 分
return "\(row)"
default: // 秒或者错误 其实没有秒的
return "\(row)"
}
}
// 处理选择事件,打印选择的值
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
switch component {
case 0:
parent.myDate.year = row + parent.myDate.minYear
case 1:
parent.myDate.month = row + 1
let newDay = parent.myDate.GetDays(yy: parent.myDate.year, mm: parent.myDate.month)
if parent.myDate.day > newDay {
parent.myDate.day = newDay
}
pickerView.reloadComponent(2)
print("月份改变:\(row + 1)-\(parent.myDate.month)")
case 2:
parent.myDate.day = row + 1
case 3:
parent.myDate.hour = row
case 4:
parent.myDate.minute = row
default:
break
}
}
// 设置宽度
public func pickerView(_ pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat {
let totalWidth = pickerView.bounds.width
switch component {
case 0:
return totalWidth * 0.24 // 第一列宽度为100
case 1:
return totalWidth * 0.21 // 第二列宽度为150
case 2:
return totalWidth * 0.23 // 第三列宽度为200
case 3:
return totalWidth * 0.15
default:
return totalWidth * 0.15
}
}
}
}
struct MyDateStruct2 {
var minYear = 1900
var maxYear = 2100
var year: Int = 2000 // 阳历
var month: Int = 1
var day: Int = 1
var hour: Int = 0
var minute: Int = 0
func GetDays(yy: Int, mm: Int) -> Int {
if mm < 1 || mm > 12 {
return 0
}
if yy == 1582 && mm == 10 {
return 21
}
// 计算是否是闰年
let isLeapYear = (yy % 4 == 0 && yy % 100 != 0) || (yy % 400 == 0)
// 每月的天数
let daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
// 计算该月的天数
var dom = daysInMonth[mm - 1]
if mm == 2 && isLeapYear {
dom = 29
}
return dom
}
}
// `TestView` 是一个包含 `SimplePicker` 的 SwiftUI 视图
struct TestView2: View {
@State private var myDate: MyDateStruct2
init() {
let calendar = Calendar.current
let now = Date()
let components = calendar.dateComponents([.year, .month, .day, .hour, .minute], from: now)
_myDate = State(initialValue: MyDateStruct2(
year: components.year!,
month: components.month!,
day: components.day!,
hour: components.hour!,
minute: components.minute!))
}
var body: some View {
VStack {
Text("年月日时分1")
Text("\(String(myDate.year))年\(myDate.month)月\(myDate.day)日\(myDate.hour)时\(myDate.minute)分")
Button(action: {
myDate.year -= 1
}, label: {
Text("阴阳历")
})
SimplePicker2(myDate: $myDate)
.frame(height: 200) // 设置选择器的高度
}
}
}
// 预览 `TestView`
#Preview {
TestView2()
// SimplePicker()
}