POP网络编程
- iOS项目开发中进行网络请求的时候,一般默认用model来保存数据
- 定义一个LGPerson数据模型来保存数据
struct LGPerson {
let name: String
let iconName: String
let age: String
let hobby: String
let petPhrase: String
init?(data: Data) {
guard let obj = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any] else {
return nil
}
guard let name = obj["name"] as? String else {
return nil
}
guard let iconName = obj["iconName"] as? String else {
return nil
}
guard let age = obj["age"] as? String else {
return nil
}
guard let hobby = obj["hobby"] as? String else {
return nil
}
guard let petPhrase = obj["petPhrase"] as? String else {
return nil
}
self.name = name
self.iconName = iconName
self.age = age
self.hobby = hobby
self.petPhrase = petPhrase
}
}
- 抽取协议中公共组成部分
- associatedtype 定义一个协议时,有的时候声明一个或多个关联类型作为协议定义的一部分将会非常有用
- 关联类型为协议中的某个类型(任意类型)提供了一个占位名(或者说别名)其代表的实际类型在协议被采纳时才会被指定。你可以通过 associatedtype 关键字来指定关联类型
enum LGHTTPMethod: String {
case GET
case POST
}
protocol LGRequest {
var host: String { get }
var path: String { get }
var method: LGHTTPMethod { get }
var parameter: [String: Any] { get }
associatedtype Response
func parse(data: Data) -> Response?
}
extension LGRequest {
func send(handler: @escaping (Response?) -> Void) {
let url = URL(string: host.appending(path))!
var request = URLRequest(url: url)
request.httpMethod = method.rawValue
// 在示例中我们不需要 `httpBody`,实践中可能需要将 parameter 转为 data
// request.httpBody = ...
let task = URLSession.shared.dataTask(with: request) {
data, response, error in
if let data = data, let res = self.parse(data: data) {
DispatchQueue.main.async { handler(res) }
} else {
DispatchQueue.main.async { handler(nil) }
}
}
task.resume()
}
}
- 具体发送网络请求的时候遵守LGRequest,自定义结构体实现协议中的方法
struct LGPersonRequest: LGRequest {
typealias Response = LGPerson
let name: String
let host = "http://127.0.0.1:5000"
var path: String {
return "/pythonJson/getTeacherInfo/?username=\(name)"
}
let method: LGHTTPMethod = .GET
let parameter: [String: Any] = [:]
func parse(data: Data) -> LGPerson? {
return LGPerson(data: data)
}
}
override func viewDidLoad() {
super.viewDidLoad()
let request = LGPersonRequest(name: "kody")
request.send { (person) in
self.updataUI(person: person!)
}
}
func updataUI(person:LGPerson){
imageView.image = UIImage(named: person.iconName)
nickName.text = person.name
ageLabel.text = person.age
hobbyLabel.text = person.hobby
petPhraseLabel.text = person.petPhrase
}