CRUDE-Futures 0.1.28

CRUDE-Futures 0.1.28

测试已测试
语种语言 SwiftSwift
许可证 MIT
发布最新版本2016年8月
SPM支持 SPM

Jason Welch 维护。



 
依赖
Alamofire>= 3.4
SwiftyJSON>= 2.3
BrightFutures>= 4.1
Result>= 2.0
 

  • Jason Welch

CRUDE-Futures

通过从 CRUDE 的各种协议继承,您可以轻松地在远程服务器上创建、读取、更新、删除和枚举您的数据模型。CRUDE-Futures 利用 BrightFutures 来异步加载数据模型,通过 Alamofire 发送请求,并通过 SwiftyJSON 映射返回的 JSON。

协议 路径覆盖 请求类型 便捷方法 返回
CRUDECreatable createPath POST createOnServer Self
createOnServerOkay Okay
CRUDEReadable readPath GET readFromServer Self
readFromServerWithId Self
CRUDEUpdatabe updatePath PUT updateOnServer Self
updateOnServerOkay Okay
CRUDEDeletable deletePath DELETE deleteFromServer Okay
CRUDEEnumeratable enumeratePath GET enumerateFromServer [Self]


CRUDE 只适用于返回 JSON 的 API 调用。


需求

Crude-Futures 依赖于以下 pods...

安装

CRUDE-Futures 可通过 CocoaPods 使用。要安装它,只需将以下行添加到您的 Podfile 中

pod 'CRUDE-Futures', '~> 0.1'

入门

第一步也是最重要的一步是设置 CRUDE 以在您的应用中使用。在您的 AppDelegate 中导入 CRUDE_FUTURES,然后在 application(application: didFinishLaunchingWithOptions:) 内调用 configure。例如:

// AppDelegate
CRUDE.configure(baseURL: "https://mysite.com/api", headers: kDefaultHeaders)

如果您想让 CRUDE 在调用 API 时进行某种日志记录,您可以通过变量提供一个 CRUDEResponseLog 块。这可以通过以下方式完成:

let myLogger: CRUDEResponseLog = { response in
    if let error = response.result.error {
         print("CRUDE FAILURE: \(error.localizedDescription)")
    } else 
        let method = response.request?.HTTPMethod ?? "UNKNOWN"
        let urlString = response.request?.URLString ?? "unknown"
        print("\(network.response!.statusCode) from \(method) \(urlString)")
    }
}

CRUDE.configure(baseURL: "https://mysite.com/api", headers: kDefaultHeaders, responseLoggingBlock: myLogger)

…或者,通过在配置调用结束时提供块来完成

CRUDE.configure(baseURL: "https://mysite.com/api", headers: kDefaultHeaders) { response in
    print("CRUDE response: \(response)")
}

您也可以在配置了CRUDE之后使用}CRUDE.setResponseLoggingBlock函数设置响应日志块。您甚至可以使用}CRUDE.setRequestLoggingBlock函数在请求之前设置一个记录器。例如

CRUDE.setRequestLoggingBlock() { method, path, params, headers in
    print("CRUDE request \(method) \(path)")
    params?.forEach { print("\($0)=\($1)") }
    print("HTTP Headers:")
    headers.forEach { print("\($0)=\($1)") }
}


如果您不提供日志块,可以通过将}CRUDE.shouldUseDefaultLogger设置为}true来使用默认记录器。


可映射模型

尽管CRUDE旨在与结构体一起使用,但它也可以与类和甚至是管理对象(在一定程度上)一起使用。

您需要做的第一件事是导入}CRUDE_Futures和}SwiftyJSON。然后通过应用任何数量的协议来声明您打算如何使用您的模型。对于只读模型,您可能只需要使用}CRUDEReadable,或者如果您希望一次检索多个项目,也许可以添加}CRUDEEnumeratable。数据实体可以通过使用}CRUDECreatable和}CRUDEDeletable来创建和销毁。如果您想修改实体并要求服务器符合您创建的新现实,您可以使用}CRUDEUpdatable

所有这些不同的协议都符合}CRUDERequestable,需要模型设置其}path字符串,通知CRUDE这些模型通常在哪里可以找到。例如}static let path = "people"将告诉CRUDE对“https://mysite.com/api/people”发送请求。模型还可以设置一个}objectKey字符串,以在返回的JSON将所有珍贵的属性都封装在一个字典中时使用。如果您在模型中不设置此值,它将默认为}nil

为了将一些JSON轻松地转换为有用的模型,需要它是}JSONConvertable的。这意味着可以通过传递一个}JSON对象来初始化它。以下是一个Person模型对象的示例

struct Person: CRUDEReadable {
    static let path: String = "person"

    let id: Int
    let firstName: String
    let lastName: String
    let favoriteColor: String?

    init(_ json: JSON) {
        id = json["id_Number"].intValue
        firstName = json["first_name"].stringValue
        lastName = json["last_name"].stringValue
        favoriteColor = json["favorite_color"].string
    }
}

是的,您确实需要执行一对一映射,但这可能会带来回报。比如说,您有一个}Household实体,它拥有几个人员。它可以像这样映射其}people属性

    people = json["people"].array?.map { Person($0) }.sort { $0.firstName < $1.firstName} ?? []

看看这个!我们甚至在一行内按名字的顺序对它们进行了排序!如果您打算通过}Household而不是}Person来制作所有请求并进行映射,您可以让}Person只遵循}JSONConvertable

如果您有一个将要执行所有操作的模型,您可以使用}CRUDEMappable来替代列举所有五个。


虽然创建和枚举模型不需要}id属性,但它对于}CRUDEReadable、}CRUDEUpdatable和}CRUDEDeletable来说是必需的。这样做是为了自动推断URL路径。例如,请求ID为}12345的人员将发送到“https://mysite.com/api/people/12345”。您可以覆盖此路径(稍后解释),但}id的要求仍然存在。


更新属性 - 写入方式

为了更新远程数据库中的实体,它需要是}JSONAttributable的。这意味着它的属性具有逆映射。

var attributes: [String : AnyObject?] {
    return [
        "id_Number": id,
        "first_name": firstName,
        "last_name": lastName,
        "favorite_color": favoriteColor
    ]
}

请注意,}attributes包含可选对象。JSONAttributable提供了一个名为}nullifiedAttributes的computed属性,它将为任何nil属性提供一个值为}NSNull的值,例如可能}favoriteColor。它还提供了一个名为}valuedAttributes的computed属性,它可以自动删除没有值的属性。

在}Household模型示例中,实体会在计算}attributes时包含}"people": people.map { $0.nullifiedAttributes }


CRUDE假设您的API只更新其接收到的参数的属性,因此对于已设置为nil的属性需要NSNull值。如果不是这样(没有新闻就是没有新闻),那么您可以使用valuedAttributes并在更新时指定该规定:thisPerson.updateOnServer(valuedAttributesOnly: true)


发起调用

那么API调用看起来是什么样子的呢?某些协议提供静态请求,某些提供实例请求,还有一些两者都提供。例如,如果您想获取具有12345编号的新人

Person.readFromServerWithId(12345)

…或者如果您已经有这个人,只是想确保您有最新版本

self.person.readFromServer()

请注意,在发出这些请求时,CRUDE不会修改实体。它会在完成后提供一个新的实体。异步调用使用BrightFutures语法处理,因此检索最新的个人版本可能如下所示

self.person.readFromServer().onSuccess { person in
    self.person = person
}.onFailure { error in
    print(error)
}.onComplete { _ in
    self.refreshControl?.endRefreshing()
}

请注意,虽然.onComplete提供了一个原始的Result,如果您只是想要在这个块中执行清理代码,可以将其丢弃。在这个例子中,我们根据加载是否成功更新视图的refreshControl。

可映射协议为您提供了方便的请求,您可以根据意图显式调用,但您仍然可以访问它们使用的底层请求。最基本的方法是request,它将给您一个包含JSON对象的Future。

CRUDE.request(.GET, CRUDE.baseURL + "person/\(self.person.id)")

如果您想直接控制请求,但不想麻烦地将JSON转换为实体,可以使用requestObject来获取单个实体或requestObjectsArray来获取实体数组。只需确保将返回的Future转换为所需的类型。

let request = CRUDE.requestObjectsArray(.GET, CRUDE.baseURL + "person/\(self.person.id)", parameters: queryItems) as Future<[Person], NSError>

request.onSuccess { people in
    self.household.people = people
}

获取确认

Okay是一个空对象,唯一目的是为了在.onSuccess中返回一些东西。这用于任何是CRUDEDeletable的模型,因为DELETE请求不应该返回任何可映射的JSON。

如果您想发出请求,但对服务器返回的内容不感兴趣,可以使用CRUDE.requestForSuccess,它也会返回一个Okay

引导流量

CRUDE假设了一个简单的API结构,其中与模型相关的请求都是这样进行的。如果您的baseURL是“https://mysite.com/api/”,那么针对Person对象的请求应该如下所示

如前所述,所有这些都可以使用path自动完成。但是,您的API可能并不那么简单。可能更新是“https://mysite.com/api/household/people/12345”,而检索特定的人来自“https://mysite.com/api/person/12345”。五个协议中的每一个都有针对该类型请求的特定路径,因此在这种情况下,您会设置updatePathreadPath的值,让path处理其他三个情况。

您可以静态设置特定的路径

static let enumeratePath = CRUDE.baseURL + "/household/people"

…或者动态设置

static var enumeratePath: String {
    return CRUDE.baseURL + "/households/\(householdID)/people"
}


始终设置path,如果有任何边缘情况,请提供特定的路径。


控制请求

如果您想能够控制请求流量本身,请使用CRUDERequest对象而不是CRUDE静态方法。

初始化一个CRUDERequest实例的方式与您使用请求函数的方式相同。必须提供urlString,并且可以选择提供parameters和/或headers。要执行请求,您有三个选项,非常类似于三个基本的CRUDE静态函数……

  • 使用makeRequestForJSON代替request
  • 使用makeRequestForObject<T: JSONConvertable>代替requestObject<T: JSONConvertable>
  • 使用makeRequestForObjectsArray<T: JSONConvertable>代替requestObjectsArray<T: JSONConvertable>

在请求进行中时,您可以使用pauseRequest()来暂时中断。然后您可以稍后调用resumeRequest(),或者放弃《code>cancelRequest。


您仍需要在您的AppDelegate中首先配置CRUDE。


想获得更多控制?!

如果您还想要自己完成更多的工作……那么您可能不应该使用这个Pod。额外的便捷性对您来说已经没有意义了。您也是穿上溜冰鞋去慢跑吗?您最喜欢的餐厅是The Melting Pot吗,在那里您租厨房用具来自己做饭?当然他们帮您买了一些杂货,但实际上您做了大部分的工作。

请使用AlamofireSwiftyJSONBrightFutures。这就是我用来组装一系列您可能不会使用到的工具的方式。

^ 免责声明:The Melting Pot提供的餐饮体验与美食同样重要。

作者

Jason Welch, [email protected]

许可

CRUDE-Futures遵循MIT许可。有关更多信息,请参阅LICENSE文件。