【问题标题】:Return String and display it in NSTextField (SwiftUI / macOS App)返回字符串并在 NSTextField 中显示(SwiftUI / macOS App)
【发布时间】:2020-12-22 17:14:02
【问题描述】:

我有以下问题:我想制作一个显示太阳信息的应用程序。我已经设法在控制台中打印了日出,但这不是最终目标。我想在 NSTextField 中显示它。这就是它开始出现问题的地方。

我尝试在private func getData() 中添加self.sunrise1.stringValue = sunrise。显然这不起作用,Xcode 告诉我,

NSControl.stringValue 只能在主线程中使用

所以现在我想我必须返回 sunrise 变量。但是当我添加return(sunrise)时Xcode显示错误:

意外的非空返回错误

所以我的问题是,如何在标签sunrise1 中显示sunrisestringValue

class ViewController: NSViewController {
    
    @IBOutlet weak var sunrise1: NSTextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let url = "https://api.sunrise-sunset.org/json?lat=36.7201600&lng=-4.4203400"
        getData(from: url)
        

        // Do any additional setup after loading the view.
    }
    
    private func getData(from url: String) {
        
        let task = URLSession.shared.dataTask(with: URL(string: url)!, completionHandler: {data, response, error in
            
            guard let data = data, error == nil else {
                print("something went wrong")
                return
            }
            
            var result: Response?
            do {
                result = try JSONDecoder().decode(Response.self, from: data)
            }
            catch {
                print("failed to convert \(error.localizedDescription)")
            }
            
            guard let json = result else {
                return
            }
            
            let sunrise = json.results.sunrise
        
            print(sunrise)
            
        })task.resume()
    }

}

struct Response: Codable {
    let results: MyResult
    let status: String
}

struct MyResult: Codable {
    let sunrise: String
    let sunset: String
    let solar_noon: String
    let day_length: String
    let civil_twilight_begin: String
    let civil_twilight_end: String
    let nautical_twilight_begin: String
    let nautical_twilight_end: String
    let astronomical_twilight_begin: String
    let astronomical_twilight_end: String
    
}

【问题讨论】:

    标签: swift xcode api uikit


    【解决方案1】:

    在主队列上分配,比如

    DispatchQueue.main.async { [weak self] in
       self?.sunrise1.stringValue = sunrise
    }
    

    【讨论】:

    • 非常感谢,这行得通。请问你哪里最好学 SwiftUI 和 XCode?是苹果官方文档还是有更好的来源。
    【解决方案2】:

    实际上,最好在您的func getData 中完成,所以当它完成工作时,您将在完成时更新您的标签。 作为参考,我可能会提出类似的建议:

      func getData(fromUrl url: String, completion: @escaping (String) -> ()) {
        let task = URLSession.shared.dataTask(with: URL(string: url)!, completionHandler: { data, response, error in
          guard let data = data, error == nil else {
            print("something went wrong")
            return
          }
          var result: Response?
          do {
            result = try JSONDecoder().decode(Response.self, from: data)
          }
          catch {
            print("failed to convert \(error.localizedDescription)")
          }
          guard let json = result else {
            return
          }
          let sunrise = json.results.sunrise
          completion(sunrise)
        })
        task.resume()
      }
    

    现在你可以调用你的方法,例如 viewDidLoad() 并像这样更新你的标签:

    self.getData(fromUrl: "") { sunrise in
      DispatchQueue.main.async { [weak self] in
         self?.sunrise1.stringValue = sunrise
      }
    }
    

    要获得更多信息,您可以了解completion block/handlers、带有完成的函数以及为什么我们必须在主线程中更新 UI。

    但是当我添加 return(sunrise) Xcode 显示错误:“意外 非空返回错误”。

    如果你想让你的函数返回一些东西,你必须在方法签名中声明它,例如:

    func itReturnInt() -> Int {
      return 1
    }
    

    会返回1,即Int,但如果你尝试返回其他类型,你会得到编译错误。

    【讨论】:

      猜你喜欢
      • 2020-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-15
      • 1970-01-01
      相关资源
      最近更新 更多