很好的问题.让我们逐一分析一下.
URLRequestConvertible在真实API中的正确用法是什么?
URLRequestConvertible
协议是确保给定对象可以创建有效NSURLRequest
的轻量级方式.实际上并没有一套严格的规则或指导方针强迫您以任何特定方式使用此协议.它只是一个方便的协议,允许其他对象存储正确创建NSURLRequest
所需的状态.关于Alamofire的更多信息可以在here找到.
我应该 for each 端点创建一个路由吗?
绝对不是.这将 destruct 使用Enum
的全部目的.Swift Enum对象功能强大,让您可以共享大量公共状态,并打开实际不同的部分.能够用以下简单的东西创建一个NSURLRequest
真的很强大!
let URLRequest: NSURLRequest = Router.ReadUser("cnoon")
我搞不懂为什么要用枚举来构建路由?为什么我们不将类与静电方法一起使用呢?
之所以使用枚举,是因为它是在公共接口下表示多个相关对象的更简明的方式.所有的方法都是在所有 case 之间共享的.如果您使用静电方法,则必须 for each 方法的每个 case 使用一个静电方法.否则,您必须在对象内使用Obj-C样式的枚举.这里有一个简单的例子来说明我的意思.
enum Router: URLRequestConvertible {
static let baseURLString = "http://example.com"
case CreateUser([String: AnyObject])
case ReadUser(String)
case 更新User(String, [String: AnyObject])
case DestroyUser(String)
var method: Alamofire.HTTPMethod {
switch self {
case .CreateUser:
return .post
case .ReadUser:
return .get
case .更新User:
return .put
case .DestroyUser:
return .delete
}
}
var path: String {
switch self {
case .CreateUser:
return "/users"
case .ReadUser(let username):
return "/users/\(username)"
case .更新User(let username, _):
return "/users/\(username)"
case .DestroyUser(let username):
return "/users/\(username)"
}
}
}
要获得任何不同端点的方法,您可以调用相同的方法,而不必传入任何参数来定义您要查找的端点类型,它已经由您 Select 的 case 处理.
let createUserMethod = Router.CreateUser.method
let updateUserMethod = Router.更新User.method
或者,如果您想获取路径,相同类型的呼叫.
let updateUserPath = Router.更新User.path
let destroyUserPath = Router.DestroyUser.path
现在,让我们使用静电方法try 相同的方法.
struct Router: URLRequestConvertible {
static let baseURLString = "http://example.com"
static var method: Method {
// how do I pick which endpoint?
}
static func methodForEndpoint(endpoint: String) -> Method {
// but then I have to pass in the endpoint each time
// what if I use the wrong key?
// possible solution...use an Obj-C style enum without functions?
// best solution, merge both concepts and bingo, Swift enums emerge
}
static var path: String {
// bummer...I have the same problem in this method too.
}
static func pathForEndpoint(endpoint: String) -> String {
// I guess I could pass the endpoint key again?
}
static var pathForCreateUser: String {
// I've got it, let's just create individual properties for each type
return "/create/user/path"
}
static var pathFor更新User: String {
// this is going to get really repetitive for each case for each method
return "/update/user/path"
}
// This approach gets sloppy pretty quickly
}
注意:如果您没有太多的属性或函数来打开大小写,那么枚举就不会比 struct 有多大优势.这只是一种具有不同句法糖的替代方法.
枚举可以最大化状态和代码重用.关联的值还允许你做一些非常强大的事情,比如对有点相似但有着难以置信的不同需求的对象进行分组...比如NSURLRequest
个创意.
为枚举用例构造参数以提高可读性的正确方法是什么?(我不得不把这一块捣碎在一起)
这是个很棒的问题.您已经列出了两种可能的 Select .我再加一个可能更适合您需要的第三个.
case CreateUser(username: String, firstName: String, lastName: String, email: String)
case ReadUser(username: String)
case 更新User(username: String, firstName: String, lastName: String, email: String)
case DestroyUser(username: String)
在有关联值的情况下,我认为为元组中的所有值添加显式名称可能会有所帮助.这确实有助于构建上下文.这样做的缺点是,您必须在switch语句中重新声明这些值.
static var method: String {
switch self {
case let CreateUser(username: username, firstName: firstName, lastName: lastName, email: email):
return "POST"
default:
return "GET"
}
}
虽然这为您提供了一个很好的、一致的上下文,但它变得相当冗长.这是您目前在SWIFT中的三个选项,哪一个是正确的取决于您的使用 case .
更新
随着?? 阿拉莫菲尔4.0??, URLRequestConvertible
现在可以更加智能,也可以投掷.我们在Alamofire中添加了对处理无效请求和通过响应处理程序生成合理错误的全面支持.这个新系统在我们的README页中有详细的记录.