1. ホーム
  2. ios

AlamofireのURLRequestConvertibleの正しい使い方

2023-08-20 11:08:21

質問

いくつかのチュートリアルや@matttからのREADMEを読みましたが、いくつかのことがわかりません。

  1. の適切な使用法は何ですか? URLRequestConvertible の適切な使い方は何でしょうか?ルータを一つ作るのに URLRequestConvertible プロトコルを実装して一つのルータを作ると、ほとんど読めなくなりそうです。エンドポイントごとにルータを作成したほうがいいのでしょうか?

  2. 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
        }
    }
    
    
  3. パラメータの渡し方は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 .