草庐IT

ios - 在 iOS Swift 中执行 POST 请求

coder 2023-09-12 原文

我正在尝试执行 POST 请求,但请求没有通过。我已经看过 Perform POST request in Swift已经,但它不包含我正在寻找的内容。

func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool {
    var request = NSMutableURLRequest(URL: NSURL(string: "https://us1.lacunaexpanse.com"))
    println("request url https://us1.lacunaexpanse.com")
    var session = NSURLSession.sharedSession()
    request.HTTPMethod = "POST"

    let apikey = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    println("apikey",apikey)

    let username = "username"
    let password = "password"

    var login = Array(["username", "password", "apikey"])

    let jsonDictionary = ["2.0", "jsonrpc", "1", "id", "login", "method", "login", "params"]
    println("jsonDictionary",jsonDictionary)

    var writeError: NSError?

    let jsonData = NSJSONSerialization.dataWithJSONObject(jsonDictionary, options: NSJSONWritingOptions(), error: NSErrorPointer())

    var resultAsString = NSString(data: jsonData, encoding: NSUTF8StringEncoding)

    resultAsString = resultAsString.stringByAppendingString("empire")

    let url = NSURL.URLWithString("string")
    println("url",url)

    var request2 = NSMutableURLRequest()
    println("Post url =%@",url)

    request2 = NSMutableURLRequest(URL:url)

    request2.HTTPMethod = "POST"

    var connection = NSURLConnection(request: request, delegate: self, startImmediately: false)

    return true

最佳答案

这里有一大堆战术问题:

  1. 您正在创建 URLSession,然后发出 NSURLConnection 请求。只需使用 URLSession

  2. 您的“请求字典”不是字典,而是数组。例如发出JSON-RPC请求,字典的正确格式是:

    let requestDictionary: [String: Any] = [
        "jsonrpc" : "2.0",
        "id"      : 1,
        "method"  : "login",
        "params"  : ["myuserid", "mypassword", "mykey"]
    ]
    
  3. 小问题,但是您使用了很多变量(通过 var),而常量(通过 let)就可以了。本着 Swift 的安全精神,尽可能使用 let

  4. 根据 Lacuna Expanse API ,您的 URL 应该包含模块名称。

    因此,例如,如果在“Empire”模块中执行POST 请求,则URL 是:

    let url = URL(string: "https://us1.lacunaexpanse.com/empire")!
    
  5. 您可能会执行大量请求,因此我建议将大部分请求放在一个可以反复调用的函数中,而无需到处重复代码。也许像下面这样的函数采用以下参数:

    • 模块(例如“帝国”与“联盟”);

    • 方法(例如“登录”与“获取验证码”);

    • 适合该请求的参数(例如,对于“登录”,这将是“名称”、“密码”和“api_key”);和

    • 将在异步请求完成时调用的闭包。

    此函数然后准备 JSON-RPC 请求并在请求完成时调用闭包:

    @discardableResult
    func submitLacunaRequest(module: String, method: String, parameters: Any, completion: @escaping (Result<[String: Any], Error>) -> Void) -> URLSessionTask? {
        let session = URLSession.shared
        let url = URL(string: "https://us1.lacunaexpanse.com")!
            .appendingPathComponent(module)
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json-rpc", forHTTPHeaderField: "Content-Type")
    
        let requestDictionary: [String: Any] = [
            "jsonrpc": "2.0",
            "id"     : 1,
            "method" : method,
            "params" : parameters
        ]
    
        request.httpBody = try! JSONSerialization.data(withJSONObject: requestDictionary)
    
        let task = session.dataTask(with: request) { data, response, error in
    
            // handle fundamental network errors (e.g. no connectivity)
    
            guard error == nil, let data = data else {
                completion(.failure(error ?? URLError(.badServerResponse)))
                return
            }
    
            // check that http status code was 200
    
            guard
                let httpResponse = response as? HTTPURLResponse,
                200 ..< 300 ~= httpResponse.statusCode
            else {
                completion(.failure(URLError(.badServerResponse)))
                return
            }
    
            // parse the JSON response
    
            do {
                guard let responseObject = try JSONSerialization.jsonObject(with: data) as? [String: Any] else {
                    throw URLError(.badServerResponse)
                }
                completion(.success(responseObject))
            } catch let parseError {
                completion(.failure(parseError))
            }
        }
        task.resume()
    
        return task
    }
    

    这会在 JSON-RPC 请求中对方法和参数进行所有必要的包装。然后,您需要做的就是调用该方法:

    submitLacunaRequest(module: "empire", method: "login", parameters: ["myuserid", "mypassword", "mykey"]) { result in
    
        switch result {
        case .failure(let error):
            print("error = \(error)")
    
        case .success(let value):
            if let errorDictionary = value["error"] as? [String: Any] {
                print("error logging in (bad userid/password?): \(errorDictionary)")
            } else if let resultDictionary = value["result"] as? [String: Any] {
                print("successfully logged in, refer to resultDictionary for details: \(resultDictionary)")
            } else {
                print("we should never get here")
                print("responseObject = \(value)")
            }
        }
    }
    

    对于需要字典的请求,例如“创建”,只需提供字典即可:

    submitLacunaRequest(module:"empire", method: "create", parameters: [
        "name"      : "user",
        "password"  : "password",
        "password1" : "password",
        "captcha_guid" : "305...dd-....-....-....-e3706...73c0",
        "captcha_solution" : "42",
        "email" : "test@gmail.com"
    ]) { result in
        switch result {
        case .failure(let error):
            print("error = \(error)")
    
        case .success(let value):
            print("responseObject = \(responseObject)")
        }
    }
    

很明显,在上面这些中,我只是做了最少的错误处理,所以你可以加强这个,但你的问题是关于发出 POST 请求,希望上面说明了这是如何完成的。

有关 Swift 2 版本,请参阅 previous revision这个答案。

关于ios - 在 iOS Swift 中执行 POST 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25341858/

有关ios - 在 iOS Swift 中执行 POST 请求的更多相关文章

  1. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  2. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  3. ruby-on-rails - rails : How to make a form post to another controller action - 2

    我知道您通常应该在Rails中使用新建/创建和编辑/更新之间的链接,但我有一个情况需要其他东西。无论如何我可以实现同样的连接吗?我有一个模型表单,我希望它发布数据(类似于新View如何发布到创建操作)。这是我的表格prohibitedthisjobfrombeingsaved: 最佳答案 使用:url选项。=form_for@job,:url=>company_path,:html=>{:method=>:post/:put} 关于ruby-on-rails-rails:Howtomak

  4. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  5. ruby - Chef 执行非顺序配方 - 2

    我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul

  6. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  7. ruby - 有人可以帮助解释类创建的 post_initialize 回调吗 (Sandi Metz) - 2

    我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法

  8. ruby - 为什么 Ruby 的 each 迭代器先执行? - 2

    我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试

  9. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  10. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

随机推荐