मापदंडों के साथ स्विफ्ट का अनुरोध प्राप्त करें


81

मैं स्विफ्ट के लिए बहुत नया हूं, इसलिए मेरे कोड में शायद बहुत सारे दोष होंगे लेकिन मैं जो हासिल करने की कोशिश कर रहा हूं, वह GETपरमहंस के साथ एक लोकलहोस्ट सर्वर को एक अनुरोध भेजना है । और इसलिए मैं इसे प्राप्त करने की कोशिश कर रहा हूं, यह देखते हुए कि मेरा फ़ंक्शन दो मापदंडों को लेता है baseURL:string,params:NSDictionary। मुझे यकीन नहीं है कि उन दोनों को वास्तविक 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)

    }

}

जवाबों:


160

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 का कहना है कि +एक क्वेरी में एक वैध चरित्र है और इसलिए इसे बच नहीं जाना चाहिए। तकनीकी रूप से, वे सही हैं, कि यह एक यूआरआई की क्वेरी में अनुमति है, लेकिन 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 else {                           // was there no error, otherwise ...
                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 में पैरामीटर को एन्कोड करने के मूल विचार को दिखाता है।


स्विफ्ट 2 और मैनुअल प्रतिशत बचने के लिए इस उत्तर के पिछले संशोधन को देखें ।


शानदार जवाब के लिए धन्यवाद। मेरा सिर्फ एक सवाल है, मैं अभी भी थोड़ा उलझन में हूं extension stringकि मूल्यों का क्या कर रहा हूं ? इसके बाद मुझे कब उपयोग करने की आवश्यकता होगी HttpBody?
MrSSS16

स्ट्रिंग विस्तार प्रतिशत RFC 3986 के मानों से बच रहा है। ऐसे कुछ वर्ण हैं जिनका URL में विशेष अर्थ है (उदाहरण के लिए &एक पैरामीटर को अगले से अलग करता है, इसलिए यदि &मान में होता है , तो आप इसे अनसैप्ड नहीं होने दे सकते)। अनुरोध के संबंध में HTTPBody, आपको इसका उपयोग नहीं करना चाहिए GET; इसमें इस्तेमाल किया जाता है POSTलेकिन नहीं GET
राब

यह इतना सरल दिखता है, इसके बजाय github.com/xyyc/SwiftSocket जैसी किसी चीज़ का उपयोग करने के क्या फायदे हैं ? मुझे खेद है कि मैं यह सब करने के लिए नया हूँ।
जिगज़त

यह सही तुलना नहीं हो सकती है, क्योंकि यह एक सॉकेट लाइब्रेरी है और यह HTTP है। क्लोज़र कुछ आलमोफायर जैसा है , लेकिन यह (ए) अधिक लचीला है ( जेएसएन अनुरोधों को संभाल सकता है, एक्स-www-फॉर्म-यूरेलेंकोडेड अनुरोध, मल्टीपार्ट, आदि); (बी) अधिक कार्यात्मक (जैसे प्रमाणीकरण चुनौतियों को संभालता है); और (c) आपको HTTP प्रोग्रामिंग के मातम से बाहर निकाल देता है। यदि कुछ भी हो, तो ऊपर दिए गए मेरे उत्तर का उद्देश्य सिर्फ अपने खुद के निर्माण के जोखिमों की एक सतर्क कहानी के रूप में है NSMutableURLRequest, यह इंगित करता है कि ओपी द्वारा सुझाए गए से अधिक है।
रॉब

यह एक सुंदर उपाय है। धन्यवाद @ रोब। Btw इस तरह मापदंडों की आपूर्ति में कोई अंतर है NSJSONSerialization.dataWithJSONObject(parameters, options: nil, error: nil)? parametersशब्दकोशों की एक सरणी होने के नाते[String: String]
Isuru

94

अपने NSURL का निर्माण करने के लिए NSURLCompords का उपयोग करें

var urlComponents = NSURLComponents(string: "https://www.google.de/maps/")!

urlComponents.queryItems = [
  NSURLQueryItem(name: "q", value: String(51.500833)+","+String(-0.141944)),
  NSURLQueryItem(name: "z", value: String(6))
]
urlComponents.URL // returns https://www.google.de/maps/?q=51.500833,-0.141944&z=6

फ़ॉन्ट: https://www.ralfebert.de/snippets/ios/encoding-nsurl-get-parameters/


5
रोब के प्रभावशाली जवाब के बावजूद, आपका काम आसान है और काम करता है।
Jan ATAC

3
यह स्वीकृत उत्तर होना चाहिए। URL का निर्माण करने के लिए क्वेरी आइटम के साथ NSURLCompords का उपयोग करने की अनुशंसा की जाती है। ज्यादा सुरक्षित और कम त्रुटि का खतरा।
जॉन रोजर्स

5

मैं इसका उपयोग कर रहा हूं, इसे खेल के मैदान में आजमाएं। कॉन्स्टेंट में स्ट्रक्चर के रूप में बेस यूरल्स को परिभाषित करें

struct Constants {

    struct APIDetails {
        static let APIScheme = "https"
        static let APIHost = "restcountries.eu"
        static let APIPath = "/rest/v1/alpha/"
    }
}

private func createURLFromParameters(parameters: [String:Any], pathparam: String?) -> URL {

    var components = URLComponents()
    components.scheme = Constants.APIDetails.APIScheme
    components.host   = Constants.APIDetails.APIHost
    components.path   = Constants.APIDetails.APIPath
    if let paramPath = pathparam {
        components.path = Constants.APIDetails.APIPath + "\(paramPath)"
    }
    if !parameters.isEmpty {
        components.queryItems = [URLQueryItem]()
        for (key, value) in parameters {
            let queryItem = URLQueryItem(name: key, value: "\(value)")
            components.queryItems!.append(queryItem)
        }
    }

    return components.url!
}

let url = createURLFromParameters(parameters: ["fullText" : "true"], pathparam: "IN")

//Result url= https://restcountries.eu/rest/v1/alpha/IN?fullText=true

1

स्विफ्ट 3 :

extension URL {
    func getQueryItemValueForKey(key: String) -> String? {
        guard let components = NSURLComponents(url: self, resolvingAgainstBaseURL: false) else {
              return nil
        }

        guard let queryItems = components.queryItems else { return nil }
     return queryItems.filter {
                 $0.name.lowercased() == key.lowercased()
                 }.first?.value
    }
}

मैंने इसका उपयोग इसके लिए छवि नाम प्राप्त करने के लिए UIImagePickerControllerकिया func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]):

var originalFilename = ""
if let url = info[UIImagePickerControllerReferenceURL] as? URL, let imageIdentifier = url.getQueryItemValueForKey(key: "id") {
    originalFilename = imageIdentifier + ".png"
    print("file name : \(originalFilename)")
}

आपकी प्रतिक्रिया ओपी के सवाल का जवाब नहीं देती है
इलियास करीम

0

यदि आपकी कुंजी और मान दोनों इस तरह के अनुरूप Dictionaryहैं, stringFromHttpParameterतो आप केवल अपना विस्तार कर सकते हैंCustomStringConvertable

extension Dictionary where Key : CustomStringConvertible, Value : CustomStringConvertible {
  func stringFromHttpParameters() -> String {
    var parametersString = ""
    for (key, value) in self {
      parametersString += key.description + "=" + value.description + "&"
    }
    return parametersString
  }
}

यह बहुत साफ-सुथरा है और stringFromHttpParametersउन शब्दकोशों पर आकस्मिक कॉल को रोकता है जिनका कोई व्यवसाय नहीं है


-1

यह विस्तार कि @Rob ने स्विफ्ट 3.0.1 के लिए काम करने का सुझाव दिया है

मैं Xcode 8.1 (8B62) के साथ अपने पोस्ट में शामिल संस्करण को संकलित करने में सक्षम नहीं था

extension Dictionary {

    /// Build string representation of HTTP parameter dictionary of keys and objects
    ///
    /// :returns: String representation in the form of key1=value1&key2=value2 where the keys and values are percent escaped

    func stringFromHttpParameters() -> String {

        var parametersString = ""
        for (key, value) in self {
            if let key = key as? String,
               let value = value as? String {
                parametersString = parametersString + key + "=" + value + "&"
            }
        }
        parametersString = parametersString.substring(to: parametersString.index(before: parametersString.endIndex))
        return parametersString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!
    }

}

-3

मैं उपयोग करता हूं:

let dictionary = ["method":"login_user",
                  "cel":mobile.text!
                  "password":password.text!] as  Dictionary<String,String>

for (key, value) in dictionary {
    data=data+"&"+key+"="+value
    }

request.HTTPBody = data.dataUsingEncoding(NSUTF8StringEncoding);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.