我有一個呼叫 REST API 并通過完成處理程式回傳結果的函式。
我想在按下 NavigationLink 時呼叫此函式,但將結果用作傳遞到目的地的物件。無法完全弄清楚如何做到這一點,或者是否有可能。這是我當前的代碼:
休息功能
func postProgramme(programmeName: String, programmeDays: Int, programmeDescription: String, completeionHandler: @escaping ProgrammeCompletionHandler) {
struct PostRoutineData: Codable {
let programmeName: String
let programmeDays: Int
let programmeDescription: String
}
let postProgrammeData = PostRoutineData(programmeName: programmeName, programmeDays: programmeDays, programmeDescription: programmeDescription)
do {
let jsonData = try JSONEncoder().encode(postProgrammeData)
let jsonString = String(data: jsonData, encoding: .utf8)!
let request = RESTRequest(path: "/workout/programme", body: jsonString.data(using: .utf8))
Amplify.API.post(request: request) { result in
switch result {
case .success(let data):
do {
//let str = String(decoding: data, as: UTF8.self)
let programme = try self.decoder.decode(Programme.self, from: data)
completeionHandler(programme)
} catch {
print("[ERROR] Error within postProgrammes()", error)
}
case .failure(let error):
print("[ERROR] Error within postProgrammes()", error)
}
}
} catch {
print("[ERROR] Error within postProgramme()", error)
}
}
NavigationLink,以及我試圖解決問題的嘗試:
NavigationLink(destination: ProgrammeDetailView(), isActive: $shouldTransit) {
Text("Create Programme")
.onTapGesture {
self.createNewProgramme()
self.shouldTransit = true
}
}
func createNewProgramme() -> ProgrammeDetailView {
sessionManager.postProgramme(programmeName: programmeName, programmeDays: programmeDays, programmeDescription: programmeDescription, completeionHandler: {(programme) -> ProgrammeDetailView in
return ProgrammeDetailView(programme: programme)}
}
uj5u.com熱心網友回復:
假設它是一個 iOS 應用程式,如果你可以為 iOS 15 部署,你可以使用最近的 async/await 環境,通過使用 async 函式并回傳 a Programme,而不是使用完成處理程式。
- 將您的函式轉換為 async 并回傳
Programme:
func postProgramme(programmeName: String, programmeDays: Int, programmeDescription: String) async -> Programme? {
// ...
case .success(let data):
do {
let programme = try self.decoder.decode(Programme.self, from: data)
// No completion handler: return a Programme
// completionHandler(programme)
return programme
} catch {
print("[ERROR] Error within postProgrammes()", error)
// Return nil everywhere else
return nil
}
- 在您的主視圖中,使用
@Statevar 型別Programme?,它將系結到ProgrammeDetailView.
該函式createNewProgramme()將更新狀態變數。
@State private var programme: Programme? = nil
var body: some View {
NavigationView {
// Pass the binding to ProgrammeDetailView
NavigationLink(destination: ProgrammeDetailView(programme: $programme, content: { programme in
// A customised view
Text(programme?.name ?? "")
}), isActive: $shouldTransit) {
Text("Create Programme")
.onTapGesture {
self.createNewProgramme()
self.shouldTransit = true
}
}
}
func createNewProgramme() {
// Task will allow working with async functions
Task {
let programme = await sessionManager.postProgramme(programmeName: programmeName, programmeDays: programmeDays, programmeDescription: programmeDescription)
// Back to main thread to update the UI
DispatchQueue.main.async {
self.programme = programme
}
}
}
- 記得
@Binding在ProgrammeDetailView. 下面的示例可以接收任何視圖作為引數,但是由于 REST API 需要一些時間來回應,因此您需要處理以下情況programme == nil:
struct ProgrammeDetailView<V: View> : View {
// The binding with the parent view
@Binding var programme: Programme?
// Your customised view that receives a Programme as a parameter
let content: (Programme)->V
var body: some View {
if programme == nil {
ProgressView()
} else {
content(programme!)
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/471659.html
