首页 > 解决方案 > 如何在 SwiftUI 中创建 json 'POST' 请求?

问题描述

我正在为一个学习编程的项目制作联系人列表应用程序,目前正在创建通过我创建的 Rest API 将联系人添加到数据库的方法。

下面的代码用于Add Contact视图,我遵循了一些关于如何从表单中获取数据、将其转换为 JSON 并通过 POST 请求将其发送到数据库的教程。

这是我得到的代码,应该发生的是我应该看到打印responseJSON,但这没有发生,实际上什么都没有发生,当我checkDetails通过按下视图上的按钮运行函数时,我得到和 的打印bodyjsonData但没有别的。甚至没有错误。

我在这里有点难过,因为我没有改变太多,如果有的话,从我遵循的教程,所以我猜这与我自己的代码有关。

任何帮助,将不胜感激!

import SwiftUI
import Combine

struct AddContact: View {
    @State var id = 999
    
    @State var first_name: String = ""
    @State var last_name: String = ""
    @State var phone_number: String = ""
    @State var address: String = ""
    
    @State var birthday = Date()
    @State var birthdayString: String = ""
    @State var create_date = Date()
    @State var create_dateString: String = ""
    @State var updated_date = Date()
    @State var updated_dateString: String = ""

    @State var manager = DataPost()
    
    var body: some View {
        if manager.formCompleted {
            Text("Done").font(.headline)
        }
        VStack {
            NavigationView {
                Form {
                    Section() {
                        TextField("First Name", text: $first_name)
                        TextField("Last Name", text: $last_name)
                    }
                    Section() {
                        TextField("Phone Number", text: $phone_number)
                        TextField("Address", text: $address)
                    }
                    Section() {
                        DatePicker("Birthday", selection: $birthday, displayedComponents: .date)
                    }
                    Section() {
                        Button(action: {
                            let dateFormatter = DateFormatter()
                            dateFormatter.dateStyle = .short
                            
                            birthdayString = dateFormatter.string(from: birthday)
                            create_dateString = dateFormatter.string(from: create_date)
                            updated_dateString = dateFormatter.string(from: updated_date)
                            
                            print("Clicked")
                            
                            self.manager.checkDetails(id: self.id, first_name: self.first_name, last_name: self.last_name, phone_number: self.phone_number, address: self.address, birthday: self.birthdayString, create_date: self.create_dateString, updated_date: self.updated_dateString)
                            
                        }, label: {
                            Text("Add Contact")
                                .fontWeight(.bold)
                                .multilineTextAlignment(.center)
                        })
                    }.disabled(first_name.isEmpty || last_name.isEmpty || phone_number.isEmpty || address.isEmpty)
                }
            }.navigationTitle("New Contact")
            .navigationBarTitleDisplayMode(.inline)
        }
    }
}

class DataPost: ObservableObject {
    var didChange = PassthroughSubject<DataPost, Never>()
    var formCompleted = false {
        didSet {
            didChange.send(self)
        }
    }
    
    func checkDetails(id: Int, first_name: String, last_name: String, phone_number: String, address: String, birthday: String, create_date: String, updated_date: String) {
        
        let body: [String: Any] = ["data": ["id": id, "first_name": first_name, "last_name": last_name, "birthday": birthday, "phone_number": phone_number, "create_date": create_date, "updated_date": updated_date, "address": address]]
                
        let jsonData = try? JSONSerialization.data(withJSONObject: body)
                
        let url = URL(string: "https://flaskcontact-list-app.herokuapp.com/contacts")!
        var request = URLRequest(url: url)
        
        request.httpMethod = "POST"
        
        request.setValue("\(String(describing: jsonData?.count))", forHTTPHeaderField: "Content-Length")
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        
        request.httpBody = jsonData

        print(body)
        print(jsonData)
        
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            guard let data = data, error == nil else {
                print(error?.localizedDescription ?? "No data")
                return
            }

            let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
            if let responseJSON = responseJSON as? [String: Any] {
                print(responseJSON)
            }
        }

        task.resume()
    }
}

标签: jsonswiftswiftui

解决方案


好的,这是我使用的测试代码。虽然我使用的是 macos 12.beta、xcode 13.beta、目标 ios 15 和 macCatalyst。在 iPhone ios15 和 macos 12 上测试。在 xcode 12.5 和 macos 11.4 上“应该是一样的”。

import Foundation
import SwiftUI
import Combine

@main
struct TestApp: App {

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

struct AddContact: View {
    @State var id = 999
    
    @State var first_name: String = ""
    @State var last_name: String = ""
    @State var phone_number: String = ""
    @State var address: String = ""
    
    @State var birthday = Date()
    @State var birthdayString: String = ""
    @State var create_date = Date()
    @State var create_dateString: String = ""
    @State var updated_date = Date()
    @State var updated_dateString: String = ""
    
    @State var manager = DataPost()
    
    var body: some View {
        if manager.formCompleted {
            Text("Done").font(.headline)
        }
        VStack {
            NavigationView {
                Form {
                    Section() {
                        TextField("First Name", text: $first_name)
                        TextField("Last Name", text: $last_name)
                    }
                    Section() {
                        TextField("Phone Number", text: $phone_number)
                        TextField("Address", text: $address)
                    }
                    Section() {
                        DatePicker("Birthday", selection: $birthday, displayedComponents: .date)
                    }
                    Section() {
                        Button(action: {
                            let dateFormatter = DateFormatter()
                            dateFormatter.dateStyle = .short
                            
                            birthdayString = dateFormatter.string(from: birthday)
                            create_dateString = dateFormatter.string(from: create_date)
                            updated_dateString = dateFormatter.string(from: updated_date)
                            
                            print("Clicked")
                            
                            self.manager.checkDetails(id: self.id, first_name: self.first_name, last_name: self.last_name, phone_number: self.phone_number, address: self.address, birthday: self.birthdayString, create_date: self.create_dateString, updated_date: self.updated_dateString)
                            
                        }, label: {
                            Text("Add Contact")
                                .fontWeight(.bold)
                                .multilineTextAlignment(.center)
                        })
                    }.disabled(first_name.isEmpty || last_name.isEmpty || phone_number.isEmpty || address.isEmpty)
                }
            }.navigationTitle("New Contact")
                .navigationBarTitleDisplayMode(.inline)
        }
    }
}

class DataPost: ObservableObject {
    var didChange = PassthroughSubject<DataPost, Never>()
    var formCompleted = false {
        didSet {
            didChange.send(self)
        }
    }
    
    func checkDetails(id: Int, first_name: String, last_name: String, phone_number: String, address: String, birthday: String, create_date: String, updated_date: String) {
        
        let body: [String: Any] = ["data": ["id": id, "first_name": first_name, "last_name": last_name, "birthday": birthday, "phone_number": phone_number, "create_date": create_date, "updated_date": updated_date, "address": address]]
        
        let jsonData = try? JSONSerialization.data(withJSONObject: body)
        
        //  "https://flaskcontact-list-app.herokuapp.com/contacts"
        let url = URL(string: "https://jsonplaceholder.typicode.com/posts")!
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("\(String(describing: jsonData?.count))", forHTTPHeaderField: "Content-Length")
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = jsonData
        
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            print("-----> data: \(data)")
            print("-----> error: \(error)")
            
            guard let data = data, error == nil else {
                print(error?.localizedDescription ?? "No data")
                return
            }

            let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
            print("-----1> responseJSON: \(responseJSON)")
            if let responseJSON = responseJSON as? [String: Any] {
                print("-----2> responseJSON: \(responseJSON)")
            }
        }
        
        task.resume()
    }
}

struct ContentView: View {
    var body: some View {
        AddContact()
    }
}

推荐阅读