我在iBooks中阅读了Apple编程语言Swift,但无法弄清楚如何在Swift中创建一个http请求(类似于CURL).我是否需要导入Obj-C类或者我只需要导入默认库?或者是否无法基于本机swift代码发出HTTP请求?
您可以使用URL
,URLRequest
而且URLSession
还是NSURLConnection
因为你通常在Objective-C做.请注意,对于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
首先,初始化a URL
和a URLRequest
:
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游乐场上尝试此代码,请添加import PlaygroundSupport
到您的游乐场,以及以下调用:
PlaygroundPage.current.needsIndefiniteExecution = true
这将允许您在游乐场中使用异步代码.
基本的Swift 3解决方案
let url = URL(string: "http://www.stackoverflow.com") let task = URLSession.shared.dataTask(with: url! as URL) { data, response, error in guard let data = data, error == nil else { return } print(NSString(data: data, encoding: String.Encoding.utf8.rawValue)) } task.resume()
使用URLSession API的Swift 3及更高版本的数据请求
//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,Decodable和Result枚举
//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,那么我们定义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)
另一种选择是提供可链接请求/响应方法的Alamofire lib.
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) }
Xcode 9.2,Swift 4
<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>
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) } } }
检查以下代码:
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
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) }
Swift 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!){ 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) } }
4.异步POST请求
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) } })
5. Asynchonous GET请求
Swift 1.2
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)") })
Swift 2.0 +
let urlPath: String = "YOUR URL HERE" let url: NSURL = NSURL(string: urlPath)! let request1: NSMutableURLRequest = NSMutableURLRequest(URL: url) request1.HTTPMethod = "GET" 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 mainURL = "YOUR_URL_HERE" let url = NSURL(string: mainURL) let request = NSMutableURLRequest(URL: url!) let boundary = "78876565564454554547676" request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") request.HTTPMethod = "POST" // POST OR PUT What you want let session = NSURLSession(configuration:NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: nil, delegateQueue: nil) let imageData = UIImageJPEGRepresentation(UIImage(named: "Test.jpeg")!, 1) var body = NSMutableData() body.appendData("--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) // Append your parameters body.appendData("Content-Disposition: form-data; name=\"name\"\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) body.appendData("PREMKUMAR\r\n".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!) body.appendData("--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) body.appendData("Content-Disposition: form-data; name=\"description\"\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) body.appendData("IOS_DEVELOPER\r\n".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!) body.appendData("--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) // Append your Image/File Data var imageNameval = "HELLO.jpg" body.appendData("--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) body.appendData("Content-Disposition: form-data; name=\"profile_photo\"; filename=\"\(imageNameval)\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) body.appendData("Content-Type: image/jpeg\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) body.appendData(imageData!) body.appendData("\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) body.appendData("--\(boundary)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) request.HTTPBody = body let dataTask = session.dataTaskWithRequest(request) { (data, response, error) -> Void in if error != nil { //handle error } else { let outputString : NSString = NSString(data:data!, encoding:NSUTF8StringEncoding)! print("Response:\(outputString)") } } dataTask.resume()
我已经完成了HTTP请求两种方法GET&POST与JSON解析这种方式:
在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") } }) }
完成
到目前为止,我正在使用这个人的包装器,效果很好 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)") }