Ответ 1
Это очень хорошие вопросы. Позвольте мне попытаться ответить на каждый по очереди.
Я создаю маршрутизатор enum, который реализует URLRequestConvertible для каждой модели в моем уровне модели?
Это большой вопрос, и, к сожалению, нет однозначного ответа. Конечно, есть несколько способов расширить шаблон Router
для размещения нескольких типов объектов. Первый вариант - добавить несколько случаев для поддержки другого типа объекта. Тем не менее, это становится волосатым довольно быстро, когда вы получаете более 6 или 7 случаев. Ваши операторы switch только начинают выходить из-под контроля. Поэтому я бы не рекомендовал этот подход.
Другой способ подойти к проблеме - это ввести дженерики в Router
.
Протокол RouterObject
protocol RouterObject {
func createObjectPath() -> String
func readObjectPath(identifier: String) -> String
func updateObjectPath(identifier: String) -> String
func destroyObjectPath(identifier: String) -> String
}
Объекты модели
struct User: RouterObject {
let rootPath = "/users"
func createObjectPath() -> String { return rootPath }
func readObjectPath(identifier: String) -> String { return "\(rootPath)/\(identifier)" }
func updateObjectPath(identifier: String) -> String { return "\(rootPath)/\(identifier)" }
func destroyObjectPath(identifier: String) -> String { return "\(rootPath)/\(identifier)" }
}
struct Company: RouterObject {
let rootPath = "/companies"
func createObjectPath() -> String { return rootPath }
func readObjectPath(identifier: String) -> String { return "\(rootPath)/\(identifier)" }
func updateObjectPath(identifier: String) -> String { return "\(rootPath)/\(identifier)" }
func destroyObjectPath(identifier: String) -> String { return "\(rootPath)/\(identifier)" }
}
struct Location: RouterObject {
let rootPath = "/locations"
func createObjectPath() -> String { return rootPath }
func readObjectPath(identifier: String) -> String { return "\(rootPath)/\(identifier)" }
func updateObjectPath(identifier: String) -> String { return "\(rootPath)/\(identifier)" }
func destroyObjectPath(identifier: String) -> String { return "\(rootPath)/\(identifier)" }
}
маршрутизатор
let baseURLString = "http://example.com"
var OAuthToken: String?
enum Router<T where T: RouterObject>: URLRequestConvertible {
case CreateObject(T, [String: AnyObject])
case ReadObject(T, String)
case UpdateObject(T, String, [String: AnyObject])
case DestroyObject(T, String)
var method: Alamofire.Method {
switch self {
case .CreateObject:
return .POST
case .ReadObject:
return .GET
case .UpdateObject:
return .PUT
case .DestroyObject:
return .DELETE
}
}
var path: String {
switch self {
case .CreateObject(let object, _):
return object.createObjectPath()
case .ReadObject(let object, let identifier):
return object.readObjectPath(identifier)
case .UpdateObject(let object, let identifier, _):
return object.updateObjectPath(identifier)
case .DestroyObject(let object, let identifier):
return object.destroyObjectPath(identifier)
}
}
// MARK: URLRequestConvertible
var URLRequest: NSMutableURLRequest {
let URL = NSURL(string: baseURLString)!
let mutableURLRequest = NSMutableURLRequest(URL: URL.URLByAppendingPathComponent(path))
mutableURLRequest.HTTPMethod = method.rawValue
if let token = OAuthToken {
mutableURLRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
}
switch self {
case .CreateObject(_, let parameters):
return Alamofire.ParameterEncoding.JSON.encode(mutableURLRequest, parameters: parameters).0
case .UpdateObject(_, _, let parameters):
return Alamofire.ParameterEncoding.URL.encode(mutableURLRequest, parameters: parameters).0
default:
return mutableURLRequest
}
}
}
Пример использования
func exampleUsage() {
let URLRequest = Router.CreateObject(Location(), ["address": "1234 Road of Awesomeness"]).URLRequest
Alamofire.request(URLRequest)
.response { request, response, data, error in
print(request)
print(response)
print(data)
print(error)
}
}
Теперь есть, конечно, несколько компромиссов, которые вы должны сделать здесь. Во-первых, ваши объекты модели должны соответствовать протоколу RouterObject
. В противном случае Router
не имеет понятия, что использовать для пути. Кроме того, вам нужно убедиться, что все ваши пути могут быть построены с помощью одного identifier
. Если они не могут, этот проект может не сработать. Последняя проблема заключается в том, что вы не можете хранить baseURL
или OAuthToken
непосредственно внутри перечисления Router
. К сожалению, статические и хранимые свойства еще не поддерживаются в общих перечислениях.
Независимо от того, это, безусловно, было бы правильным способом избежать создания Router
для каждого объекта модели.
Должен ли
Alamofire.Manager.sharedInstance
использоваться как мой одиночный экземплярNetworkManager
?
Это, безусловно, можно было бы использовать таким образом. Это действительно зависит от вашего варианта использования и того, как вы разработали свой сетевой доступ. Это также зависит от того, сколько разных типов сеансов вам нужно. Если вам нужны фоновые сеансы и сеансы по умолчанию, вам, вероятно, по-прежнему нужна концепция NetworkManager
, которая содержит каждый пользовательский экземпляр Manager
. Однако, если вы просто нажмете на сеть с сеансом по умолчанию, то, вероятно, будет sharedInstance
.
Как можно использовать
baseURL
одиночного синтаксисаAlamofire
в сочетании с шаблономRouter
?
Хороший вопрос... приведенный ниже код является одним из примеров того, как это можно сделать.
Расширение Alamofire Manager
extension Manager {
static let baseURLString = "http://example.com"
static var OAuthToken: String?
}
Router URLRequestConvertible Updates
var URLRequest: NSMutableURLRequest {
let URL = NSURL(string: Alamofire.Manager.baseURLString)!
let mutableURLRequest = NSMutableURLRequest(URL: URL.URLByAppendingPathComponent(path))
mutableURLRequest.HTTPMethod = method.rawValue
if let token = Alamofire.Manager.OAuthToken {
mutableURLRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
}
switch self {
case .CreateObject(_, let parameters):
return Alamofire.ParameterEncoding.JSON.encode(mutableURLRequest, parameters: parameters).0
case .UpdateObject(_, _, let parameters):
return Alamofire.ParameterEncoding.URL.encode(mutableURLRequest, parameters: parameters).0
default:
return mutableURLRequest
}
}
Надеюсь, это поможет пролить свет. Удачи!