【问题标题】:Asynchronous issue: Calling Web Api from Swift异步问题:从 Swift 调用 Web Api
【发布时间】:2018-05-30 09:04:29
【问题描述】:

当我第一次单击按钮时,我得到“失败 998”。然后当我第二次单击时,我得到“成功 999”。这应该是异步问题,这就是为什么我添加了“DispatchQueue”代码行但它不起作用。当我第一次按下按钮时,我应该得到“成功 999”。我该如何解决这个问题? (顺便swift版本是4.1)

这里是源代码:

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var lblDetail: UILabel!

var globalTempValue = ""

override func viewDidLoad() {
    super.viewDidLoad()
}


struct MyGitHub: Codable {
    let resultCode: String?
    private enum CodingKeys: String, CodingKey {
        case resultCode
    }
}

@IBAction func btnClickAction(_ sender: Any) {
  callMyApi()

    if (globalTempValue == "999")
    {
       print ("success 999")
    }
    else
    {
        print ("fail 998")
    }
}

func callMyApi()
{
    guard let gitUrl = URL(string: "https://transsupp.com/tApp/ws01.ashx") else
    { return }
    URLSession.shared.dataTask(with: gitUrl)
    {
            (data, response , error) in
            guard let data = data else { return }
            do
            {
                let decoder = JSONDecoder()
                let gitData = try decoder.decode(MyGitHub.self, from: data)
                DispatchQueue.main.async
                    {
                        self.globalTempValue = gitData.resultCode!
                    }
            }
            catch
                let err
            {
                print("Err", err)
            }
    }.resume()
}
}

web api 返回这个结构:

{
  "resultCode": "999",
  "resultMessage": "ok",
  "showPopUpPage": "True",
  "contentTextOfPopUpPage": "ws01Settings4Colors.ashx<br/>table:renkAyarlari<br/>showPopUpPage:True<br/><a href=https://www.google.com>click for the link brother</a>and this a skip line in here<br/>",
  "backgroundColor": "4D5656",
  "textColorOnThePage": "FFFFFF",
  "alertTextColorOnThePage": "E91E63",
  "buttonTextColor": "FFFFFF",
  "buttonBackgroundColor": "81D4FA",
  "alertButtonTextColor": "FFFFFF",
  "alertButtonBackgroundColor": "E91E63",
  "inputTextColor": "4D5656",
  "inputBackgroundColor": "FFFFFF",
  "dropDownMenuTextColor": "4D5656",
  "dropDownMenuBackgroundColor": "FFFFFF",
  "showBackgroundImage": "False",
  "backgroundImagePath": "http://transsupp.com/app/Assets/BackgroundImages/other_background.png"
}

【问题讨论】:

标签: json swift


【解决方案1】:

使用完成块在异步任务之后执行操作。

func callMyApi(param: String, completion: @escaping (_ result : MyGitHub?, _ error: Error?) -> Void)
    {
        guard let gitUrl = URL(string: "https://transsupp.com/tApp/ws01.ashx") else
        { return }
        URLSession.shared.dataTask(with: gitUrl)
        {
            (data, response , error) in
            guard let data = data else { return }
            do
            {
                let decoder = JSONDecoder()
                let gitData = try decoder.decode(MyGitHub.self, from: data)
                DispatchQueue.main.async
                    {
                        completion(gitData, nil)
                }
            }
            catch
                let err
            {
                print("Err", err)
                completion(nil, err)
            }
            }.resume()
    }

调用上述函数:

self.callMyApi(param: "PRARAM_STRING") { (result, error) in
        if result?.resultCode == "999"
        {
            print ("success 999")
        }else{
            print ("fail 998")
        }
    }

【讨论】:

  • 感谢您的回复。但是当我调用 self.callMyApi 函数时如何发送参数。当我调用这个函数时,我要写什么而不是“结果”而不是“错误”。如果可能的话,你能更新你的回复吗? @洛基
  • @mannyCalavera - 检查更新的答案,只是将单个参数添加为String 类型,您可以根据需要添加参数。 'result' & 'error' 不是参数,它们是完成块的返回值。
【解决方案2】:

然后您调用您的 API,而无需等待您检查 globalTempValue 的响应,此时它等于“”。第二次你成功了,因为到那时结果已经从你的第一次调用中回来了。您可以通过多种方式解决此问题,其中一种在 dataTask 闭包中,另一种在 globalTempValue 上使用属性观察器,如下所示:

var globalTempValue: String = "" {
    willSet{
        if (newValue == "999")
        {
            print ("success 999")
        }
        else
        {
            print ("fail 998")
        }
    }
}

【讨论】:

  • 让我告诉你我做了什么:我在 callMyApi() 之后在 'btnClickAction' 中编写了你的​​解决方案。然后我按下按钮,但它不起作用。我的意思是我在点击按钮后在 xcode 的输出对话框中看不到任何内容。顺便说一句,我在'viewDidLoad'行和'UIViewController'@Andras M之间保留'var globalTempValue =“”'定义。
  • 我的代码没有进入 btnClickAction,而是替换了 globalTempValue 声明。这样,您声明变量并为其分配一个空字符串的初始 vslue,并添加一个属性观察器,该观察器在属性即将更改时触发并打印 newValue
猜你喜欢
  • 2020-03-10
  • 1970-01-01
  • 2015-05-12
  • 2010-11-16
  • 1970-01-01
  • 2015-09-01
  • 1970-01-01
  • 2021-07-02
  • 2012-07-15
相关资源
最近更新 更多