超空间 (Hyperspace)

CI Status Version Carthage compatible SwiftPM compatible Platform codecov License

超空间 (Hyperspace) 为 URLSession 和 HTTP 提供了一个简单的抽象层。 主要目标有以下几个:

内容

用法

1. 创建请求

创建请求时有多种选择。 这些包括创建静态函数以减少创建 Request 对象时的样板代码,或者只是在本地创建它们。 此外,如果您的网络请求很复杂,您仍然可以创建自己的自定义结构体来封装和提供 Request 对象。

选项 1 - 扩展 Request

下面的示例说明了如何在 Request 上创建一个扩展,这可以大大减少在像社交网络 feed 中创建新帖子的请求时的样板代码。 它利用了 Request 中的许多默认值(所有这些都是可定制的)以保持定义的简洁

extension Request where Response == Post {
    
    static func createPost(_ post: NewPost) -> Request<Post> {
        return Request(method: .post, url: URL(string: "https://jsonplaceholder.typicode.com/posts")!, headers: [.contentType: .applicationJSON], body: try? HTTP.Body.json(post))
    }
}

选项 2 - 在本地定义每个 Request

let createPostRequest: Request<Post> = Request(method: .post, url: URL(string: "https://jsonplaceholder.typicode.com/posts")!, headers: [.contentType: .applicationJSON], body: try? HTTP.Body.json(post))

选项 3 - 创建一个封装 RequestCreatePostRequest

struct CreatePostRequest {
    let newPost: NewPost
    
    var request: Request<Post> {
        return Request(method: .post, url: URL(string: "https://jsonplaceholder.typicode.com/posts")!, headers: [.contentType: .applicationJSON], body: try? HTTP.Body.json(post))
    }
}

对于以上示例,Post 响应类型和 NewPost 主体定义如下

struct Post: Decodable {
    let id: Int
    let userId: Int
    let title: String
    let body: String
}
struct NewPost: Encodable {
    let userId: Int
    let title: String
    let body: String
}

2. 创建请求默认值(可选)

为了避免必须为应用程序中的每个请求定义默认 Request 属性值,依赖 Hyperspace 提供的 RequestDefaults 会很有用。 这些甚至可以自定义

RequestDefaults.defaultCachePolicy = .reloadIgnoringLocalCacheData // Default cache policy is '.useProtocolCachePolicy'
RequestDefaults.defaultDecoder = MyCustomDecoder() // Default decoder is JSONDecoder()

3. 创建一个 BackendService 来执行您的请求

我们建议通过为要与之通信的 API 的每个部分创建单独的“控制器”对象来遵守接口隔离原则。 每个控制器都应该暴露一组相关函数,并使用 BackendService 来执行请求。 但是,对于这个简单的例子,我们将直接使用 BackendService 作为视图控制器上的 private 属性

class ViewController: UIViewController {
    private let backendService = BackendService()

    // Rest of your view controller code...
}

4. 实例化您的请求

假设一个视图控制器应该在用户点击“发送”按钮时创建帖子。 可能是这样的

@IBAction private func sendButtonTapped(_ sender: UIButton) {
    let title = ... // Get the title from a text view in the UI...
    let message = ... // Get the message from a text view/field in the UI...
    let post = NewPost(userId: 1, title: title, body: message)

    let createPostRequest = CreatePostRequest(newPost: post)

    // Execute the network request...
}

5. 使用 BackendService 执行请求

对于上面的示例,您将如何执行请求并解析响应。 虽然所有数据转换都发生在底层 URLSession 正在使用的后台队列中,但所有 BackendService 完成回调都发生在主队列中,因此无需担心在更新 UI 之前进行线程处理。 请注意,下面成功响应的关联值的类型是 Post 结构体,如上面的 CreatePostRequest 中所定义的那样

do {
    let post = NewPost(userId: 1, title: title, body: "")
    let createPostRequest = Request<Post>.createPost(post)
    let createdPost = try await backendService.execute(request: createPostRequest)
    // Insert the new post into the UI...
    
} catch {
    // Alert the user to the error...
}

示例

克隆仓库

git clone https://github.com/BottleRocketStudios/iOS-Hyperspace.git

从这里,您可以打开 Hyperspace.xcworkspace 并运行示例

共享代码

示例目标

Playgrounds

要求

安装

Cocoapods

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

pod 'Hyperspace'

Carthage

将以下内容添加到您的 Cartfile

github "BottleRocketStudios/iOS-Hyperspace"

运行 carthage update 并按照 Carthage 自述文件中的步骤进行操作。

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/BottleRocketStudios/iOS-Hyperspace.git", from: "5.0.0")
]

作者

Bottle Rocket Studios

许可证

Hyperspace 在 Apache 2.0 许可证下可用。 有关更多信息,请参见 LICENSE.txt 文件。

贡献

请参阅 CONTRIBUTING 文档。 谢谢,贡献者