Я создаю маршрутизатор enum, который реализует URLRequestConvertible для каждой модели на уровне моей модели?
Это отличный вопрос, и, к сожалению, нет единого идеального ответа. Несомненно, есть несколько способов расширить шаблон Router
для размещения нескольких типов объектов. Первый вариант - добавить больше дел для поддержки другого типа объекта. Тем не менее, это становится довольно быстро, когда вы получаете более 6 или 7 случаев. Ваши операторы switch просто начинают выходить из-под контроля. Поэтому я бы не рекомендовал такой подход.
Другим способом решения проблемы является введение дженериков в Router
.
RouterObject Protocol
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?
}
Обновления маршрутизатора URLRequestConvertible
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
}
}
Надеюсь, это поможет пролить свет. Желаем удачи!
Если вы используете Windows, затем загрузите инструмент Fiddler Fiddler .
При этом будет настроен HTTP-прокси, который можно использовать для тестирования заголовков HTTP и просмотра всего HTTP-трафика на ПК и в браузере.
Если вы работаете на платформе * nix, вы можете изменить «хороший» уровень, чтобы сделать ваш процесс второстепенным, пока вы не достигнете удовлетворительного уровня «запаздывания». для ваших нужд.
Прежде всего, пожалуйста, никогда не искажайте свой код с помощью операторов if (DEBUG) workSlowly ();
. Вы будете укушены этой практикой, и это будет больно.
Во-вторых, используйте одно из решений по регулированию трафика, которые уже были опубликованы здесь. Я собираюсь добавить решение на основе Java: Sloppy . Его очень легко настроить и запустить везде, где работает Java.
Этот вопрос может помочь вам out .
Лично я добавляю что-то подобное в начало файла моей библиотеки или любого другого файла, который всегда включается:
if(DEBUG) {
sleep(2);
}
Это PHP, но в большинстве языков будет нечто подобное.
Один из вариантов (если вы работаете в Linux, но в другой системе unix есть аналогичные инструменты) формирование трафика (Google для команд HTB, qdics и tc)
Второй вариант - это модуль apache_mod_cband , это также, вероятно, проще начать.
Вы можете попробовать Чарльза. Это кроссплатформенный - я использую его, и он очень хорошо работает.
В Windows вы можете использовать Proxomitron или установить скрипач (например). Оба позволяют установить скорость загрузки.