首页 > 解决方案 > 通过函数传递时不能修改对象数组?

问题描述

我创建了一个名为 Weather 的自定义类并声明了一个 Weather 对象数组。

import Foundation

class Weather {
    var cityName:String
    var temperature:Double
    var temperatureMax:Double
    var temperatureMin:Double

    init(cityName: String, temperature: Double, temperatureMax: Double, temperatureMin: Double) {

        self.cityName = cityName
        self.temperature = temperature
        self.temperatureMax = temperatureMax
        self.temperatureMin = temperatureMin

    }
}

import UIKit
import SwiftyJSON

class ViewController: UIViewController {
    @IBOutlet weak var myLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        var weatherArrays = [Weather]()
        findLocation(zipCode: "11210", weatherArrays: weatherArrays)
        print(weatherArrays[0].cityName)
    }

    func findLocation(zipCode: String, weatherArrays: [Weather])
    {
        let zip = zipCode
        let appID = "245360e32e91a426865d3ab8daab5bf3"
        let urlString = "http://api.openweathermap.org/data/2.5/weather?zip=\(zip)&appid=\(appID)&units=imperial"
        let request = URLRequest(url: URL(string: urlString)!)
        URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
            do
            {
                let json = try JSONSerialization.jsonObject(with: data!) as! NSDictionary
                let main = json["main"] as! [String:Any]
                let temp = main["temp"]! as! Double
                let name = json["name"]! as! String
                let tempMax = main["temp_max"]! as! Double
                let tempMin = main["temp_min"]! as! Double
                weatherArrays.append(Weather(cityName: name, temperature: temp, temperatureMax: tempMax, temperatureMin: tempMin))
            }
            catch
            {
                print("Error")
            }

            }.resume()
    }

}

我将数组传递给一个函数,并将这些值附加到 weatherArrays 参数。但是,当我编译时出现错误,“不能对不可变值使用变异成员:'weatherArrays' 是一个 'let' 常量。”

Weather 类最初是一个结构,但我遇到了同样的错误,我阅读并发现结构值不能在函数中编辑,因为它是按值传递的。我将结构更改为一个类,但我仍然遇到同样的错误?当我将weatherArrays 声明为var 时,为什么它说“'weatherArrays' 是'let' 常量”?

标签: swiftclassstructconstants

解决方案


这是您的代码的更好方法

import UIKit
import SwiftyJSON

struct Weather {
    let cityName:String
    let temperature:Double
    let temperatureMax:Double
    let temperatureMin:Double
}
class ViewController: UIViewController {

    @IBOutlet weak var myLabel: UILabel!

    var array = [Weather]()
    let appID = "245360e32e91a426865d3ab8daab5bf3"

    override func viewDidLoad() {
        super.viewDidLoad()

        findLocation(zipCode: "11210"){ array in
            guard let array = array else {
                print("Error")
                return
            }
            print(array.first?.cityName ?? "no city name found")
        }

    }

    func buildUrl(queryItems: [URLQueryItem]) -> URL?{
        var components = URLComponents()
        components.scheme = "http"
        components.host = "api.openweathermap.org"
        components.path = "/data/2.5/weather"
        components.queryItems = queryItems
        return components.url
    }

    func findLocation(zipCode: String, completionHandler: @escaping (_ array: [Weather]?) -> ()){

        guard let url = buildUrl(queryItems: [URLQueryItem(name: "zip", value: zipCode), URLQueryItem(name: "appID", value: appID), URLQueryItem(name: "units", value: "imperial")]) else {
            print("Error in building url")
            return
        }

        let request = URLRequest(url: url)
        URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
            guard let data = data else {
                print(error?.localizedDescription ?? "")
                completionHandler(nil)
                return
            }
            do{
                var array = [Weather]()
                let json = try JSON(data: data)
                if json["cod"].intValue == 200{
                    let main = json["main"]
                    let temp = main["temp"].doubleValue
                    let name = json["name"].stringValue
                    let tempMax = main["temp_max"].doubleValue
                    let tempMin = main["temp_min"].doubleValue
                    array.append(Weather(cityName: name, temperature: temp, temperatureMax: tempMax, temperatureMin: tempMin))
                    completionHandler(array)
                }else{
                    completionHandler(nil)
                }

            } catch let error{
                print(error)
            }
            }.resume()
    }

}

模型用struct,不用写init方法

当您知道数据不会被更改时,使用 let 而不是 var

不要使用 NSDictionary。

您在调用函数后立即编写了 print 语句,因为只有在调用服务器完成后才会填充数组。所以我使用了完成处理程序

我看到您已经安装了 SwiftyJSON,但您实际上并没有使用它的好处。看解析部分。

关于你得到的错误是因为 Swift 是按值传递的,即当你传递数组对象时,你实际上传递的是它的副本而不是实际的数组。如果你想修改同一个数组,你需要我们inout。可以找到一个很棒的教程

编辑:正如@rmaddy 所建议的,通过返回一个新数组来使代码更安全。请参阅他的评论以获取更多信息。


推荐阅读