SimpleWebRequests 4.1.12

SimpleWebRequests 4.1.12

测试测试过
语言语言 SwiftSwift
许可证 MIT
发布最后发布2021年2月
SPM支持 SPM

Niklas Fahl维护。



  • 出自
  • CAPS

SimpleWebRequests

Version License Platform

要求

  • Swift 4
  • iOS 10.3 及以上版本

示例项目

示例项目展示了如何使用库来实现处理网络调用的几种不同方式。只有当您想要能够轻松地在不同的数据源之间切换时,才需要自定义请求管理器。

安装

CocoaPods

SimpleWebRequests 可通过 CocoaPods 获取。要安装它,只需将以下行添加到您的 Podfile 中

pod 'SimpleWebRequests'

手册

将 'Sources' 目录中的所有文件添加到您的项目中,您就可以开始使用了。

入门

此库允许您快速搭建网络层,同时也支持更复杂的设置,涉及多个数据源(发布、开发、本地、模拟),但此处不做过多介绍。

要开始使用,您需要为每个网络请求添加 'DataResource' 的子类到项目中。我建议添加一个名为 '{ProjectName}DataResources.swift' 的文件,并将资源放置在此文件中,如下所示:

注意:标题、查询和资源参数通常不是静态的,将在资源实例化和使用时使用 'setHeaders:、' setBody: ' 和 ' setQuery: ' 设置。

//  {ProjectName}ApiResources.swift

struct GetArticlesResource: DataResource {
    typealias Model = [Article]
    
    var urlSessionConfiguration: URLSessionConfiguration = URLSessionConfiguration.default
    var httpMethod: HttpMethod = .get
    var headers: [String: String]?
    var baseUrl: String = "https://www.test.com"
    var methodPath: String? = "api/test"
    var query: String?
    var body: Data?
}

设置好资源后,您可以按照以下示例进行一些网络调用

let resource = GetArticlesResource()
let sessionTask = NetworkDataRequest(resource: resource).load { (response) in
    switch response {
    case let .success(model):
        // Do something with the model coming back
    case let .error(error):
        // Handle general error
    case let .httpError(statusCode):
        // Handle HTTP error
    }
}

如果您的请求需要一个体,可以直接在类定义中将资源的体设置,如果它们是固定的,或者如下所示

//let resource = AddArticlesResource()
let body = Article(title: "Test 1", description: "Testing article description.")
resource.setBody(body: JSONCoder.encode(object: body))
//let sessionTask = NetworkDataRequest(resource: resource).load { (response) in
//...

如果您的请求需要一个查询,可以直接在类定义中将资源的查询设置,如果它们是固定的,或者如下所示

//let resource = AddArticlesResource()
resource.setQuery(query: "?something=something")
//let sessionTask = NetworkDataRequest(resource: resource).load { (response) in
//...

如果您的请求需要标题,可以直接在类定义中将资源的标题设置,如果它们是固定的,或者如下所示

//let resource = AddArticlesResource()
resource.setHeaders(headers: ["SomeHeaderKey": "SomeHeaderValue"])
//let sessionTask = NetworkDataRequest(resource: resource).load { (response) in
//...

高级设置

高级设置允许您通过通用管理类在不同的数据源之间自动切换。为此设置,您需要继承以下结构体/协议。再次推荐用您的项目名作为类的前缀以提高清晰度。

protocol ApiInformation
protocol DataRequestManager
class MockDataRequestManager (optional)
class LocalDataRequestManager (optional)

让我们从 ApiInformation 类开始。这个类将允许您设置在运行时使用的所需数据源。在下面的示例中,我根据我的应用设置在构建配置中的调试或发布,在数据源之间进行切换。

//  {ProjectName}ApiInformation.swift

struct {ProjectName}ApiInformation: ApiInformation {
    #if DEBUG
    var dataSource: DataSource = DataSource(type: .development, baseUrl: "http://development.something.com")
    #else
    var dataSource: DataSource = DataSource(type: .release, baseUrl: "https://release.something.com")
    #endif
}

接下来要设置的是数据处理管理器,如下所示处理数据源切换

注意:在线数据请求管理器将被设置为 NetworkDataRequestManager 的新实例,除非您希望创建自己的继承自它的类来对该类进行所需的更改。

//  {ProjectName}DataRequestManager.swift

public struct {ProjectName}DataRequestManager: DataRequestManager {
    public typealias Resource = DataResource
    public var apiInformation: ApiInformation = {ProjectName}ApiInformation()
    public var onlineDataRequestManager: NetworkDataRequestManager = NetworkDataRequestManager()
    public var localDataRequestManager: LocalDataRequestManager? = {ProjectName}LocalDataRequestManager()
    public var mockDataRequestManager: MockDataRequestManager? = {ProjectName}MockDataRequestManager()
    
    public static var shared: {ProjectName}DataRequestManager = {ProjectName}DataRequestManager()
}

模拟以及本地请求管理器的设置非常相似,这完全取决于您的实现和您希望如何处理这些数据请求,因为这个库只提供了这些部分的框架,以便数据处理管理器可以根据数据源进行切换。以下是每个可能看起来像的示例

模拟数据请求管理器

注意:在switch语句中,我展示了如何根据资源类型处理每种资源情况。请确保为每个case语句生成和返回相应的模拟数据。

//  {ProjectName}MockDataRequest.swift

public class {ProjectName}MockDataRequestManager: MockDataRequestManager {
    // All your custom variables to allow mocking your server
    var articles: [Article] = [Article(title: "Mock 1", description: "Mocking an article."), Article(title: "Mock 2", description: "Mocking an article again.")]
    
    public override func loadRequest<Resource: DataResource>(with resource: Resource, completion: @escaping (DataResponse<Resource.Model>) -> Void) -> URLSessionTask {
        return handleRequest(with: resource, completion: completion)
    }
}

extension {ProjectName}MockDataRequestManager {
    
    // MARK: - Handle Request
    
    func handleRequest<Resource: DataResource>(with resource: Resource, completion: @escaping (DataResponse<Resource.Model>) -> Void) -> URLSessionTask {
        switch resource.self {
        case is GetArticlesResource:
            getArticles(completion: completion as! (DataResponse<GetArticlesResource.Model>) -> Void)
        default:
            return URLSessionTask()
        }
        return URLSessionTask()
    }
}

extension {ProjectName}MockDataRequestManager {
    
    // MARK: - Articles (GET)
    
    func getArticles(completion: @escaping (DataResponse<GetArticlesResource.Model>) -> Void)  {
        let response: DataResponse = .success(model: articles)
        completion(response)
    }
}

本地数据请求管理器

注意:在switch语句中,我展示了如何根据资源类型处理每种资源情况。请确保从本地数据库返回适当的数据,例如,为每个case语句返回数据。

//  {ProjectName}LocalDataRequest.swift

public class {ProjectName}LocalDataRequestManager: LocalDataRequestManager {
    public override func loadRequest<Resource: DataResource>(with resource: Resource, completion: @escaping (DataResponse<Resource.Model>) -> Void) -> URLSessionTask {
        // Get offline data
        return handleRequest(with: resource, completion: completion)
    }
}

extension {ProjectName}LocalDataRequestManager {
    
    // MARK: - Handle Request
    
    func handleRequest<Resource: DataResource>(with resource: Resource, completion: @escaping (DataResponse<Resource.Model>) -> Void) -> URLSessionTask {
        switch resource.self {
        case is GetArticlesResource:
            let error = NSError(domain: "Local Data Fetch Error", code: 1, userInfo: nil)
            let response: DataResponse = DataResponse<Resource.Model>.error(error: error)
            completion(response)
        default:
            return URLSessionTask()
        }
        return URLSessionTask()
    }
}

这是所需的所有高级设置。下面是如何使用高级设置处理调用的示例。

let resource = GetArticlesResource()
let sessionTask = {ProjectName}DataRequestManager.shared.loadRequest(with: resource) { (response) in
    switch response {
    case let .success(model):
        // Do something with the model coming back
    case let .error(error):
        // Handle general error
    case let .httpError(statusCode):
        // Handle HTTP error
    }
}

还有一件事情需要考虑,以帮助在调用这些请求时编写整洁的代码。考虑扩展数据请求管理器并添加表示每个请求所做的事情的函数和设置资源的设置,包括设置您的标头、主体和查询。以下是如何调用它的示例。

注意:我已经扩展了我的资源类,以根据某些参数生成查询参数。

// {ProjectName}DataRequestManager.swift

extension {ProjectName}DataRequestManager {

    func getArticles(completion: @escaping (DataResponse<[Article]>) -> Void) -> URLSessionTask {
        let resource = GetArticlesResource()
        resource.setQuery(query: resource.articlesQuery())
        return {ProjectName}DataRequestManager.shared.loadRequest(with: resource, completion: completion)
    }
    
    // Example including setting a body
    func addArticle(with body: Article, completion: @escaping (DataResponse<Article>) -> Void) -> URLSessionTask {
        let resource = AddArticlesResource()
        resource.setBody(body: JSONCoder.encode(object: body))
        return {ProjectName}DataRequestManager.shared.loadRequest(with: resource, completion: completion)
    }
}


// {ProjectName}DataResources.swift

extension GetArticlesResource {
    
    func articlesQuery(with id: Int) -> String {
        return "?id=\(id)"
    }
}


// SomeFile.swift

let sessionTask = {ProjectName}DataRequestManager.shared.getArticles { (response) in
    switch response {
    case let .success(model):
        // Do something with the model coming back
    case let .error(error):
        // Handle general error
    case let .httpError(statusCode):
        // Handle HTTP error
    }
}

作者

Niklas Fahl (fahlout) - LinkedIn

灵感来自:http://mrgott.com/swift-programing/33-rest-api-in-swift-4-using-urlsession-and-jsondecode

许可协议

SimpleWebRequests 在MIT许可协议下可用。有关更多信息,请参阅LICENSE文件。