在Swift中的WebService中传递参数

Ann*_*nnu 2 ios swift

我正在学习Swift,我不知道如何使用Swift将参数发送到服务器.在Objective-C中,我们可以使用"%@"占位符来完成此操作.但是对于Swift应该怎么做,假设我有一个需要电子邮件和密码的登录web服务.

现在我想知道的是,我将如何发送logintextfieldpasswordtextfield文本到服务器,例如,

var bodyData = "email=logintextfield.text&password=passwordtextfield.text"
Run Code Online (Sandbox Code Playgroud)

Rob*_*Rob 10

在创建包含用户输入的HTTP请求时,如果用户的输入中有任何保留字符,通常应该百分之一,以便:

let login    = logintextfield.text?.addingPercentEncodingForURLQueryValue() ?? ""
let password = passwordtextfield.text?.addingPercentEncodingForURLQueryValue() ?? ""
let bodyData = "email=\(login)&password=\(password)"
Run Code Online (Sandbox Code Playgroud)

请注意,你真的要检查,看是否loginpasswordnil或不是.无论如何,逃逸百分比如下:

extension String {

    /// Percent escapes values to be added to a URL query as specified in RFC 3986
    ///
    /// This percent-escapes all characters besides the alphanumeric character set and "-", ".", "_", and "~".
    ///
    /// http://www.ietf.org/rfc/rfc3986.txt
    ///
    /// :returns: Returns percent-escaped string.

    func addingPercentEncodingForURLQueryValue() -> String? {
        let allowedCharacters = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~")

        return self.addingPercentEncoding(withAllowedCharacters: allowedCharacters)
    }

}
Run Code Online (Sandbox Code Playgroud)

请参阅此答案,了解此扩展的另一个演绎.


如果您想看到上述使用的演示,请想象以下请求:

let keyData = "AIzaSyCRLa4LQZWNQBcjCYcIVYA45i9i8zfClqc"
let sensorInformation = false
let types = "building"
let radius = 1000000
let locationCoordinate = CLLocationCoordinate2D(latitude:40.748716, longitude: -73.985643)
let name = "Empire State Building, New York, NY"
let floors = 102
let now = Date()

let params:[String: Any] = [
    "key" : keyData,
    "sensor" : sensorInformation,
    "typesData" : types,
    "radius" : radius,
    "location" : locationCoordinate,
    "name" : name,
    "floors" : floors,
    "when" : now,
    "pi" : M_PI]

let url = URL(string: "http://some.web.site.com/inquiry")!
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpBody = params.dataFromHttpParameters()

let task = URLSession.shared.dataTask(with: request) { data, response, error in
    guard data != nil && error == nil else {
        print("error submitting request: \(error)")
        return
    }

    if let httpResponse = response as? HTTPURLResponse where httpResponse.statusCode != 200 {
        print("response was not 200: \(response)")
        return
    }

    // handle the data of the successful response here
}
task.resume()
Run Code Online (Sandbox Code Playgroud)

我包含了许多未包含在您的示例中的参数,但仅仅是为了说明例程对各种参数类型的处理.

顺便说一句,以上使用我的datafromHttpParameters功能:

extension Dictionary {

    /// This creates a String representation of the supplied value.
    ///
    /// This converts NSDate objects to a RFC3339 formatted string, booleans to "true" or "false",
    /// and otherwise returns the default string representation.
    ///
    /// - parameter value: The value to be converted to a string
    ///
    /// - returns:         String representation

    private func httpStringRepresentation(_ value: Any) -> String {
        switch value {
        case let date as Date:
            return date.rfc3339String()
        case let coordinate as CLLocationCoordinate2D:
            return "\(coordinate.latitude),\(coordinate.longitude)"
        case let boolean as Bool:
            return boolean ? "true" : "false"
        default:
            return "\(value)"
        }
    }

    /// Build `Data` representation of HTTP parameter dictionary of keys and objects
    ///
    /// This percent escapes in compliance with RFC 3986
    ///
    /// http://www.ietf.org/rfc/rfc3986.txt
    ///
    /// :returns: String representation in the form of key1=value1&key2=value2 where the keys and values are percent escaped

    func dataFromHttpParameters() -> Data {
        let parameterArray = self.map { (key, value) -> String in
            let percentEscapedKey = (key as! String).addingPercentEncodingForURLQueryValue()!
            let percentEscapedValue = httpStringRepresentation(value).addingPercentEncodingForURLQueryValue()!
            return "\(percentEscapedKey)=\(percentEscapedValue)"
        }

        return parameterArray.joined(separator: "&").data(using: .utf8)!
    }

}
Run Code Online (Sandbox Code Playgroud)

在这里,因为我正在处理一个参数字符串数组,我使用该join函数来连接它们&,但想法相同.

随意定制该函数来处理您可能传递给它的任何数据类型(例如,我通常不会CLLocationCoordinate2D在那里,但您的示例包括一个,所以我想展示它可能是什么样子).但关键是,如果您提供包含用户输入的任何字段,请确保以百分比形式转义它.

仅供参考,这是我rfc3339String上面使用的功能.(显然,如果你不需要传输日期,你不需要这个,但是为了更完整的解决方案,我将它包括在内.)

extension Date {

    /// Get RFC 3339/ISO 8601 string representation of the date.
    ///
    /// For more information, see:
    ///
    /// https://developer.apple.com/library/ios/qa/qa1480/_index.html
    ///
    /// - returns: Return RFC 3339 representation of date string

    func rfc3339String() -> String {
        let formatter = DateFormatter()

        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSX"
        formatter.timeZone = TimeZone(secondsFromGMT: 0)
        formatter.locale = Locale(identifier: "en_US_POSIX")

        return formatter.string(from: self)
    }
}
Run Code Online (Sandbox Code Playgroud)

要查看Swift 2的演绎,请参阅此答案的上一个演绎.