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


当前回答

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)

其他回答

检查以下代码:

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

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

快速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()

Then

 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)



}

快速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()

Then

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


        })

快速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)")


        })

快速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. 上传图片(文件)

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

    })
}

Done

一个简单的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?

答:吻

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

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