Faro 3.0.1

Faro 3.0.1

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布上次发布2018年1月
SwiftSwift 版本3.0
SPM支持 SPM

doozMenJelle VandebeeckLeroy Jenkins 维护。



Faro 3.0.1

BuddyBuild

======

要快速开始,请按照以下说明操作。要了解我们为何以及如何构建 Faro 的更深入信息,请访问 wiki 页面。

版本 2.0

版本 2.0 与 1.0 兼容,但您需要阅读变更日志并遵循迁移提示。

概念

我们通过使用作为触发 Call 并获取 ResultFunction 的 Service 类来构建服务请求。该函数由服务器响应后的代码组成。使用该函数来评估响应并获取请求的模型或抛出的错误。

特性

错误处理

  • 从 2.0 版本开始,错误处理使用 throws。一开始可能会让人困惑,但它有减少代码的潜力。
  • 我们专注于使错误描述性并在 FaroError
  • 默认情况下打印所有错误

服务

  • Service 是用 Swift 编写的,而不使用 Objective-C 运行时
  • Service 清洁地封装了所有用于处理网络请求的参数,在 Call 中。
  • 轻松编写一个 'MockService' 从本地驱动器加载 JSON

自动解析

  • 使用我们的 JSONDeserialization 和 JSONSerialization 运算符来解析关系和属性

协议

  • 因为我们使用协议,所以您可以使用任何类型,包括 CoreData 的 NSManagedObject 💪🏼

模拟

  • 如果您想切换来自服务器的数据或文件,请使用 FaroSingleton 单例。
  • 对单元测试很有用 💪🏼
  • 当 API 尚未可用时很有用🤓

安全

  • 证书固定
  • 在开发期间允许未验证的 HTTPS 主机
  • 在 401 错误时重试身份验证

专门为该目的创建了 FaroSecureURLSession

定义一个 Call

您可以编写示例服务,使调用成为一个单行代码。

let call = Call(path: "posts", method: HTTPMethod.GET, rootNode: "rootNode")
// the rootNode is used to query the json in the response in `rootNode(from json:)`

执行一个 Call

小贴士:查看 ServiceSpec,

简而言之,响应可以是

  • 需要反序列化成JSONDeserializable类型的JSON节点集合。
  • 单个JSON节点。
  • 响应中没有JSON,HTTP状态码就足够了。
  • 发生错误。

但这适用于任何HTTP方法,但让我们假设我们有

let call = Call(path: "posts")
let config = Configuration(baseURL: "http://jsonplaceholder.typicode.com"
let service =  Service<Post>(call, deprecatedService: DeprecatedService(configuration: config)

这看起来就像我们希望在config中的baseURL上执行一个call,它将被反序列化为Post类型。

可选地设置服务单例。例如在appdelegate启动后。

  let baseURL = "http://jsonplaceholder.typicode.com"

  // Optionally create your own FaroSession to handle for example security.
  FaroSingleton.setup(with: baseURL, session: FaroSession())

JSON节点集合

长版本

        service.collection { [weak self] (resultFunction) in
                DispatchQueue.main.async {
                    do {
                        let posts = try resultFunction() // Use the function to get the result or the error thrown
                          self?.label.text = "Performed call for \(posts)"
                    } catch {
                        // printError(error) // errors are printed by default so you could leave this out
                      }
              }
        }

短版本

        service.collection {
                DispatchQueue.main.async {
              let posts = try? $0() // Us anonymous closure arguments if you are comfortable with the syntax
              self?.label.text = "Performed call for posts"
              }
        }

单个JSON节点

短版本

        service.single {
            DispatchQueue.main.async {
                do {
                    let model = try $0()
                    print("🙏 sucessfully finished call")
                } catch {
                    print("👿 something went wrong with \(error)")
                }
            }
        }

响应中没有JSON

这通常是针对HTTP方法POST短版本

        service.sendWithoutJSONInResponse {
            DispatchQueue.main.async {
                do {
                    try $0()
                    print("🙏 sucessfully finished call")
                } catch {
                    print("👿 something went wrong with \(error)")
                }
            }
        }

错误

因为我们默认会抛出错误并打印出来,所以你应该始终知道问题出在哪里。当发生错误时,会发生两件事

  1. Service类中,有一个名为handleError的函数,当发生任何错误时都会被调用。默认情况下,此函数会打印错误。如有需要,您可以覆盖此函数
  2. 错误被抛出。错误始终为FaroError类型。

例如,如果当收到Unauthorized(401)时你想重新尝试请求,你可以。

        // Do any Service call like above

        do {
            let _ = try resultFunction()
        } cacht FaroError.invalidAuthentication(call: let call):

            // Handle this specific error case

         catch {
           // Handle all other possible errors.
            print("👿 something went wrong with \(error)")
        }

JSONSerialize / JSONDeserialize

反序列化和序列化可以自动发生。更详细的示例可以查看ParseableSpec测试。

你可以解析:

  • 原始类型
  • 日期
  • 枚举
  • 可反序列化对象的数组/集合

JSONDeserializable

class Zoo: JSONDeserializable {
    var uuid: String?
    var color: String?
    var animal: Animal?
    var date: Date?
    var animalArray: [Animal]?

    required init(_ raw: [String: Any]) throws {
        self.uuid |< raw["uuid"]
        self.color |< raw["color"]
        self.animal |< raw["animal"]
        self.animalArray |< raw["animalArray"]
        self.date |< (raw["date"], "yyyy-MM-dd")
    }
}

JSONSerializable

extension Zoo: JSONSerializable {
    var json: [String: Any] {
        get {
            var json = [String: Any]()
            json["uuid"] <| self.uuid
            json["color"] <| self.color
            json["animal"] <| self.animal
            json["animalArray"] <| self.animalArray
            json["date"] <| self.date
            return json
        }
    }
}

带必填属性的类型

因为Swift要求在我们可以对self调用map(from:)之前设置所有属性,所以你必须手动处理必填属性。

class Jail: JSONDeserializable {
    var cellNumber: String

    required init(_ raw: [String: Any]) throws {
        cellNumber = try create("cellNumber", from: raw)
    }

}

如果你不想创建而是更新现有实例怎么办?

模型应实现JSONUpdateable,并使用ServiceUpdate<T>

支持multipart表单

您可以使用Faro向服务器发送multipart/form-data。为此,您可以添加文件作为Call的参数。

示例

// Example image as Data
guard let jpeg = UIImageJPEGRepresentation(image, 0.7) else {
    print("👿 not a valid jpeg")
    return
}

// Create a multipart object and add it to the call
let multipart = MultipartFile(parameterName: "image", data: jpeg, mimeType: .jpeg)
let call = Call(path: "queries",
                method: .POST,
                parameter: [.multipart(multipart)])

// This assumes we have setup a singleton
let service = ServiceNoResponseData(call: call)
service.send {
  do {
    try $0()
  } catch {
    // handle error
  }
}

安全

安全由FaroSecureURLSession处理。每个DeprecatedService都有一个默认为FaroURLSession的session。

如果您需要更多的安全选项,您可以提供一个FaroSecureURLSession的子类,或者实现FaroSessionable。为了让Faro知道您的会话,您需要通过FaroSingleton提供它,或者为每个创建的DeprecatedService实例提供。

但首先实现FaroSecureURLSession

然后将它添加到Faro

通过单例

func setupFaroWithSecurity() {
        let baseURL = "http://jsonplaceholder.typicode.com"

        let sessionSessionDelegate = FaroURLSessionDelegate(allowUntrustedCertificates: false)
        let secureSession = FaroSecureURLSession(urlSessionDelegate: sessionSessionDelegate)
        FaroSingleton.setup(with: baseURL, session: secureSession)
// Example image as Data
guard let jpeg = UIImageJPEGRepresentation(image, 0.7) else {
    print("👿 not a valid jpeg")
    return
}

通过已弃用 DeprecatedService 实例

DeprecatedService(configuration: Configuration(baseURL: baseURL), faroSession: secureSession)

要求

  • iOS 8 或更高版本
  • 因为我们使用了泛型,所以您只能在 Swift 文件中使用此 pod。您可以与 Objective-C 混搭,但不能与泛型类混搭。更多信息请参考 这里

安装

Faro 可通过 CocoaPodsSwift 包管理器 获取。

若使用 CocoaPods 安装,请将以下行添加到您的 Podfile 中

pod "Faro"

贡献

不要太过于思考,要努力尝试!

更多关于 贡献指南 的信息,请参阅 wiki 页面。

编码指南

我们遵循 iCapps 编码指南

我们使用 Swiftlint 来保持代码整洁。

许可证

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