AlamofireのURLRequestConvertibleの正しい使い方
質問
いくつかのチュートリアルや@matttからのREADMEを読みましたが、いくつかのことがわかりません。
-
の適切な使用法は何ですか?
URLRequestConvertible
の適切な使い方は何でしょうか?ルータを一つ作るのにURLRequestConvertible
プロトコルを実装して一つのルータを作ると、ほとんど読めなくなりそうです。エンドポイントごとにルータを作成したほうがいいのでしょうか? -
2番目の質問は、Swift言語の経験不足が原因である可能性が高いです。私はなぜ
enum
はルータを構築するために使用されるのですか?なぜ静的メソッドを持つクラスを使用しないのでしょうか? 以下はその例です(AlamofireのREADMEより)。enum Router: URLRequestConvertible { static let baseURLString = "http://example.com" static let perPage = 50 case Search(query: String, page: Int) // MARK: URLRequestConvertible var URLRequest: NSURLRequest { let (path: String, parameters: [String: AnyObject]?) = { switch self { case .Search(let query, let page) where page > 1: return ("/search", ["q": query, "offset": Router.perPage * page]) case .Search(let query, _): return ("/search", ["q": query]) } }() let URL = NSURL(string: Router.baseURLString)! let URLRequest = NSURLRequest(URL: URL.URLByAppendingPathComponent(path)) let encoding = Alamofire.ParameterEncoding.URL return encoding.encode(URLRequest, parameters: parameters).0 } }
-
パラメータの渡し方は2通りあります。
case CreateUser([String: AnyObject]) case ReadUser(String) case UpdateUser(String, [String: AnyObject]) case DestroyUser(String)
で、(ユーザーが4つのパラメータを持っているとすると)
case CreateUser(String, String, String, String) case ReadUser(String) case UpdateUser(String, String, String, String, String) case DestroyUser(String)
@mattt は、例では最初のものを使っています。しかし、これではルータの外(例えばUIViewController内)でパラメータ名を"hardcoding"してしまうことになります。 パラメータ名のタイポはエラーになる可能性があります。
他の人は2番目のオプションを使っていますが、その場合、各パラメータが何を表しているかはまったくわかりません。
何が正しい方法なのでしょうか?
どのように解決するのですか?
素晴らしい質問ですね。ひとつひとつ分解してみましょう。
<ブロッククオート現実のAPIにおけるURLRequestConvertibleの適切な使用方法は何ですか?
このような
URLRequestConvertible
プロトコルは、与えられたオブジェクトが有効な
NSURLRequest
. このプロトコルを特定の方法で使用することを強制するような厳密なルールやガイドラインは、実際には存在しないのです。これは単に、他のオブジェクトが適切に NSURLRequest
. Alamofireに関連する詳細な情報は、以下を参照してください。
ここで
.
エンドポイントごとに1つのRouterを作成したほうがよいですか?
絶対にやめましょう。それは
Enum
. SwiftのEnumオブジェクトは驚くほど強力で、大量の共通の状態を共有し、実際に異なる部分で切り替えることができます。Enumオブジェクトを作成できることで
NSURLRequest
を作成できることは、本当に強力です!
let URLRequest: NSURLRequest = Router.ReadUser("cnoon")
なぜルータを作るのにenumを使うのかがわからない?なぜ静的メソッドを持つクラスを使用しないのでしょうか?
enumは、複数の関連するオブジェクトを共通のインターフェイスの下で表現する、より簡潔な方法であるため、使用されています。すべてのメソッドはすべてのケースで共有されます。もし静的メソッドを使用した場合、各メソッドに対して各ケース用の静的メソッドを用意しなければなりません。あるいは、オブジェクトの内部でObj-Cスタイルのenumを使わなければならないでしょう。以下はその簡単な例です。
enum Router: URLRequestConvertible {
static let baseURLString = "http://example.com"
case CreateUser([String: AnyObject])
case ReadUser(String)
case UpdateUser(String, [String: AnyObject])
case DestroyUser(String)
var method: Alamofire.HTTPMethod {
switch self {
case .CreateUser:
return .post
case .ReadUser:
return .get
case .UpdateUser:
return .put
case .DestroyUser:
return .delete
}
}
var path: String {
switch self {
case .CreateUser:
return "/users"
case .ReadUser(let username):
return "/users/\(username)"
case .UpdateUser(let username, _):
return "/users/\(username)"
case .DestroyUser(let username):
return "/users/\(username)"
}
}
}
異なるエンドポイントのメソッドを取得するために、探しているエンドポイントのタイプを定義するためのパラメータを渡すことなく、同じメソッドを呼び出すことができます。
let createUserMethod = Router.CreateUser.method
let updateUserMethod = Router.UpdateUser.method
あるいは、パスを取得したい場合も、同じような呼び出しになります。
let updateUserPath = Router.UpdateUser.path
let destroyUserPath = Router.DestroyUser.path
では、静的メソッドを使って同じ方法を試してみましょう。
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 pathForUpdateUser: String {
// this is going to get really repetitive for each case for each method
return "/update/user/path"
}
// This approach gets sloppy pretty quickly
}
注:ケースを切り替えるプロパティや関数があまりない場合、enumは構造体よりも多くの利点を提供しません。これは単に、異なる構文上の糖分を含む代替アプローチです。
列挙型は状態とコードの再利用を最大化することができます。また、関連付けられた値によって、ある程度似ているが信じられないほど異なる要件を持つオブジェクトをグループ化するなど、本当に強力なことを行うことができます...たとえば、次のようなものです。
NSURLRequest
のように、作成することができます。
読みやすさを向上させるために、enumケースのパラメータを構築する正しい方法は何ですか?(これをマッシュアップする必要がありました)
すごい質問ですね。あなたはすでに2つの可能な選択肢を提示しました。あなたのニーズにもう少し合うかもしれない3つ目を追加させてください。
case CreateUser(username: String, firstName: String, lastName: String, email: String)
case ReadUser(username: String)
case UpdateUser(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の現時点での3つのオプションで、どれを使うのが正しいかはユースケースに依存します。
更新
リリースに伴い、? Alamofire 4.0 ??????? をリリースしました。
URLRequestConvertible
は非常に賢くなり、投げることもできるようになりました。Alamofireでは、無効なリクエストを処理し、レスポンスハンドラで適切なエラーを生成するための完全なサポートが追加されました。この新しいシステムの詳細については、私たちの
README
.
関連
-
[解決済み】Xcode - 'NSUnknownKeyException', reason: ... this class is not key value coding-compliant for the key X" エラーの修正方法とは?
-
iOS classic error Undefined symbols for architecture XXX:
-
[解決済み] アトミック属性と非アトミック属性の違いは何ですか?
-
[解決済み] キーボードがあるときに、UITextFieldを編集開始時に上に移動させるには?
-
[解決済み] UITableViewの選択を無効にするにはどうすればよいですか?
-
[解決済み] 文字列の長さを取得する
-
[解決済み] UITableViewCell、スワイプ時に削除ボタンを表示させる
-
[解決済み] Swiftを使用してアプリのバージョンとビルド番号を取得するにはどうすればよいですか?
-
[解決済み] swiftで電子メールアドレスを検証する方法は?
-
[解決済み】iOSアプリの名前を変更する方法は?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[エラー処理】iOSのエラー、アーキテクチャx86_64の未定義シンボルについて
-
制御が非ボイド関数の終了に達する
-
[解決済み] iOSまたはmacOSで、インターネット接続が有効かどうかを確認するにはどうすればよいですか?
-
[解決済み] performSelectorのセレクタが不明なため、リークが発生する可能性があります。
-
[解決済み] 制約条件の変更をアニメーションで表現するには?
-
[解決済み] Objective-Cでデリゲートを作成するにはどうしたらいいですか?
-
[解決済み] UILabelで複数行のテキストを表示する
-
[解決済み] iPadマルチタスクのサポートには、これらの方向が必要です。
-
[解決済み] UITextBorderStyleNoneを使用してUITextFieldのパディングを設定する
-
[解決済み] ファイルはユニバーサル(3スライス)ですが、iOSの静的ライブラリのための(n)ARMv7-sスライスエラーが含まれていない、どうにかして回避するには?