如何在Swift中进行HTTP请求?

我在iBooks中阅读了Apple的编程语言Swift,但不知道如何在Swift中发出HTTP请求(类似cURL)。我需要导入Obj-C类还是只需要导入默认库?或者不能基于原生Swift代码进行HTTP请求?

512550 次浏览

你可以像在Objective-C中一样使用URLURLRequestURLSessionNSURLConnection。注意,对于iOS 7.0及更高版本,URLSession是首选。

使用URLSession

URLSession初始化URL对象和URLSessionDataTask对象。然后使用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协议的文档 . conf文件

在Xcode操场上测试

如果你想在Xcode游乐场上尝试这段代码,添加import PlaygroundSupport到你的游乐场,以及下面的调用:

PlaygroundPage.current.needsIndefiniteExecution = true

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

斯威夫特3.0

通过一个小抽象 https://github.com/daltoniam/swiftHTTP < / p >

例子

    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)")
}
 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")
}

它一定会对你有帮助

我调用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.

检查以下代码:

1. SynchonousRequest

斯威夫特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

斯威夫特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连接

斯威夫特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请求

斯威夫特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. 异步GET请求

斯威夫特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()

你可以使用只是,一个python-requests风格的HTTP库。

使用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

你可以在操场上中找到更多的例子

在操场上以同步模式使用这个库是Swift中最接近cURL的东西。

另一个选项是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)
}

我已经完成了HTTP请求这两个方法得到 &帖子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")
}


})
}

完成

//这是一个对我有用的例子

//发送请求到服务器的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'];

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

HTTP请求是异步的,因此需要一种方法从HTTP请求中获取返回值。这种方法使用通知器,分布在两个类中。

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

在viewDidLoad中,我们设置了NotifierObserver,设置了json,并调用getHTTPRequest函数。它将返回函数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.
}
}

在Utility.swift中有两个静态函数,首先用于编码json,然后执行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
}
}

和Http请求

    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)")
}
}

sendNotification函数完成了循环。注意,在观察者中,在选择器字符串的末尾有一个“:”。这允许通知在userInfo中携带有效负载。我给它一个String和Int。

    static func sendNotification (key: String, message:String?, num: Int?){
NSNotificationCenter.defaultCenter().postNotificationName(
key,
object: nil,
userInfo:   (["message": message!,
"num": "\(num!)"])
)
}

注意,使用HTTP是老式的,更喜欢HTTPS参见我如何加载一个HTTP URL与应用程序传输安全启用在iOS 9?

基本的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 4及以上:使用URLSession API进行数据请求

   // create the url
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及以上,可解码和结果enum

// APIError enum which shows all possible Network errors
enum APIError: Error {
case networkError(Error)
case dataNotFound
case jsonParsingError(Error)
case invalidStatusCode(Int)
case badURL(String)
}


// 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
guard let dataURL = URL(string: url) else {
completion(.failure(APIError.badURL(url))
return
}
    

// 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(APIError.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(APIError.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)

细节

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

Info.plist

NSAppTransportSecurity

添加到info plist:

<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")
}

结果

enter image description here

下面是一个非常简单的斯威夫特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()

在Swift 4.1和Xcode 9.4.1中。

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

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 ?? "")
}
}

下面给出了一个“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()

__abc0 + __abc1

只要添加到cezar的回答,如果你想使用苹果的URLSession类进行web请求,有多种方法来完成任务

  1. 简单的GET请求与URL
  2. 简单的GET请求与URL和参数
  3. 简单的GET请求与错误处理的URL
  4. 简单的POST请求与URL,参数与错误处理

1. 简单的GET请求与URL

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()
}

__abc0: __abc1

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

2. 简单的GET请求与URL和参数

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.简单的GET请求与错误处理的URL

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. 简单的POST请求与URL,参数与错误处理。

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()
}

谢谢你的建议!!

为了让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)
}

答:吻

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

更新:- Xcode 13.0 &斯威夫特5 +

获取HTTP请求

let url = URL(string: "URL HERE")! //PUT Your URL
var request = URLRequest(url: url)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let safeData = data,
let response = response as? HTTPURLResponse,
error == nil else {                                              // check for fundamental networking error
print("error", error ?? "Unknown error")
delegate?.onError(error!)
return
}
            

guard (200 ... 299) ~= response.statusCode else {                    // check for http errors
print("statusCode should be 2xx, but is \(response.statusCode)")
print("response = \(response)")
return
}
            

let responseString = String(data: safeData, encoding: .utf8)
print("Response String = \(responseString)")
}
        

task.resume()

下面是在Linux上使用Swift进行HTTP请求的从头到尾的说明。

首先创建一个SwiftPM包

mkdir swift-http && cd swift-http && swift package init --type executable
然后替换./Sources/swift-http/main.swift的内容 用下面的代码:

import Foundation
import FoundationNetworking


let sema = DispatchSemaphore(value: 0)


URLSession.shared.dataTask(with: URL(string: "http://numbersapi.com/42")!) {(data, response, error) in
print(String(data: data!, encoding: .utf8) ?? String(describing: error))
sema.signal()
}.resume()


sema.wait()

然后运行代码

swift run

输出的例子:

[6/6] Build complete!
42 is the answer to the Ultimate Question of Life, the Universe, and Everything.

注意: DispatchSemaphore被使用,这样我们的程序在得到响应之前不会退出。

你也可以这样做:

import Foundation
import FoundationNetworking


var done = false


URLSession.shared.dataTask(with: URL(string: "http://numbersapi.com/42")!) {(data, response, error) in
print(String(data: data!, encoding: .utf8) ?? String(describing: error))
done = true
}.resume()


while !done { Thread.sleep(forTimeInterval: 1) }