1. ホーム
  2. ios

[解決済み] パラメータ付きSwift GETリクエスト

2023-01-20 03:56:25

質問

私はswiftの初心者なので、おそらく私のコードには多くの欠陥があるでしょう。 GET リクエストをパラメータ付きでローカルホストサーバーに送信することです。もっと言うと、私は私の関数が2つのパラメータを取ることを考えると、それを達成しようとしています。 baseURL:string,params:NSDictionary . 私はそれらの2つを実際のURLRequestに結合する方法がわからないのですか?以下は、私がこれまでに試したものです。

    func sendRequest(url:String,params:NSDictionary){
       let urls: NSURL! = NSURL(string:url)
       var request = NSMutableURLRequest(URL:urls)
       request.HTTPMethod = "GET"
       var data:NSData! =  NSKeyedArchiver.archivedDataWithRootObject(params)
       request.HTTPBody = data
       println(request)
       var session = NSURLSession.sharedSession()
       var task = session.dataTaskWithRequest(request, completionHandler:loadedData)
       task.resume()

    }

}

func loadedData(data:NSData!,response:NSURLResponse!,err:NSError!){
    if(err != nil){
        println(err?.description)
    }else{
        var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
        println(jsonResult)

    }

}

どのように解決するのですか?

を構築する際に GET リクエストを構築する場合、リクエストのボディはなく、 すべてが URL になります。URL を構築するために (そして適切にパーセントエスケープするために) URLComponents .

var url = URLComponents(string: "https://www.google.com/search/")!

url.queryItems = [
    URLQueryItem(name: "q", value: "War & Peace")
]

唯一のトリックは、ほとんどのウェブサービスが + 文字がパーセントエスケープされていることです (これは application/x-www-form-urlencoded 仕様 ). しかし URLComponents はそれをパーセントエスケープしないでしょう。Apple は次のように主張しています。 + はクエリで有効な文字であり、したがってエスケープされるべきではないと主張しています。技術的には、URI のクエリで許可されていることは正しいのですが、この文字は application/x-www-form-urlencoded リクエストでは特別な意味を持ち、本当にエスケープされずに渡されるべきではありません。

をパーセントでエスケープする必要があることを Apple は認めています。 + 文字をパーセントでエスケープする必要があることを認めていますが、それを手動で行うように助言しています。

var url = URLComponents(string: "https://www.wolframalpha.com/input/")!

url.queryItems = [
    URLQueryItem(name: "i", value: "1+2")
]

url.percentEncodedQuery = url.percentEncodedQuery?.replacingOccurrences(of: "+", with: "%2B")

これは非効率的な回避策ですが、動作はしますし、クエリに + 文字が含まれ、それをスペースとして解釈するサーバーがある場合、Apple が推奨する方法です。

というわけで、これをあなたの sendRequest ルーチンと組み合わせると、次のようなものが出来上がります。

func sendRequest(_ url: String, parameters: [String: String], completion: @escaping ([String: Any]?, Error?) -> Void) {
    var components = URLComponents(string: url)!
    components.queryItems = parameters.map { (key, value) in 
        URLQueryItem(name: key, value: value) 
    }
    components.percentEncodedQuery = components.percentEncodedQuery?.replacingOccurrences(of: "+", with: "%2B")
    let request = URLRequest(url: components.url!)
    
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard
            let data = data,                              // is there data
            let response = response as? HTTPURLResponse,  // is there HTTP response
            200 ..< 300 ~= response.statusCode,           // is statusCode 2XX
            error == nil                                  // was there no error
        else {
            completion(nil, error)
            return
        }
        
        let responseObject = (try? JSONSerialization.jsonObject(with: data)) as? [String: Any]
        completion(responseObject, nil)
    }
    task.resume()
}

といった感じで呼び出すのでしょう。

sendRequest("someurl", parameters: ["foo": "bar"]) { responseObject, error in
    guard let responseObject = responseObject, error == nil else {
        print(error ?? "Unknown error")
        return
    }

    // use `responseObject` here
}

個人的には JSONDecoder を返すようになりました。 struct を返すようになりましたが、これはここではあまり関係ありません。これで、GETリクエストのURLにパラメータをパーセントエンコードする方法の基本的な考え方が示されたかと思います。


参照 この回答の前の改訂版 をご覧ください。