Swift 网络请求工具类

Posted 北冥鱼_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift 网络请求工具类相关的知识,希望对你有一定的参考价值。

一、首先定义 API 类:

import Foundation
import UIKit

// 声明 APIDelegate 回调方法
protocol APIDelegate: AnyObject 
  func loginFailed(error: Error)
  func loginSucceeded(userId: String)
  func announcementsFailed(error: Error)
  func announcementsLoaded(announcements: [Announcement])
  func orgLoaded(org: [Employee])
  func orgFailed(error: Error)
  func eventsLoaded(events: [Event])
  func eventsFailed(error: Error)
  func productsLoaded(products: [Product])
  func productsFailed(error: Error)
  func purchasesLoaded(purchases: [PurchaseOrder])
  func purchasesFailed(error: Error)
  func userLoaded(user: UserInfo)
  func userFailed(error: Error)


class API 
  // 声明 server 地址与端口, 如 "http://localhost:8080/"
  let server = AppDelegate.configuration.server
  let session: URLSession

  weak var delegate: APIDelegate?
  var token: Token?

  init() 
    session = URLSession(configuration: .default)
  

  func login(username: String, password: String) 
    let eventsEndpoint = server + "api/users/login"
    let eventsURL = URL(string: eventsEndpoint)!
    var urlRequest = URLRequest(url: eventsURL)
    urlRequest.httpMethod = "POST"
    let data = "\\(username):\\(password)".data(using: .utf8)!
    let basic = "Basic \\(data.base64EncodedString())"
    urlRequest.addValue(basic, forHTTPHeaderField: "Authorization")
    let task = session.dataTask(with: urlRequest)  data, _, error in
      guard let data = data else 
        if error != nil 
          DispatchQueue.main.async 
            self.delegate?.loginFailed(error: error!)
          
        
        return
      
      let decoder = JSONDecoder()
      if let token = try? decoder.decode(Token.self, from: data) 
        self.handleToken(token: token)
       else 
        do 
          let error = try decoder.decode(APIError.self, from: data)
          DispatchQueue.main.async 
            self.delegate?.loginFailed(error: error)
          
         catch 
          DispatchQueue.main.async 
            self.delegate?.loginFailed(error: error)
          
        
      
    

    task.resume()
  

  func handleToken(token: Token) 
    self.token = token
    Logger.logDebug("user \\(token.user.id)")
    DispatchQueue.main.async 
      self.delegate?.loginSucceeded(userId: token.user.id.uuidString)
    
  

  func logout() 
    token = nil
    delegate = nil
    UIApplication.appDelegate.showLogin()
  

  //swiftlint:disable identifier_name
  func submitPO(po: PurchaseOrder) throws 
    let url = URL(string: server + "api/" + "purchases")!
    var request = URLRequest(url: url)
    if let token = token?.token 
      let bearer = "Bearer \\(token)"
      request.addValue(bearer, forHTTPHeaderField: "Authorization")
    
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.httpMethod = "POST"

    let coder = JSONEncoder()
    coder.dateEncodingStrategy = .iso8601
    let data = try coder.encode(po)
    request.httpBody = data
    let task = loadTask(
      request: request,
      success: self.poSuccess,
      failure: self.delegate?.purchasesFailed(error:))
    task.resume()
  

  private func poSuccess(po: PurchaseOrder) 
    getPurchases()
  

  private func request(_ endpoint: String) -> URLRequest 
    let url = URL(string: server + "api/" + endpoint)!
    var request = URLRequest(url: url)
    if let token = token?.token 
      let bearer = "Bearer \\(token)"
      request.addValue(bearer, forHTTPHeaderField: "Authorization")
    
    return request
  

  func loadTask<T: Decodable>(
    request: URLRequest,
    success: ((T) -> Void)?,
    failure: ((Error) -> Void)?
  ) -> URLSessionTask 
    return session.dataTask(with: request)  data, _, error in
      guard let data = data else 
        if error != nil 
          DispatchQueue.main.async 
            failure?(error!)
          
        
        return
      
      let decoder = JSONDecoder()
      decoder.dateDecodingStrategy = .iso8601
      if let items = try? decoder.decode(T.self, from: data) 
        DispatchQueue.main.async 
          success?(items)
        
       else 
        do 
          let error = try decoder.decode(APIError.self, from: data)
          DispatchQueue.main.async 
            failure?(error)
          
         catch 
          DispatchQueue.main.async 
            failure?(error)
          
        
      
    
  

  func getAnnouncements() 
    let req = request("announcements")
    let task = loadTask(
      request: req,
      success: self.delegate?.announcementsLoaded(announcements:),
      failure: self.delegate?.announcementsFailed(error:))
    task.resume()
  

  func getOrgChart() 
    let req = request("employees")
    let task = loadTask(
      request: req,
      success: self.delegate?.orgLoaded(org:),
      failure: self.delegate?.orgFailed(error:))
    task.resume()
  

  func getEvents() 
    let req = request("events")
    let task = loadTask(
      request: req,
      success: self.delegate?.eventsLoaded(events:),
      failure: self.delegate?.eventsFailed(error:))
    task.resume()
  

  func getProducts() 
    let req = request("products")
    let task = loadTask(
      request: req,
      success: self.delegate?.productsLoaded(products:),
      failure: self.delegate?.productsFailed(error:))
    task.resume()
  

  func getPurchases() 
    let req = request("purchases")
    let task = loadTask(
      request: req,
      success: self.delegate?.purchasesLoaded(purchases:),
      failure: self.delegate?.purchasesFailed(error:))
    task.resume()
  

  func getUserInfo(userID: String) 
    let req = request("users/\\(userID)")
    let task = loadTask(
      request: req,
      success: self.delegate?.userLoaded(user:),
      failure: self.delegate?.userFailed(error:))
    task.resume()
  


二、使用方法:

  1. 在 AppDelegate 声明
  // 声明变量
  static var configuration: Configuration!
  var api: API!

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool 
    // 初始化变量
    AppDelegate.configuration = Configuration.load()
    api = API()

    return true
  
  1. 其中 Configuration:
import Foundation

struct Configuration: Codable 
  struct UI: Codable 
    struct Button: Codable 
      let cornerRadius: Double
      let borderWidth: Double
    

    let button: Button
  

  struct BusinessRules: Codable 
    let maxPOExpense: Double
  

  let server: String
  let debug: Bool
  let ui: UI
  let rules: BusinessRules


// MARK: - Local Settings

extension Configuration 
  var firstDayOfWeek: DaysOfWeek 
    if UserDefaults.standard.object(forKey: "firstDayOfWeek") != nil 
      return DaysOfWeek(rawValue: UserDefaults.standard.integer(forKey: "firstDayOfWeek"))!
    
    return .sunday
  


extension Configuration 
  //swiftlint:disable force_try
  static func load() -> Configuration 
    let url = Bundle.main.url(forResource: "configuration", withExtension: "json")!
    let data = try! Data(contentsOf: url)
    let decoder = JSONDecoder()
    return try! decoder.decode(Configuration.self, from: data)
  


  1. 在 controller 中使用:
 var api: API  return (UIApplication.shared.delegate as! AppDelegate).api 
  let skin: Skin = .login

  override func viewDidLoad() 
    super.viewDidLoad()

    api.delegate = self
    Styler.shared.style(background: view, buttons: [signInButton], with: skin)
  

以上是关于Swift 网络请求工具类的主要内容,如果未能解决你的问题,请参考以下文章

ios swift 打造自己的http请求工具

Swift网络请求(Moya篇)

swift中第三方网络请求库Alamofire的安装与使用

Swift 项目中涉及到 JSONDecoder,网络请求,泛型协议式编程的一些记录和想法

鸿蒙网络请求(下):工具类封装和使用

鸿蒙网络请求(下):工具类封装和使用