SwiftUI onChange 修饰符如何工作?
How SwiftUI onChange modifier works?
我动态填充了一个 SwiftUI Picker。 Picker 正在成功运行。我想触发或监听选择器更改事件。假设我将打印 if user select item 的值。我的 iOS 部署目标是 14,我发现 iOS 有一个内置函数 onChange 来检测这种监听器。我使用了那个修改器但没有工作。
这是我的代码:
var body: some View {
Picker( selection: $selectedStrength, label: Text("Status")) {
ForEach(courseList, id: \.self) { item in
Text(item.courseCode ?? "")
}
}
.onChange(of:selectedStrength, perform: { _ in
print("Value Changed!")
})
.pickerStyle(WheelPickerStyle())
}
尝试以下代码实现:
struct ContentView: View {
var colors = ["Red", "Green", "Blue", "Tartan"]
@State private var selectedColor = "Red"
var body: some View {
VStack {
Picker("Please choose a color", selection: $selectedColor) {
ForEach(colors, id: \.self) {
Text([=10=])
}
}
Text("You selected: \(selectedColor)")
}
}
}
我认为这是由于类型不匹配,Picker 选择类型和项目类型或 (!) 标签应该相同。一旦你按项目迭代但显示 courseCode
这可能是错误的原因。
尝试类似的方法(未测试,因为提供的代码不是独立的且不可运行)
Picker(selection: $selectedStrength, label: Text("Status")) {
ForEach(courseList, id: \.self) { item in
// assiming selectedStrength type and item.courseCode type is the same
Text(item.courseCode ?? "").tag(item.courseCode)
}
}
.onChange(of: selectedStrength, perform: { _ in
print("Value Changed!")
})
总结:我调用了 REST API 并解析了数据,然后我尝试从这些数据创建一个 SwiftUI Picker。
解决方法:经过多方查找,找到了正确的解决方法。我直接从 Json 对象数据填充选择器。我将这些数据转换为 SwiftUI 字符串数组并尝试了 onChange 函数,它现在可以工作了。
我的代码:
import SwiftUI
struct TeacherCourseListParser: Decodable, Hashable{
var totalStudent: Int?
var courseName: String?
var courseCode: String?
var courseId: Int?
var courseTeacherEnrollId: Int?
}
struct Test: View {
@State var courseList = [TeacherCourseListParser]()
@State private var selectedStrength = ""
@State var courseCodeTempArray = [String]()
var body: some View {
VStack(spacing: 0){
Picker( selection: $selectedStrength, label: Text("Course Code")) {
ForEach(courseCodeTempArray, id: \.self) {
Text([=10=])
}
}
.onChange(of: selectedStrength, perform: { _ in
print("Value Changed!")
})
.pickerStyle(WheelPickerStyle())
}
}
这是我如何获取 JSON 对象的函数:
func FetchTeacherCourseCode(){
let token = UserDefaults.standard.string(forKey: "login_token")
// create post request
guard let url = URL(string: Constant.mainServerUrl+Constant.getTeacherCourseList) else {
print("Invalid URL")
return
}
print(url)
var request = URLRequest(url: url)
request.httpMethod = "GET"
// request.httpBody = jsonData
request.allHTTPHeaderFields = [
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": "Bearer "+token!
]
URLSession.shared.dataTask(with: request) {data, response, error in
if let data = data {
do {
//-- Parse response according to the object
let detailedObjectFetcher = try! JSONDecoder().decode([TeacherCourseListParser].self, from: data)
DispatchQueue.main.async {
for i in detailedObjectFetcher {
// instead of populating Picker from JSON object directly I generated a string array
courseCodeTempArray.append(i.courseCode ?? "")
}
self.courseList = detailedObjectFetcher
showProgressBar = false
}
} catch DecodingError.keyNotFound(let key, let context) {
Swift.print("could not find key \(key) in JSON: \(context.debugDescription)")
} catch DecodingError.valueNotFound(let type, let context) {
Swift.print("could not find type \(type) in JSON: \(context.debugDescription)")
} catch DecodingError.typeMismatch(let type, let context) {
Swift.print("type mismatch for type \(type) in JSON: \(context.debugDescription)")
} catch DecodingError.dataCorrupted(let context) {
Swift.print("data found to be corrupted in JSON: \(context.debugDescription)")
} catch let error as NSError {
NSLog("Error in read(from:ofType:) domain= \(error.domain), description= \(error.localizedDescription)")
}
}
// print("Fetch failed: \(error?.localizedDescription ?? "Unknown error")")
}.resume()
}
}
我动态填充了一个 SwiftUI Picker。 Picker 正在成功运行。我想触发或监听选择器更改事件。假设我将打印 if user select item 的值。我的 iOS 部署目标是 14,我发现 iOS 有一个内置函数 onChange 来检测这种监听器。我使用了那个修改器但没有工作。 这是我的代码:
var body: some View {
Picker( selection: $selectedStrength, label: Text("Status")) {
ForEach(courseList, id: \.self) { item in
Text(item.courseCode ?? "")
}
}
.onChange(of:selectedStrength, perform: { _ in
print("Value Changed!")
})
.pickerStyle(WheelPickerStyle())
}
尝试以下代码实现:
struct ContentView: View {
var colors = ["Red", "Green", "Blue", "Tartan"]
@State private var selectedColor = "Red"
var body: some View {
VStack {
Picker("Please choose a color", selection: $selectedColor) {
ForEach(colors, id: \.self) {
Text([=10=])
}
}
Text("You selected: \(selectedColor)")
}
}
}
我认为这是由于类型不匹配,Picker 选择类型和项目类型或 (!) 标签应该相同。一旦你按项目迭代但显示 courseCode
这可能是错误的原因。
尝试类似的方法(未测试,因为提供的代码不是独立的且不可运行)
Picker(selection: $selectedStrength, label: Text("Status")) {
ForEach(courseList, id: \.self) { item in
// assiming selectedStrength type and item.courseCode type is the same
Text(item.courseCode ?? "").tag(item.courseCode)
}
}
.onChange(of: selectedStrength, perform: { _ in
print("Value Changed!")
})
总结:我调用了 REST API 并解析了数据,然后我尝试从这些数据创建一个 SwiftUI Picker。
解决方法:经过多方查找,找到了正确的解决方法。我直接从 Json 对象数据填充选择器。我将这些数据转换为 SwiftUI 字符串数组并尝试了 onChange 函数,它现在可以工作了。
我的代码:
import SwiftUI
struct TeacherCourseListParser: Decodable, Hashable{
var totalStudent: Int?
var courseName: String?
var courseCode: String?
var courseId: Int?
var courseTeacherEnrollId: Int?
}
struct Test: View {
@State var courseList = [TeacherCourseListParser]()
@State private var selectedStrength = ""
@State var courseCodeTempArray = [String]()
var body: some View {
VStack(spacing: 0){
Picker( selection: $selectedStrength, label: Text("Course Code")) {
ForEach(courseCodeTempArray, id: \.self) {
Text([=10=])
}
}
.onChange(of: selectedStrength, perform: { _ in
print("Value Changed!")
})
.pickerStyle(WheelPickerStyle())
}
}
这是我如何获取 JSON 对象的函数:
func FetchTeacherCourseCode(){
let token = UserDefaults.standard.string(forKey: "login_token")
// create post request
guard let url = URL(string: Constant.mainServerUrl+Constant.getTeacherCourseList) else {
print("Invalid URL")
return
}
print(url)
var request = URLRequest(url: url)
request.httpMethod = "GET"
// request.httpBody = jsonData
request.allHTTPHeaderFields = [
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": "Bearer "+token!
]
URLSession.shared.dataTask(with: request) {data, response, error in
if let data = data {
do {
//-- Parse response according to the object
let detailedObjectFetcher = try! JSONDecoder().decode([TeacherCourseListParser].self, from: data)
DispatchQueue.main.async {
for i in detailedObjectFetcher {
// instead of populating Picker from JSON object directly I generated a string array
courseCodeTempArray.append(i.courseCode ?? "")
}
self.courseList = detailedObjectFetcher
showProgressBar = false
}
} catch DecodingError.keyNotFound(let key, let context) {
Swift.print("could not find key \(key) in JSON: \(context.debugDescription)")
} catch DecodingError.valueNotFound(let type, let context) {
Swift.print("could not find type \(type) in JSON: \(context.debugDescription)")
} catch DecodingError.typeMismatch(let type, let context) {
Swift.print("type mismatch for type \(type) in JSON: \(context.debugDescription)")
} catch DecodingError.dataCorrupted(let context) {
Swift.print("data found to be corrupted in JSON: \(context.debugDescription)")
} catch let error as NSError {
NSLog("Error in read(from:ofType:) domain= \(error.domain), description= \(error.localizedDescription)")
}
}
// print("Fetch failed: \(error?.localizedDescription ?? "Unknown error")")
}.resume()
}
}