我在iBooks中阅读了Apple的The Programming Language Swift,但无法弄清楚如何在Swift中发出HTTP请求(例如cURL)。我需要导入Obj-C类还是只需要导入默认库?还是无法基于本机Swift代码发出HTTP请求?

评论

使用URLSession(GET,POST,DELETE方法):stackoverflow.com/a/48306950/6898523

#1 楼

您可以像在Objective-C中通常使用的那样使用URLURLRequestURLSessionNSURLConnection。请注意,对于iOS 7.0和更高版本,首选URLSession
使用URLSession

URL初始化URLSessionDataTask对象和URLSession。然后使用resume()运行任务。
let url = URL(string: "http://www.stackoverflow.com")!

let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
    guard let data = data else { return }
    print(String(data: data, encoding: .utf8)!)
}

task.resume()

使用NSURLConnection

首先,初始化URLURLRequest
let url = URL(string: "http://www.stackoverflow.com")!
var request = URLRequest(url: url)
request.httpMethod = "POST" 

然后,您可以加载异步请求:
NSURLConnection.sendAsynchronousRequest(request, queue: OperationQueue.main) {(response, data, error) in
    guard let data = data else { return }
    print(String(data: data, encoding: .utf8)!)
}

,或者您可以初始化NSURLConnection
let connection = NSURLConnection(request: request, delegate:nil, startImmediately: true)

只需确保将委托设置为nil以外的其他值,并使用委托方法与响应和收到的数据。
有关详细信息,请查看NSURLConnectionDataDelegate协议的文档
在Xcode操场上进行测试
如果要在Xcode操场上尝试此代码,请将import PlaygroundSupport添加到操场上,以及以下调用:
PlaygroundPage.current.needsIndefiniteExecution = true

这将允许您在操场上使用异步代码。

评论


不要在操场上的iOS 8 beta 2上浪费时间,因为不支持XCPlayground。如果您想尝试黑客,有一种聪明而丑陋的方法可以等待:stackoverflow.com/a/24058337/700206

–惠特尼乐园
2014年7月1日在13:48



如何使用NSURLSession发送POST数据?

–费尔南多·圣地亚哥
2014年9月21日19:23在

此示例在6.1失败:test.swift:5:57:错误:可选类型'NSURL?'的值没有包装;你是说用'!'要么 '?'? let task = NSURLSession.sharedSession()。dataTaskWithURL(url){{data,response,error)in

– mcuadros
2014年10月12日12:04



添加感叹号可修复@mcuadros的错误消息... .dataTaskWithURL(url!)

– Sean McClory
14-10-30在15:04

您能修复代码片段吗?这是从Swift 4 print开始工作的内容(String(data:data !, encoding:String.Encoding.utf8))

–内特
17年7月2日在9:27



#2 楼

检查以下代码:

1。 SynchonousRequest

Swift 1.2

    let urlPath: String = "YOUR_URL_HERE"
    var url: NSURL = NSURL(string: urlPath)!
    var request1: NSURLRequest = NSURLRequest(URL: url)
    var response: AutoreleasingUnsafeMutablePointer<NSURLResponse?>=nil
    var dataVal: NSData =  NSURLConnection.sendSynchronousRequest(request1, returningResponse: response, error:nil)!
    var err: NSError
    println(response)
    var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataVal, options: NSJSONReadingOptions.MutableContainers, error: &err) as? NSDictionary
    println("Synchronous\(jsonResult)")


Swift 2.0 +

let urlPath: String = "YOUR_URL_HERE"
    let url: NSURL = NSURL(string: urlPath)!
    let request1: NSURLRequest = NSURLRequest(URL: url)
    let response: AutoreleasingUnsafeMutablePointer<NSURLResponse?>=nil


    do{

        let dataVal = try NSURLConnection.sendSynchronousRequest(request1, returningResponse: response)

            print(response)
            do {
                if let jsonResult = try NSJSONSerialization.JSONObjectWithData(dataVal, options: []) as? NSDictionary {
                    print("Synchronous\(jsonResult)")
                }
            } catch let error as NSError {
                print(error.localizedDescription)
            }



    }catch let error as NSError
    {
         print(error.localizedDescription)
    }


2。 AsynchonousRequest

Swift 1.2

let urlPath: String = "YOUR_URL_HERE"
    var url: NSURL = NSURL(string: urlPath)!
    var request1: NSURLRequest = NSURLRequest(URL: url)
    let queue:NSOperationQueue = NSOperationQueue()
    NSURLConnection.sendAsynchronousRequest(request1, queue: queue, completionHandler:{ (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
        var err: NSError
        var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
        println("Asynchronous\(jsonResult)")
       })


Swift 2.0 +

let urlPath: String = "YOUR_URL_HERE"
    let url: NSURL = NSURL(string: urlPath)!
    let request1: NSURLRequest = NSURLRequest(URL: url)
    let queue:NSOperationQueue = NSOperationQueue()

    NSURLConnection.sendAsynchronousRequest(request1, queue: queue, completionHandler:{ (response: NSURLResponse?, data: NSData?, error: NSError?) -> Void in

        do {
            if let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? NSDictionary {
                print("ASynchronous\(jsonResult)")
            }
        } catch let error as NSError {
            print(error.localizedDescription)
        }


    })


3。和往常一样URL连接

Swift 1.2 2.0 +

    var dataVal = NSMutableData()
    let urlPath: String = "YOUR URL HERE"
    var url: NSURL = NSURL(string: urlPath)!
    var request: NSURLRequest = NSURLRequest(URL: url)
    var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: true)!
    connection.start()


然后

 func connection(connection: NSURLConnection!, didReceiveData data: NSData!){
    self.dataVal?.appendData(data)
}


func connectionDidFinishLoading(connection: NSURLConnection!)
{
    var error: NSErrorPointer=nil

    var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataVal!, options: NSJSONReadingOptions.MutableContainers, error: error) as NSDictionary

    println(jsonResult)



}


4。异步POST请求

Swift 1.2

   var dataVal = NSMutableData()
    let urlPath: String = "YOUR URL HERE"
    var url: NSURL = NSURL(string: urlPath)!
    var request: NSURLRequest = NSURLRequest(URL: url)
    var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: true)!
    connection.start()


Swift 2.0 +

func connection(connection: NSURLConnection!, didReceiveData data: NSData!){
    dataVal.appendData(data)
}


func connectionDidFinishLoading(connection: NSURLConnection!)
{

    do {
        if let jsonResult = try NSJSONSerialization.JSONObjectWithData(dataVal, options: []) as? NSDictionary {
            print(jsonResult)
        }
    } catch let error as NSError {
        print(error.localizedDescription)
    }

}


5,异步GET请求

Swift 1.2

    let urlPath: String = "YOUR URL HERE"
    var url: NSURL = NSURL(string: urlPath)!
    var request1: NSMutableURLRequest = NSMutableURLRequest(URL: url)

    request1.HTTPMethod = "POST"
     var stringPost="deviceToken=123456" // Key and Value

    let data = stringPost.dataUsingEncoding(NSUTF8StringEncoding)

    request1.timeoutInterval = 60
    request1.HTTPBody=data
    request1.HTTPShouldHandleCookies=false

    let queue:NSOperationQueue = NSOperationQueue()

     NSURLConnection.sendAsynchronousRequest(request1, queue: queue, completionHandler:{ (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in


        var err: NSError

        var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
        println("AsSynchronous\(jsonResult)")


        })


Swift 2.0 +

let urlPath: String = "YOUR URL HERE"
    let url: NSURL = NSURL(string: urlPath)!
    let request1: NSMutableURLRequest = NSMutableURLRequest(URL: url)

    request1.HTTPMethod = "POST"
    let stringPost="deviceToken=123456" // Key and Value

    let data = stringPost.dataUsingEncoding(NSUTF8StringEncoding)

    request1.timeoutInterval = 60
    request1.HTTPBody=data
    request1.HTTPShouldHandleCookies=false

    let queue:NSOperationQueue = NSOperationQueue()

    NSURLConnection.sendAsynchronousRequest(request1, queue: queue, completionHandler:{ (response: NSURLResponse?, data: NSData?, error: NSError?) -> Void in

        do {
            if let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? NSDictionary {
                print("ASynchronous\(jsonResult)")
            }
        } catch let error as NSError {
            print(error.localizedDescription)
        }


    })


6。图片(文件)上传

Swift 2.0 +

    let urlPath: String = "YOUR URL HERE"
    var url: NSURL = NSURL(string: urlPath)!
    var request1: NSMutableURLRequest = NSMutableURLRequest(URL: url)

    request1.HTTPMethod = "GET"
    request1.timeoutInterval = 60
    let queue:NSOperationQueue = NSOperationQueue()

     NSURLConnection.sendAsynchronousRequest(request1, queue: queue, completionHandler:{ (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in


        var err: NSError

        var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
        println("AsSynchronous\(jsonResult)")


        })


#3 楼

另一个选项是Alamofire库,它提供可链接的请求/响应方法。

https://github.com/Alamofire/Alamofire

发出请求

import Alamofire

Alamofire.request(.GET, "http://httpbin.org/get")


响应处理

Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
         .response { request, response, data, error in
              print(request)
              print(response)
              print(error)
          }


评论


我认为,尽管建议由外部lib提供答复,而框架提供的功能却不是正确的方法。

– turkishweb
16年2月2日,13:25

@turkishweb是正确的。 Cezar的答案更加完整,并且不使用外部库。那应该是公认的答案。

– fredmaggiowski
16年2月2日在13:28

Cezar的答案已经过时了(自Swift 3起),Alamofire的界面比URLSession和consorts的界面好很多。同样,接受并不是衡量某种善良程度的抽象标准(更不用说您了!!)),而是对OP的最大帮助。 (对于“纯”解决方案,有SO文档!)如果这是答案,那就完美了-它不是在使用第一手原则,但是那并不总是“正确”的解决方案,不是吗?

–拉斐尔
17 Mar 24 '17在45



除非特别要求,否则请不要提供第三方库(根据SO指南)

– Alec O
17年11月17日在3:23

@AlecO能否请我指出这些指南的内容?

–拉斐尔
19年3月19日在7:10

#4 楼

Swift 4及以上版本:使用URLSession API的数据请求

   //create the url with NSURL
   let url = URL(string: "https://jsonplaceholder.typicode.com/todos/1")! //change the url

   //create the session object
   let session = URLSession.shared

   //now create the URLRequest object using the url object
   let request = URLRequest(url: url)

   //create dataTask using the session object to send data to the server
   let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in

       guard error == nil else {
           return
       }

       guard let data = data else {
           return
       }

      do {
         //create json object from data
         if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
            print(json)
         }
      } catch let error {
        print(error.localizedDescription)
      }
   })

   task.resume()


Swift 4及以上版本,可解码和结果枚举

//APPError enum which shows all possible errors
enum APPError: Error {
    case networkError(Error)
    case dataNotFound
    case jsonParsingError(Error)
    case invalidStatusCode(Int)
}

//Result enum to show success or failure
enum Result<T> {
    case success(T)
    case failure(APPError)
}

//dataRequest which sends request to given URL and convert to Decodable Object
func dataRequest<T: Decodable>(with url: String, objectType: T.Type, completion: @escaping (Result<T>) -> Void) {

    //create the url with NSURL
    let dataURL = URL(string: url)! //change the url

    //create the session object
    let session = URLSession.shared

    //now create the URLRequest object using the url object
    let request = URLRequest(url: dataURL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 60)

    //create dataTask using the session object to send data to the server
    let task = session.dataTask(with: request, completionHandler: { data, response, error in

        guard error == nil else {
            completion(Result.failure(AppError.networkError(error!)))
            return
        }

        guard let data = data else {
            completion(Result.failure(APPError.dataNotFound))
            return
        }

        do {
            //create decodable object from data
            let decodedObject = try JSONDecoder().decode(objectType.self, from: data)
            completion(Result.success(decodedObject))
        } catch let error {
            completion(Result.failure(APPError.jsonParsingError(error as! DecodingError)))
        }
    })

    task.resume()
}


示例:

///如果我们想从占位符API获取待办事项,那么我们定义ToDo结构并调用dataRequest并传递“ https://jsonplaceholder.typicode.com/todos/1 “字符串url。

struct ToDo: Decodable {
    let id: Int
    let userId: Int
    let title: String
    let completed: Bool

}

dataRequest(with: "https://jsonplaceholder.typicode.com/todos/1", objectType: ToDo.self) { (result: Result) in
    switch result {
    case .success(let object):
        print(object)
    case .failure(let error):
        print(error)
    }
}


//这将打印结果:

ToDo(id: 1, userId: 1, title: "delectus aut autem", completed: false)


评论


如何调整它以接受对象数组?

–kirqe
10月8日,19:15



@kirqe如果您想接受数组作为响应,则传递`objectType:[T] .self``,这里T确认为可解码协议

– Suhit Patil
10月8日,19:54



#5 楼

Swift 3+基本解决方案

guard let url = URL(string: "http://www.stackoverflow.com") else { return }

let task = URLSession.shared.dataTask(with: url) { data, response, error in

  guard let data = data, error == nil else { return }

  print(NSString(data: data, encoding: String.Encoding.utf8.rawValue))
}

task.resume()


评论


您的示例适用于Swift 3,因此应使用URL(string:“ http://www.stackoverflow.com”)而不是NSURL

– FelixSFD
16年8月23日在11:29

从URL转换为URL没有意义URLSession.shared.dataTask(with:url!)

– Leo Dabus
16年2月2日在16:51

我收到此错误:应用传输安全性由于不安全,阻止了明文HTTP(http://)资源加载。可以通过应用程序的Info.plist文件配置临时异常。

–user285594
17年2月9日在17:26

@YumYumYum您是否已根据此文章stackoverflow.com/questions/30731785/…配置了应用程序传输安全性?

–本·沙利文(Ben Sullivan)
17-2-10在17:36



Leo Dabus变量url是URL类型吗?

–汤姆·舒尔茨(Tom Schulz)
18年4月16日在20:29

#6 楼

Swift 3.0
通过一个小的抽象
https://github.com/daltoniam/swiftHTTP
示例
    do {
        let opt = try HTTP.GET("https://google.com")
        opt.start { response in
            if let err = response.error {
                print("error: \(err.localizedDescription)")
                return //also notify app of failure as needed
            }
            print("opt finished: \(response.description)")
            //print("data is: \(response.data)") access the response of the data with response.data
        }
    } catch let error {
        print("got an error creating the request: \(error)")
    }


评论


您是否找到一种在显示视图之前等待请求完成的方法? @AlexanderN

–重塑
15年3月18日在21:56

#7 楼

详细信息


Xcode 9.2,Swift 4
Xcode 10.2.1(10E1001),Swift 5

Info.plist


NSAppTransportSecurity

添加到信息列表:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>



Alamofire示例

Alamofire

import Alamofire

class AlamofireDataManager {
    fileprivate let queue: DispatchQueue
    init(queue: DispatchQueue) { self.queue = queue }

    private func createError(message: String, code: Int) -> Error {
        return NSError(domain: "dataManager", code: code, userInfo: ["message": message ])
    }

    private func make(session: URLSession = URLSession.shared, request: URLRequest, closure: ((Result<[String: Any]>) -> Void)?) {
        Alamofire.request(request).responseJSON { response in
            let complete: (Result<[String: Any]>) ->() = { result in DispatchQueue.main.async { closure?(result) } }
            switch response.result {
                case .success(let value): complete(.success(value as! [String: Any]))
                case .failure(let error): complete(.failure(error))
            }
        }
    }

    func searchRequest(term: String, closure: ((Result<[String: Any]>) -> Void)?) {
        guard let url = URL(string: "https://itunes.apple.com/search?term=\(term.replacingOccurrences(of: " ", with: "+"))") else { return }
        let request = URLRequest(url: url)
        make(request: request) { response in closure?(response) }
    }
}


Alamofire示例的使用

private lazy var alamofireDataManager = AlamofireDataManager(queue: DispatchQueue(label: "DataManager.queue", qos: .utility))
//.........

alamofireDataManager.searchRequest(term: "jack johnson") { result in
      print(result.value ?? "no data")
      print(result.error ?? "no error")
}



URLSession示例

import Foundation

class DataManager {

    fileprivate let queue: DispatchQueue
        init(queue: DispatchQueue) { self.queue = queue }

    private func createError(message: String, code: Int) -> Error {
        return NSError(domain: "dataManager", code: code, userInfo: ["message": message ])
    }

    private func make(session: URLSession = URLSession.shared, request: URLRequest, closure: ((_ json: [String: Any]?, _ error: Error?)->Void)?) {
        let task = session.dataTask(with: request) { [weak self] data, response, error in
            self?.queue.async {
                let complete: (_ json: [String: Any]?, _ error: Error?) ->() = { json, error in DispatchQueue.main.async { closure?(json, error) } }

                guard let self = self, error == nil else { complete(nil, error); return }
                guard let data = data else { complete(nil, self.createError(message: "No data", code: 999)); return }

                do {
                    if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
                        complete(json, nil)
                    }
                } catch let error { complete(nil, error); return }
            }
        }

        task.resume()
    }

    func searchRequest(term: String, closure: ((_ json: [String: Any]?, _ error: Error?)->Void)?) {
        let url = URL(string: "https://itunes.apple.com/search?term=\(term.replacingOccurrences(of: " ", with: "+"))")
        let request = URLRequest(url: url!)
        make(request: request) { json, error in closure?(json, error) }
    }
}


URLSession示例的使用

private lazy var dataManager = DataManager(queue: DispatchQueue(label: "DataManager.queue", qos: .utility))
// .......
dataManager.searchRequest(term: "jack johnson") { json, error  in
      print(error ?? "nil")
      print(json ?? "nil")
      print("Update views")
}


结果



评论


searchRequest?术语?他们来自哪里?

– El Tomato
18年1月22日在3:28

这是请求的完整样本。 class func searchRequest(term:String,...是从itunes.apple.com下载数据的示例。此示例将进行搜索,因此,我选择/发明了searchRequest函数名称。term是“ itunes.apple.com/搜索?”。您可以选择函数的任何名称来描述您的逻辑模型。

–瓦西里·博德纳丘克(Vasily Bodnarchuk)
18年1月22日在8:45

不错的解决方案。我已经更改了闭包以返回包含成功和错误案例的枚举。

–霓虹灯
18年4月11日在8:29

#8 楼

我已经完成了HTTP请求两种方法JSON的GET和POST解析,方法如下:

on viewDidLoad():

override func viewDidLoad() {
super.viewDidLoad()

    makeGetRequest()
    makePostRequest()

}

func makePostRequest(){

    let urlPath: String = "http://www.swiftdeveloperblog.com/http-post-example-script/"
    var url: NSURL = NSURL(string: urlPath)!
    var request: NSMutableURLRequest = NSMutableURLRequest(URL: url)

    request.HTTPMethod = "POST"
    var stringPost="firstName=James&lastName=Bond" // Key and Value

    let data = stringPost.dataUsingEncoding(NSUTF8StringEncoding)

    request.timeoutInterval = 60
    request.HTTPBody=data
    request.HTTPShouldHandleCookies=false

    let queue:NSOperationQueue = NSOperationQueue()

    NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler:{ (response:NSURLResponse!, data: NSData!, error: NSError!) -> Void in
        var error: AutoreleasingUnsafeMutablePointer<NSError?> = nil
        let jsonResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers, error: error) as? NSDictionary

         if (jsonResult != nil) {
            // Success
           println(jsonResult)

           let message = jsonResult["Message"] as! NSString

           println(message)
         }else {
            // Failed
            println("Failed")
        }

    })

}

func makeGetRequest(){
    var url : String = "http://api.androidhive.info/contacts/"
    var request : NSMutableURLRequest = NSMutableURLRequest()
    request.URL = NSURL(string: url)
    request.HTTPMethod = "GET"
    request.timeoutInterval = 60

    NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler:{ (response:NSURLResponse!, data: NSData!, error: NSError!) -> Void in
        var error: AutoreleasingUnsafeMutablePointer<NSError?> = nil
        let jsonResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers, error: error) as? NSDictionary

        if (jsonResult != nil) {
            // Success
            println(jsonResult)

            let dataArray = jsonResult["contacts"] as! NSArray;

            for item in dataArray { // loop through data items

                let obj = item as! NSDictionary

                for (key, value) in obj {

                    println("Key: \(key) - Value: \(value)")

                    let phone = obj["phone"] as! NSDictionary;

                    let mobile = phone["mobile"] as! NSString
                    println(mobile)
                    let home = phone["home"] as! NSString
                    println(home)
                    let office = phone["office"] as! NSString
                    println(office)
                }
            }

        } else {
            // Failed
            println("Failed")
        }

    })
}


完成

评论


无法使用类型为'(NSMutableURLRequest,queue:NSOperationQueue,completeHandler:(NSURLResponse !, NSData !, NSError!)-> Void)'的参数列表调用'sendAsynchronousRequest'

– bMalum
15年8月17日在9:27

#9 楼

使用URLSession + Swift 5
只需添加到cezar的答案中,如果您想使用Apple的URLSession类发出Web请求,则可以通过多种方式执行任务

使用URL的简单GET请求
带URL和参数的简单GET请求
带错误处理的URL的简单GET请求
带URL和错误处理的参数的简单POST请求



1。带有URL的简单GET请求
func simpleGetUrlRequest()
    {
        let url = URL(string: "https://httpbin.org/get")!

        let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
            guard let data = data else { return }
            print("The response is : ",String(data: data, encoding: .utf8)!)
            //print(NSString(data: data, encoding: String.Encoding.utf8.rawValue) as Any)
        }
        task.resume()
    }


注意:确保必须在pList中为http请求添加“ NSAppTransportSecurity”键

<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>


2。具有URL和参数的简单GET请求。
func simpleGetUrlWithParamRequest()
    {
        let url = URL(string: "https://www.google.com/search?q=peace")!
        
        let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
            
            if error != nil || data == nil {
                print("Client error!")
                return
            }
            guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
                print("Server error!")
                return
            }
            print("The Response is : ",response)
        }
        task.resume()
    }


3。具有URL并带有错误处理的简单GET请求。
func simpleGetUrlRequestWithErrorHandling()
    {
        let session = URLSession.shared
        let url = URL(string: "https://httpbin.org/get")!
        
        let task = session.dataTask(with: url) { data, response, error in
            
            if error != nil || data == nil {
                print("Client error!")
                return
            }
            
            guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
                print("Server error!")
                return
            }
            
            guard let mime = response.mimeType, mime == "application/json" else {
                print("Wrong MIME type!")
                return
            }
            
            do {
                let json = try JSONSerialization.jsonObject(with: data!, options: [])
                print("The Response is : ",json)
            } catch {
                print("JSON error: \(error.localizedDescription)")
            }
            
        }
        task.resume()
    }


4。带有URL的简单POST请求,带有错误处理的参数。
func simplePostRequestWithParamsAndErrorHandling(){
        let configuration = URLSessionConfiguration.default
        configuration.timeoutIntervalForRequest = 30
        configuration.timeoutIntervalForResource = 30
        let session = URLSession(configuration: configuration)
        
        let url = URL(string: "https://httpbin.org/post")!
        
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")
        
        let parameters = ["username": "foo", "password": "123456"]
        
        do {
            request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
        } catch let error {
            print(error.localizedDescription)
        }
        
        let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
            
            if error != nil || data == nil {
                print("Client error!")
                return
            }
            
            guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
                print("Oops!! there is server error!")
                return
            }
            
            guard let mime = response.mimeType, mime == "application/json" else {
                print("response is not json")
                return
            }
            
            do {
                let json = try JSONSerialization.jsonObject(with: data!, options: [])
                print("The Response is : ",json)
            } catch {
                print("JSON error: \(error.localizedDescription)")
            }
            
        })
        
        task.resume()
    }

您的建议受到赞赏!

评论


为什么不使用var session = URLSession.shared而不使用它,而只覆盖变量?需要吗?

–vrwim
19年8月7日在13:17

#10 楼


我在登录按钮click上调用json。


@IBAction func loginClicked(sender : AnyObject) {

    var request = NSMutableURLRequest(URL: NSURL(string: kLoginURL)) // Here, kLogin contains the Login API.

    var session = NSURLSession.sharedSession()

    request.HTTPMethod = "POST"

    var err: NSError?
    request.HTTPBody = NSJSONSerialization.dataWithJSONObject(self.criteriaDic(), options: nil, error: &err) // This Line fills the web service with required parameters.
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue("application/json", forHTTPHeaderField: "Accept")

    var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
        var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
        var err1: NSError?
        var json2 = NSJSONSerialization.JSONObjectWithData(strData.dataUsingEncoding(NSUTF8StringEncoding), options: .MutableLeaves, error:&err1 ) as NSDictionary

        println("json2 :\(json2)")

        if(err) {
            println(err!.localizedDescription)
        }
        else {
            var success = json2["success"] as? Int
            println("Success: \(success)")
        }
    })

    task.resume()
}


这里,我为参数制作了单独的字典。

var params = ["format":"json", "MobileType":"IOS","MIN":"f8d16d98ad12acdbbe1de647414495ec","UserName":emailTxtField.text,"PWD":passwordTxtField.text,"SigninVia":"SH"]as NSDictionary
    return params
}

// You can add your own sets of parameter here.


#11 楼

您可以使用python-requests样式的HTTP库Just。

使用Just发送HTTP请求的一些示例:

// synchronous GET request with URL query a=1
let r = Just.get("https://httpbin.org/get", params:["a":1])

// asynchronous POST request with form value and file uploads
Just.post(
    "http://justiceleauge.org/member/register",
    data: ["username": "barryallen", "password":"ReverseF1ashSucks"],
    files: ["profile_photo": .URL(fileURLWithPath:"flash.jpeg", nil)]
) { (r)
    if (r.ok) { /* success! */ }
}


请求结果r的访问方式类似于python-request

r.ok            // is the response successful?
r.statusCode    // status code of response
r.content       // response body as NSData?
r.text          // response body as text?
r.json          // response body parsed by NSJSONSerielization


您可以在此游乐场找到更多示例

使用该库在操场上以同步模式运行是最接近cURL的东西,可以在Swift中获得。

评论


尽管此链接可以回答问题,但最好在此处包括答案的基本部分,并提供链接以供参考。如果链接的页面发生更改,仅链接的答案可能会失效。

– dimo414
15年5月13日在21:51

似乎已弃用该库。没有Swift 4支持,也没有人响应未解决的问题。

– Heinrisch
18/09/19在17:21

#12 楼

在Swift 4.1和Xcode 9.4.1中。

JSON POST方法示例。要检查Internet连接,请从https://developer.apple.com/library/archive/samplecode/Reachability/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007324-Intro-DontLinkElementID_2添加Reachability.h和.m文件

func yourFunctionName {
    //Check internet connection
    let networkReachability = Reachability.forInternetConnection()
    let networkStatus:Int = (networkReachability?.currentReachabilityStatus())!.rawValue
    print(networkStatus)
    if networkStatus == NotReachable.rawValue {
        let msg = SharedClass.sharedInstance.noNetMsg//Message
        //Call alert from shared class
        SharedClass.sharedInstance.alert(view: self, title: "", message: msg)
    } else {
        //Call spinner from shared class
        SharedClass.sharedInstance.activityIndicator(view: self.view)//Play spinner

        let parameters = "Your parameters here"
        var request = URLRequest(url: URL(string: url)!)

        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"

        print("URL : \(request)")

        request.httpBody = parameters.data(using: .utf8)

        let task = URLSession.shared.dataTask(with: request) { data, response, error in guard let data = data, error == nil else { // check for fundamental networking error
            //Stop spinner
            SharedClass.sharedInstance.stopActivityIndicator() //Stop spinner
            //Print error in alert
            SharedClass.sharedInstance.alert(view: self, title: "", message: "\(String(describing: error!.localizedDescription))")
            return
            }

            SharedClass.sharedInstance.stopActivityIndicator() //Stop spinner

            if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
                print("statusCode should be 200, but is \(httpStatus.statusCode)")
                print("response = \(String(describing: response))")
            }

            do {
                let response = try JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject]
                print(response!)
                //Your code here                    
            } catch let error as NSError {
                print(error)
            }
        }

        task.resume()

    }

}


如果您有兴趣在SharedClass中使用此功能

//My shared class
import UIKit
class SharedClass: NSObject {

static let sharedInstance = SharedClass()

func postRequestFunction(apiName: String , parameters: String, onCompletion: @escaping (_ success: Bool, _ error: Error?, _ result: [String: Any]?)->()) {

    var URL =  "your URL here/index.php/***?"

    URL = URL.replacingOccurrences(of: "***", with: apiName)

    var request = URLRequest(url: URL(string: URL)!)
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    request.httpMethod = "POST"
    print("shared URL : \(request)")
    request.httpBody = parameters.data(using: .utf8)

    var returnRes:[String:Any] = [:]
    let task = URLSession.shared.dataTask(with: request) { data, response, error in

        if let error = error {
            onCompletion(false, error, nil)
        } else {
            guard let data = data else {
                onCompletion(false, error, nil)
                return
            }

            if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode == 200 {
                do {
                   returnRes = try JSONSerialization.jsonObject(with: data, options: []) as! [String : Any]
                    onCompletion(true, nil, returnRes)

                } catch let error as NSError {
                   onCompletion(false, error, nil)
                }
            } else {
                onCompletion(false, error, nil)
            }
        }
    }
    task.resume()
}


private override init() {

}


最后调用此函数这个....

SharedClass.sharedInstance.postRequestFunction(apiName: "Your API name", parameters: parameters) { (success, error, result) in
    print(result!)
    if success {
        //Your code here
    } else {
        print(error?.localizedDescription ?? "")
    }
}


#13 楼

发出HTTP GET请求的简单Swift 2.0方法

HTTP请求是异步的,因此您需要一种从HTTP请求获取返回值的方法。此方法使用通告程序,并且分布在两个类中。

示例是使用网站http://www.example.com/handler.php?do=CheckUserJson&json=来检查标识符令牌的用户名和密码,该文件称为处理程序。 php并在do参数上具有switch语句以获得RESTful方法。

在viewDidLoad中,我们设置了NotifierObserver,设置了json并调用了getHTTPRequest函数。它将返回带有http请求返回的参数的函数checkedUsernameAndPassword。进行HTTP调用。

override func viewDidLoad() {
    super.viewDidLoad()
    // setup the Notification observer to catch the result of check username and password
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "checkedUsernameAndPassword:", name: CHECK_USERNAME_AND_PASSWORD, object: nil)        
    let username = GlobalVariables.USER_NAME
    let password = GlobalVariables.PASSWORD
    // check username and password
    if let jsonString = Utility.checkUsernameAndPasswordJson(username, password:password){
        print("json string returned = \(jsonString)")
        let url = CHECKUSERJSON+jsonString
        // CHECKUSERJSON = http://www.example.com/handler.php?do=CheckUserJson&json=
        // jsonString = {\"username\":\"demo\",\"password\":\"demo\"}"
        // the php script handles a json request and returns a string identifier           
        Utility.getHTTPRequest(url,notifierId: CHECK_USERNAME_AND_PASSWORD)
        // the returned identifier is sent to the checkedUsernaeAndPassword function when it becomes availabel.
    }
}


和Http请求

    static func checkUsernameAndPasswordJson(username: String, password: String) -> String?{
    let para:NSMutableDictionary = NSMutableDictionary()
        para.setValue("demo", forKey: "username")
        para.setValue("demo", forKey: "password")
    let jsonData: NSData
    do{
        jsonData = try NSJSONSerialization.dataWithJSONObject(para, options: NSJSONWritingOptions())
        let jsonString = NSString(data: jsonData, encoding: NSUTF8StringEncoding) as! String
        return jsonString
    } catch _ {
        print ("UH OOO")
        return nil
    }
}


sendNotification函数完善了圈子。注意,在Observer中,选择器字符串的末尾有一个“:”。这允许通知在userInfo中携带有效负载。我给它一个字符串和一个整数。

    static func getHTTPRequest (url:String , notifierId: String) -> Void{
    let urlString = url
    let config = NSURLSessionConfiguration.defaultSessionConfiguration()
    let session = NSURLSession(configuration: config, delegate: nil, delegateQueue: nil)
    let safeURL = urlString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
    if let url = NSURL(string: safeURL){
        let request  = NSMutableURLRequest(URL: url)
        request.HTTPMethod = "GET"
        request.timeoutInterval = 60
        let taskData = session.dataTaskWithRequest(request, completionHandler: {
            (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
            if (data != nil) {
                let result = NSString(data: data! , encoding: NSUTF8StringEncoding)
                sendNotification (notifierId, message: String(result), num: 0)
            }else{
                  sendNotification (notifierId, message: String(UTF8String: nil), num: -1)                    }
        })
    taskData.resume()
    }else{
        print("bad urlString = \(urlString)")
    }
}


请注意,使用HTTP已过时,更喜欢使用HTTPS,请参阅如何在iOS中启用应用传输安全性的情况下加载HTTP URL 9?

#14 楼

 var post:NSString = "api=myposts&userid=\(uid)&page_no=0&limit_no=10"

    NSLog("PostData: %@",post);

    var url1:NSURL = NSURL(string: url)!

    var postData:NSData = post.dataUsingEncoding(NSASCIIStringEncoding)!

    var postLength:NSString = String( postData.length )

    var request:NSMutableURLRequest = NSMutableURLRequest(URL: url1)
    request.HTTPMethod = "POST"
    request.HTTPBody = postData
    request.setValue(postLength, forHTTPHeaderField: "Content-Length")
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    request.setValue("application/json", forHTTPHeaderField: "Accept")

    var reponseError: NSError?
    var response: NSURLResponse?

    var urlData: NSData? = NSURLConnection.sendSynchronousRequest(request, returningResponse:&response, error:&reponseError)

    if ( urlData != nil ) {
        let res = response as NSHTTPURLResponse!;

        NSLog("Response code: %ld", res.statusCode);

        if (res.statusCode >= 200 && res.statusCode < 300)
        {
            var responseData:NSString  = NSString(data:urlData!, encoding:NSUTF8StringEncoding)!

            NSLog("Response ==> %@", responseData);

            var error: NSError?

            let jsonData:NSDictionary = NSJSONSerialization.JSONObjectWithData(urlData!, options:NSJSONReadingOptions.MutableContainers , error: &error) as NSDictionary

            let success:NSInteger = jsonData.valueForKey("error") as NSInteger

            //[jsonData[@"success"] integerValue];

            NSLog("Success: %ld", success);

            if(success == 0)
            {
                NSLog("Login SUCCESS");

                self.dataArr = jsonData.valueForKey("data") as NSMutableArray
                self.table.reloadData()

            } else {

                NSLog("Login failed1");
                ZAActivityBar.showErrorWithStatus("error", forAction: "Action2")
            }

        } else {

            NSLog("Login failed2");
            ZAActivityBar.showErrorWithStatus("error", forAction: "Action2")

        }
    } else {

        NSLog("Login failed3");
        ZAActivityBar.showErrorWithStatus("error", forAction: "Action2")
}


肯定会为您提供帮助

#15 楼

//这是为我工作的示例

// Swift函数将具有键值的请求发布到服务器

func insertRecords()
{



    let usrID = txtID.text
    let checkin = lblInOut.text
    let comment = txtComment.text



    // The address of the web service
    let urlString = "http://your_url/checkInOut_post.php"

    // These are the keys that your are sending as part of the post request
    let keyValues = "id=\(usrID)&inout=\(checkin)&comment=\(comment)"




    // 1 - Create the session by getting the configuration and then
    //     creating the session

    let config = NSURLSessionConfiguration.defaultSessionConfiguration()
    let session = NSURLSession(configuration: config, delegate: nil, delegateQueue: nil)


    // 2 - Create the URL Object

    if let url = NSURL(string: urlString){


        // 3 - Create the Request Object

        var request  = NSMutableURLRequest(URL: url)
        request.HTTPMethod = "POST"

        // set the key values
        request.HTTPBody = keyValues.dataUsingEncoding(NSUTF8StringEncoding);


        // 4 - execute the request

        let taskData = session.dataTaskWithRequest(request, completionHandler: {

            (data:NSData!, response:NSURLResponse!, error:NSError!) -> Void in

            println("\(data)")

            // 5 - Do something with the Data back

            if (data != nil) {

                // we got some data back
                println("\(data)")

                let result = NSString(data: data , encoding: NSUTF8StringEncoding)
                println("\(result)")

                if result == "OK" {

                    let a = UIAlertView(title: "OK", message: "Attendece has been recorded", delegate: nil, cancelButtonTitle: "OK")

                    println("\(result)")

                    dispatch_async(dispatch_get_main_queue()) {


                    a.show()


                    }


                } else {
                  // display error and do something else

                }


            } else

            {   // we got an error
                println("Error getting stores :\(error.localizedDescription)")

            }


        })

        taskData.resume()



    }


}


PHP获取键值的代码

$ empID = $ _POST ['id'];

$ inOut = $ _POST ['inout'];

$ comment = $ _POST ['comment'];

#16 楼

这是一个在操场上非常简单的Swift 4示例:

import UIKit
// run asynchronously in a playground
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

// create a url
let url = URL(string: "http://www.stackoverflow.com")

// create a data task
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
    if error != nil {
        print("there's a problem")
    }
    print(String(data: data!, encoding: String.Encoding.utf8) ?? "")
}

//running the task w/ resume
task.resume()


#17 楼

为了使XCUITest在异步请求完成之前停止测试完成,请使用此命令(可能减少100超时):

func test_api() {
    let url = URL(string: "https://jsonplaceholder.typicode.com/posts/42")!
    let exp = expectation(description: "Waiting for data")
    let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
        guard let data = data else { return }
        print(String(data: data, encoding: .utf8)!)
        exp.fulfill()
    }
    task.resume()
    XCTWaiter.wait(for: [exp], timeout: 100)
}


#18 楼

吻答案:

URLSession.shared.dataTask(with: URL(string: "https://google.com")!) {(data, response, error) in
    print(String(data: data!, encoding: .utf8))
}.resume()


#19 楼

发出HTTP请求是现代语言的核心功能,并且是许多开发人员在适应新环境时首先要学习的内容之一。在谈到Swift时,无论是语言本身还是社区内部,都为该问题提供了大量解决方案。让我们看一些最受欢迎的例子。
这是Alamofire请求示例:-

在以下所有示例中,我们将在命令行上使用Swift。这并不意味着您不能将其中的任何一个复制并粘贴到Xcode,而是Swift拥有一系列有用的命令行实用程序,这些实用程序使在本教程中测试代码变得容易。
通过打开终端和导航到您希望此代码存在的目录。我的目录名为SwiftHTTP,您将在本文的其余示例中看到。
输入以下内容以生成可执行的命令行项目:
swift package init --type executable

这还将生成一个Package .swift文件。这样,我们可以添加依赖项以使用Swift Package Manager安装第三方库。
带有URLRequest的HTTP请求
首先,我们将使用称为URLRequest的内置API。如果要继续使用命令行,请在上一个命令生成的Sources目录中打开main.swift,然后输入以下代码:
import Foundation

// Set the URL the request is being made to.
let request = URLRequest(url: NSURL(string: "https://api.nasa.gov/planetary/apod? 
api_key=DEMO_KEY")! as URL)
do {
    // Perform the request
    var response: AutoreleasingUnsafeMutablePointer<URLResponse?>? = nil
    let data = try NSURLConnection.sendSynchronousRequest(request, returning: response)

    // Convert the data to JSON
    let jsonSerialized = try JSONSerialization.jsonObject(with: data, options: []) as? [String : Any]

    if let json = jsonSerialized, let url = json["url"], let explanation = json["explanation"] {
        print(url)
        print(explanation)
    }
}

发出HTTP请求。回到您的终端并运行以下命令,请记住,您可能必须修改此命令以适合您的Swift项目的名称:
swift build && .build/debug/SwiftHTTP

带有URLSession的HTTP请求
URLSession是另一个发送内置于该语言的HTTP请求的流行方法。 URLSession也不执行主线程之外的请求,这很漂亮。
修改main.swift使其包含以下代码:
import Foundation

let url = URL(string: "https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY")

let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in

    if let data = data {
        do {
            // Convert the data to JSON
            let jsonSerialized = try JSONSerialization.jsonObject(with: data, options: 
            []) as? [String : Any]

            if let json = jsonSerialized, let url = json["url"], let explanation = 
            json["explanation"] {
                print(url)
                print(explanation)
            }
        }  catch let error as NSError {
            print(error.localizedDescription)
        }
    } else if let error = error {
        print(error.localizedDescription)
    }
}

task.resume()

// Infinitely run the main loop to wait for our request.
// Only necessary if you are testing in the command line.
RunLoop.main.run()

我们之前在URLRequest上使用的示例是同步的,但此示例是异步的。因此,我们在最后调用RunLoop.main.run()以确保脚本在响应请求之前没有完成执行。如果在不同的上下文中使用此代码,请随意删除最后一行。
和以前一样,运行以下代码:
swift build && .build/debug/SwiftHTTP

一旦获得响应,请使用以下命令杀死脚本ctrl-c。
使用Alamofire的HTTP请求
以前的方法已内置到该语言中。但是Swift中也有第三方网络库。 Alamofire在Swift社区中是一个出色的(也是最受欢迎的)。
Alamofire是一个用户友好且用途广泛的库,具有很多选择。它具有可链接的请求和响应方法,并处理样板功能,例如验证HTTP响应。
与其他示例不同,我们需要修改Package.swift使其起作用。我们还将使用另一个名为SwiftyJSON的库,该库使JSON的解析更加用户友好,并且可以与Alamofire很好地配合。 />现在回到main.swift更改代码以使用Alamofire:
import PackageDescription

let package = Package(
   name: "SwiftHTTP",
   dependencies: [
       .Package(url: "https://github.com/Alamofire/Alamofire.git", majorVersion: 4),
       .Package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", majorVersion: 3, 
       minor: 1)
   ]
)

就像我们前面的选项一样,请求是异步的,因此我们调用RunLoop.main。 run()。

#20 楼

下面给出了示例“ GET”请求的示例。

let urlString = "YOUR_GET_URL"
let yourURL = URL(string: urlstring)
let dataTask = URLSession.shared.dataTask(with: yourURL) { (data, response, error) in
do {
    let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers)
    print("json --- \(json)")
    }catch let err {
    print("err---\(err.localizedDescription)")
    }
   }
dataTask.resume()