使不可变函数参数可变

时间:2017-04-23 14:20:07

标签: arrays swift immutability mutable

我有一个接收数组的方法,在该方法中我想将一些对象附加到该数组。由于Swifts对函数的参数是不可变的,我无法这样做。至关重要的是,我保持对该数组的相同引用,因为该数组将用于表视图中以显示数据。我的代码如下:

class func loadData(tableView: UITableView, results: [LocationInfo]){
    print("\n Data fetch started \n")
    let root = FIRDatabase.database().reference()
    let locationSummary = root.child("LocSummary")

    locationSummary.observeSingleEvent(of: .value,with: { (snapshot) in
        for item in snapshot.children{
            let locationInfo = LocationInfo(snapshot: item as! FIRDataSnapshot)
            results.append(locationInfo) // ERROR IS WITH THIS

        }
        DispatchQueue.main.async {
            print("\n data fetch completed \n ")
            tableView.reloadData()
            print("After on completion method \(results.count)")

        }
    })
}

如何在保持相同参考的同时将数据附加到此数组。

3 个答案:

答案 0 :(得分:2)

您可以通过将该数组声明为属性(并删除函数的class修饰符)来使该数组可用于所有函数,或者您可以将函数的参数定义为 in -out参数。通过在参数类型之前添加inout关键字,可以通过保持对传递的数组的引用来使参数可变。

尽管如此,我建议你把你的阵列变成一个属性 - 只是因为它更容易,而且在我看来,它更易于维护。

答案 1 :(得分:1)

  

至关重要的是,我要对该数组保持相同的引用

这种欲望是不连贯的。请考虑:locationSummary.observingSingleEvent接受一个将以异步方式执行的函数,即在某个未知未来时间。但这就是你想通过"相同的参考"来改变这个数组的地方。很遗憾地说,你会在未来某个未知的时间回来,继续保持对一些持久性变量的引用,并且,噗,突然之间,改变它。

因此,此[Location] 无法成为loadData的参数。

我还建议问问自己为什么这需要是一个函数。这意味着没有实例,所以无论如何都没有有意义的地方存储持久变量!

如果这是一个普通的实例方法(即删除class),那么问题就很容易解决:让你的[Location]成为一个实例属性,现在你可以从异步中引用它功能。小心(1)只在主线程上获取和设置它,以及(2)不要意外地保留self(你会想要[weak self] in)来使自己陷入保留周期。 / p>

答案 2 :(得分:0)

第一点:你不能保持对该阵列的相同引用"因为那不是对数组的引用。它是一个临时值,仅存在于方法结束之前。

我看到你有一张桌子视图。为了使LocationInfo对象保持在表视图中显示,您需要将results分配(即复制)到参数中,然后可以使用该参数填充表视图。这个简单的东西可能会起作用......这取决于代码的其余部分是什么样的。

var tableViewData: [LocationInfo] = []

// note, this isn't a class func anymore.
func loadData(results: [LocationInfo]){
    print("\n Data fetch started \n")
    tableViewData = results
    let root = FIRDatabase.database().reference()
    let locationSummary = root.child("LocSummary")

    locationSummary.observeSingleEvent(of: .value,with: { (snapshot) in
        for item in snapshot.children{
            let locationInfo = LocationInfo(snapshot: item as! FIRDataSnapshot)
            tableViewData.append(locationInfo)

        }
        DispatchQueue.main.async {
            print("\n data fetch completed \n ")
            self.tableView.reloadData()
            print("After on completion method \(results.count)")

        }
    })
}