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


当前回答

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

其他回答

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

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

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

你可以使用URL URLRequest URLSession或者NSURLConnection就像你在Objective-C中通常做的那样。注意,对于iOS 7.0及更高版本,URLSession是首选。

使用URLSession

初始化URL对象和URLSession中的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

首先,初始化URL和URLRequest:

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

然后,你可以异步加载请求:

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

或者你可以初始化一个NSURLConnection:

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

只是要确保将委托设置为nil以外的东西,并使用委托方法处理接收到的响应和数据。

要了解更多细节,请查看NSURLConnectionDataDelegate协议的文档

在Xcode操场上测试

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

PlaygroundPage.current.needsIndefiniteExecution = true

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

答:吻

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

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