前端
SwiftUI 使用URLSession异步调用JSON格式接口
  • By刘立博
  • 2021-09-21 22:16:27
  • 1768人已阅读

定义后端接口

搭建接口 /v1/test, 接收一个JSON输入对象,返回一个JSON输出对象

 

接口输入对象定义

很简单,一个字段inputMsg

@Data
public class TestAO
{
    String inputMsg;
}

接口输出对象定义

我们不能直接获取这个对象,而需要先解析泛型响应对象的相关字段后,再解析data获取此对象

@Data
public class TestVO
{
    String inputMsg;
    String outputMsg;
}

泛型相应对象

用于封装一些公共属性,如是否成功?错误信息等

@Data
@ApiModel(value = "API View Object<T>",description = "接口泛型响应对象")
public class RestResponseTVO<T>
{
    @ApiModelProperty(value = "是否失败",notes="0 成功 1失败",example = "0")
    private Integer hasError;
    @ApiModelProperty(value = "错误信息",notes="描述失败的具体原因",example = "参数错误")
    private String error_msg;
    @ApiModelProperty(value = "响应对象",notes="响应数据对象",example = "操作成功")
    private T data;

}

该接口描述如下

创建项目目录

创建两个目录Dto用于定义接口输出对象实体,RequestUtils用于定义网络通信相关方法

定义输出对象实体: TestResponseDTO.swift

根据后端接口输出对象定义两个结构体TestResponseDTOFull和TestResponseDTO,其中TestResponseDTOFull定义了完整的输出对象,而TestResponseDTO定义了我们真正关心的输出对象,继承Codable的目的是遵守SwiftUI反序列化协议,继承Hashable是遵守Swift对象比较协议

//
//  TestResponseDTO.swift
//  testRequest
//
//  Created by 刘立博 on 2021/9/21.
//

import Foundation

struct TestResponseDTO: Codable,Hashable {
    
    var inputMsg: String
    var outputMsg: String
    
    init()
    {
        inputMsg = ""
        outputMsg = ""
    }
}

struct TestResponseDTOFull: Codable{
    var hasError: Int
    var error_msg: String?
    var data: TestResponseDTO
    
    init() {
        hasError = 0
        error_msg = ""
        data = TestResponseDTO()
    }
}

 

定义网络通信方法 RequestTestAPI.swift

其包含两个属性,item用于将接口的返回对象发布至视图层;url用于定义接口的URL

class RequestTestAPI: ObservableObject
{
    @Published var item: TestResponseDTO = TestResponseDTO()
    static let url = URL(string: "http://127.0.0.1:9000/v1/test")!
}

 

封装通信方法send

改方法接收一个传参,对应接口输入对象的inputMsg,完成对请求方法\header头\输入对象的定义,异步发起HTTP请求后,首先将接口返回值解析为TestResponseDTOFull,判断hasError为0后,再将其解析为TestResponseDTO

//
//  RequestTestAPI.swift
//  testRequest
//
//  Created by 刘立博 on 2021/9/21.
//

import Foundation

class RequestTestAPI: ObservableObject
{
    @Published var item: TestResponseDTO = TestResponseDTO()
    static let url = URL(string: "http://127.0.0.1:9000/v1/test")!
    
    func send(inputMsg:String)
    {
        var request = URLRequest.init(url: RequestTestAPI.url, timeoutInterval: 10)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        let params = ["inputMsg":inputMsg] as [String:Any]
        request.httpBody = try! JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
        
        URLSession.shared.dataTask(with: request)
        { (data, response, error) in
            
            guard let data = data, error == nil else
            {
                return
            }

            let jsonDecoder = JSONDecoder()
            
            do{
                let modelObject = try jsonDecoder.decode(TestResponseDTOFull.self, from: data)
                
                if modelObject.hasError != 0 {
                    return
                }
                
                DispatchQueue.main.async {
                    self.item = modelObject.data
                    print(self.item)
                }
            }catch{
                print(error)
            }
                
            
        }
        .resume()
    }
}

 

构建视图

当视图加载完成后,调用send方法,并将获取到的接口返回值填充至Text

//
//  ContentView.swift
//  testRequest
//
//  Created by 刘立博 on 2021/9/21.
//

import SwiftUI

struct ContentView: View {
    
    @ObservedObject var testApi = RequestTestAPI()
    
    
    var body: some View {
        VStack{
            Text(testApi.item.outputMsg).padding()
        }.onAppear(perform: {
            testApi.send(inputMsg: "test input")
        })
            
        
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

 

测试

正确返回后端接口的返回