Bagaimana cara saya membuat permintaan HTTP di Swift?

371

Saya membaca The Programming Language Swift oleh Apple di iBooks, tetapi tidak dapat menemukan cara untuk membuat permintaan HTTP (seperti cURL) di Swift. Apakah saya perlu mengimpor kelas Obj-C atau apakah saya hanya perlu mengimpor perpustakaan default? Atau apakah tidak mungkin untuk membuat permintaan HTTP berdasarkan kode Swift asli?

Dicky Tsang
sumber
2
Gunakan URLSession (GET, POST, DELETE METHODS): stackoverflow.com/a/48306950/6898523
MAhipal Singh

Jawaban:

550

Anda dapat menggunakan URL, URLRequestdan URLSessionatau NSURLConnectionseperti yang biasa Anda lakukan di Objective-C. Perhatikan bahwa untuk iOS 7.0 dan yang lebih baru, URLSessionlebih disukai.

Menggunakan URLSession

Inisialisasi URLobjek dan URLSessionDataTaskdari URLSession. Kemudian jalankan tugas dengan 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()

Menggunakan NSURLConnection

Pertama, inisialisasi a URLdan a URLRequest:

let url = URL(string: "http://www.stackoverflow.com")!
var request = URLRequest(url: url)
request.httpMethod = "POST" 

Kemudian, Anda dapat memuat permintaan secara tidak sinkron dengan:

NSURLConnection.sendAsynchronousRequest(request, queue: OperationQueue.main) {(response, data, error) in
    guard let data = data else { return }
    print(String(data: data, encoding: .utf8)!)
}

Atau Anda dapat menginisialisasi NSURLConnection:

let connection = NSURLConnection(request: request, delegate:nil, startImmediately: true)

Pastikan untuk mengatur delegasi Anda ke sesuatu selain nildan menggunakan metode delegasi untuk bekerja dengan respons dan data yang diterima.

Untuk detail lebih lanjut, periksa dokumentasi untuk NSURLConnectionDataDelegateprotokolnya

Menguji bermain Xcode

Jika Anda ingin mencoba kode ini di taman bermain Xcode, tambahkan import PlaygroundSupportke taman bermain Anda, serta panggilan berikut:

PlaygroundPage.current.needsIndefiniteExecution = true

Ini akan memungkinkan Anda untuk menggunakan kode asinkron di taman bermain.

Cezar
sumber
2
Jangan buang waktu Anda di iOS 8 beta 2 di taman bermain karena XCPlayground tidak didukung. Ada cara pintar dan jelek untuk menunggu jika Anda ingin mencoba retas: stackoverflow.com/a/24058337/700206
whitneyland
7
Bagaimana Anda mengirim data POST menggunakan NSURLSession?
Fernando Santiago
2
Contoh ini gagal pada 6.1: test.swift: 5: 57: error: nilai tipe opsional 'NSURL?' tidak terbuka; apakah Anda bermaksud menggunakan '!' atau '?'? biarkan tugas = NSURLSession.sharedSession (). dataTaskWithURL (url) {(data, respons, kesalahan) di
mcuadros
2
Menambahkan tanda seru memperbaiki pesan kesalahan @mcuadros ... .dataTaskWithURL (url!)
Sean McClory
3
Bisakah Anda memperbaiki snipet kode? Inilah yang berfungsi pada Swift 4print(String(data: data!, encoding: String.Encoding.utf8))
Nate
101

Periksa Kode Di Bawah Ini:

1. Pertanyaan Synchonous

Cepat 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. Permintaan Asynchonous

Cepat 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. Seperti koneksi URL biasa

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

Kemudian

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

Kemudian

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. Permintaan POST Asynchonous

Cepat 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. MENDAPATKAN Permintaan Asynchonous

Cepat 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. Unggah Gambar (File)

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()
PREMKUMAR
sumber
93

Opsi lain adalah lib Alamofire yang menawarkan metode Chainable Request / Response.

https://github.com/Alamofire/Alamofire

Membuat permintaan

import Alamofire

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

Penanganan Respons

Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
         .response { request, response, data, error in
              print(request)
              print(response)
              print(error)
          }
Bijan
sumber
125
Saya pikir membalas dengan menyarankan lib eksternal, sementara fungsi disediakan oleh kerangka kerja bukanlah cara yang tepat untuk melakukannya.
turkishweb
9
@turkishweb benar. Jawaban Cezar lebih lengkap dan tidak menggunakan perpustakaan eksternal. Itu harus menjadi jawaban yang diterima.
FredMaggiowski
12
Jawaban Cezar sudah usang (karena Swift 3) dan antarmuka Alamofire jauh lebih bagus daripada URLSessiondan dari permaisuri. Juga, penerimaan bukanlah ukuran dari beberapa ukuran abstrak kebaikan (apalagi milikmu!;)) Tetapi dari apa yang paling membantu OP. (Untuk solusi "murni", ada SO Dokumentasi!) Jika itu adalah jawaban ini, sempurna - itu tidak menggunakan prinsip pertama, tetapi kemudian itu tidak selalu merupakan solusi "benar", bukan?
Raphael
9
Tolong jangan menawarkan perpustakaan pihak ketiga kecuali jika diminta secara khusus, sesuai pedoman SO
Alec O
1
Alamofire adalah yang terbaik
tania_S
36

Swift 4 dan lebih tinggi: Permintaan Data menggunakan API URLSession

   //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 dan lebih tinggi, Decodable dan Result enum

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

contoh:

// jika kita ingin mengambil todo dari placeholder API, maka kita mendefinisikan struct ToDo dan memanggil dataRequest dan meneruskan " https://jsonplaceholder.typicode.com/todos/1 " url string.

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

// ini mencetak hasilnya:

ToDo(id: 1, userId: 1, title: "delectus aut autem", completed: false)
Suhit Patil
sumber
21

Solusi Dasar 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()
Ben Sullivan
sumber
3
Contoh Anda adalah untuk Swift 3 , jadi Anda harus menggunakan URL(string: "http://www.stackoverflow.com")sebagai gantinyaNSURL
FelixSFD
casting dari URL ke URL tidak masuk akalURLSession.shared.dataTask(with: url!)
Leo Dabus
Saya mendapatkan kesalahan ini:App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.
@YumYumYum Sudahkah Anda mengonfigurasi keamanan transportasi aplikasi sesuai pos ini stackoverflow.com/questions/30731785/…
Ben Sullivan
Leo Dabus url variabel bertipe URL?
Tom Schulz
14

Saya menggunakan pembungkus orang ini dengan hasil yang baik sejauh ini https://github.com/daltoniam/swiftHTTP . Tidak ada abstraksi besar yang bocor sejauh ini

Contoh

    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)")
    }
Alex Nolasco
sumber
3
Sudahkah Anda menemukan cara untuk menunggu permintaan selesai sebelum menunjukkan tampilan? @AlexanderN
Reshad
9

Detail

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

Info.plist

NSAppTransportSecurity

Tambahkan ke daftar info:

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

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

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

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

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

Hasil

masukkan deskripsi gambar di sini

Bodnarchuk dengan mudah
sumber
searchRequest? istilah? Mereka berasal dari mana?
El Tomato
Ini adalah contoh lengkap permintaan. class func searchRequest(term: String, ...adalah contoh data pengunduhan dari itunes.apple.com. Sampel ini akan mencari, jadi, saya memilih / menemukan searchRequestnama fungsi. termbagian " itunes.apple.com/search ?" permintaan. Anda dapat memilih nama fungsi apa pun yang akan menjelaskan model logika Anda.
Vasily Bodnarchuk
Solusi yang bagus. Saya telah mengubah closureuntuk mengembalikan enum dengan kasing successdan error.
neoneye
7

Saya telah melakukan Permintaan HTTP Kedua metode DAPATKAN & POST dengan JSON Parsing dengan cara ini:

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

    })
}

Selesai

Hiren Patel
sumber
Tidak dapat memanggil 'sendAsynchronousRequest' dengan daftar argumen tipe '(NSMutableURLRequest, antrian: NSOperationQueue, completionHandler: (NSURLResponse !, NSData !, NSError!) -> Void)'
bMalum
4

Menggunakan URLSession + Swift 5

Hanya menambahkan jawaban cezar , jika Anda ingin membuat permintaan web menggunakan kelas URLSession Apple, ada beberapa cara untuk melakukan tugas tersebut

  1. Permintaan GET sederhana dengan URL
  2. Permintaan GET sederhana dengan URL dan Parameter
  3. Permintaan GET sederhana dengan URL dengan Penanganan Kesalahan
  4. Permintaan POST sederhana dengan URL, Parameter dengan Penanganan Kesalahan

1. Permintaan GET Sederhana dengan 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()
    }

Catatan : Pastikan Anda harus menambahkan kunci "NSAppTransportSecurity" di pList untuk permintaan http

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

2. Permintaan GET Sederhana dengan URL dan Parameter

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. MENDAPATKAN Permintaan Sederhana dengan URL dengan Penanganan Kesalahan

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. Permintaan POST sederhana dengan URL, Parameter dengan Penanganan Kesalahan.

func simplePostRequestWithParamsAndErrorHandling(){
        var session = URLSession.shared
        let configuration = URLSessionConfiguration.default
        configuration.timeoutIntervalForRequest = 30
        configuration.timeoutIntervalForResource = 30
        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()
    }

Saran Anda sangat dihargai !!

swiftBoy
sumber
Mengapa Anda menggunakan var session = URLSession.sharedsaat Anda tidak menggunakannya, tetapi hanya menimpa variabel? Apakah itu dibutuhkan?
vrwim
3

Saya memanggil json pada klik tombol login

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

Di sini, saya telah membuat kamus terpisah untuk parameter.

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.
Annu
sumber
2

Anda dapat menggunakan Just , python-requestsperpustakaan HTTP gaya.

Beberapa contoh pengiriman permintaan HTTP dengan Just:

// 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! */ }
}

Dalam kedua kasus, hasil permintaan rdapat diakses dengan cara yang mirip dengan 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

Anda dapat menemukan lebih banyak contoh di taman bermain ini

Menggunakan perpustakaan ini dalam mode sinkron di taman bermain adalah hal yang paling dekat dengan CURL yang bisa didapatkan di Swift.

Daniel Duan
sumber
Meskipun tautan ini dapat menjawab pertanyaan, lebih baik untuk memasukkan bagian-bagian penting dari jawaban di sini dan memberikan tautan untuk referensi. Jawaban hanya tautan dapat menjadi tidak valid jika halaman tertaut berubah.
dimo414
Sepertinya perpustakaan ini sudah usang. Tidak ada dukungan Swift 4 dan tidak ada yang menanggapi masalah terbuka.
Heinrisch
2

Dalam Swift 4.1 dan Xcode 9.4.1.

Contoh pendekatan JSON POST . Untuk memeriksa koneksi internet, tambahkan file Reachability.h & .m dari 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()

    }

}

Jika Anda tertarik menggunakan fungsi ini di 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() {

}

Dan akhirnya memanggil fungsi ini seperti ini ....

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

Pendekatan Swift 2.0 sederhana untuk membuat permintaan HTTP GET

Permintaan HTTP asinkron sehingga Anda perlu cara untuk mendapatkan nilai yang dikembalikan dari Permintaan HTTP. Pendekatan ini menggunakan Notifiers dan tersebar di dua kelas.

Contohnya adalah untuk memeriksa nama pengguna dan kata sandi untuk token pengidentifikasi menggunakan situs web http://www.example.com/handler.php?do=CheckUserJson&json= Itu adalah file yang disebut handler.php dan memiliki pernyataan beralih pada lakukan parameter untuk mendapatkan pendekatan yang tenang.

Di viewDidLoad kita mengatur NotifierObserver, mengatur json dan melakukan panggilan ke fungsi getHTTPRequest. Ini akan kembali ke fungsi checkedUsernameAndPassword dengan parameter yang dikembalikan dari permintaan 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.
    }
}

Ada dua fungsi statis di Utility.swift pertama untuk menyandikan json dan kemudian melakukan panggilan 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
    }
}

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

Fungsi sendNotification melengkapi lingkaran. Perhatikan bahwa di Observer ada ":" di akhir string pemilih. Ini memungkinkan pemberitahuan untuk membawa muatan di userInfo. Saya memberikan ini String dan Int.

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

Perhatikan bahwa menggunakan HTTP adalah oldFashioned, lebih suka HTTPS lihat Bagaimana cara memuat URL HTTP dengan App Transport Security diaktifkan di iOS 9?

pengguna462990
sumber
0
 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")
}

itu pasti akan membantu Anda

Mohit Tomar
sumber
0

// Ini contoh yang cocok untukku

// Fungsi Swift yang mengirim permintaan ke server dengan nilai kunci

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



    }


}

Kode PHP untuk mendapatkan nilai kunci

$ empID = $ _POST ['id'];

$ inOut = $ _POST ['inout'];

$ comment = $ _POST ['comment'];

Ali
sumber
0

Berikut adalah contoh Swift 4 yang sangat sederhana di taman bermain:

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()
kerajinan
sumber
0

Agar XCUITest menghentikan pengujian sebelum permintaan async selesai gunakan ini (mungkin kurangi waktu tunggu 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)
}
Charlie Seligman
sumber
0

Jawaban KISS:

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

Contoh untuk permintaan "GET" sampel diberikan di bawah ini.

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()
Haseeb Mohamed
sumber