是否可以通过引用而不是副本将数组分配给类属性? [英] Is it possible to assign an array to a class property by reference rather than a copy?

查看:75
本文介绍了是否可以通过引用而不是副本将数组分配给类属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景:

我设计了一个 TableViewDataSource 类,该类为 UITableViewDataSource UITableViewDelegate 。实例化 TableViewSection 对象,这些对象将传递到 TableViewDataSource ,用于配置单元格,节标题,句柄选择,行插入等。

I designed a TableViewDataSource class that provides an implementation for UITableViewDataSource and UITableViewDelegate. You instantiate TableViewSection objects, which are passed to the TableViewDataSource which are used to configure cells, section headers, handle selection, row insertion, etc.

TableViewSection 对象具有名为 dataSource的属性:[AnyObject ]?,设置后将用于计算该节中的行数,并为单元格配置块提供一个对象:

The TableViewSection object has a property called dataSource: [AnyObject]?, which, when set, is used to calculate the number of rows in the section, and provide an object for the cell configuration block:

// get the section, dequeue a cell for that section, retrieve the item from the dataSource
// ...
tableSection.cellConfigurationBlock?(cell: AnyObject, item: AnyObject?, indexPath: NSIndexPath)
return cell

我想要的是想要做的是从我的 viewModel 到我的 tableSection.dataSource 分配对数组的引用,使我的 viewModel 更新数组,然后更新表视图。在Swift中,您不能通过引用传递数组。解决方法似乎是使用 NSMutableArray ,但是随之而来的是类型安全性的损失和更大的认知负荷,同时将对象从Swift到来回地转换为Foundation。

What I'd like to do is assign a reference to an array from my viewModel to my tableSection.dataSource, having my viewModel update the array, in turn updating the table view. In Swift, you cannot pass an array by reference. The workaround seems to be to use an NSMutableArray, but with that comes a loss of type safety, and greater cognitive load while translating objects back and forth from Swift to Foundation.

工作示例:

let kCellIdentifier = "SomeCellIdentifier"
class MyViewController: UITableViewController {
    // Property declarations
    @IBOutlet var tableDataSource: TableViewDataSource!

    var viewModel: MyViewControllerViewModel = MyViewControllerViewModel()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.setupTableView()
        self.refresh()
    }

    func setupTableView() {
        var tableSection = TableViewSection(cellIdentifier: kCellIdentifier)
        tableSection.dataSource = self.viewModel.collection
        // tableSection configuration
        // ...

        self.tableDataSource.addSection(tableSection)
    }

    func refresh() {
        self.viewModel
            .refresh()
            .subscribeNext({ result in
                self.tableView.reloadData()
            }, error: { error in
                self.logger.error(error.localizedDescription)
            })
    }
}

viewModel 上的 refresh()方法命中我的A PI服务,在响应时更新它的 collection 属性,并在<$ c $的 next 事件中提供结果c> RACSignal ( RACSignal 是由反应性可可粉,实际上,除了要点外。)

The refresh() method on the viewModel hits my API service, updates it's collection property on response, and provides the result on the next event of an RACSignal (RACSignal is a class provided by Reactive Cocoa and really, besides the point).

我找到了一种解决方法,该方法涉及在每次更新时重新分配数据源

I've found one workaround, which involves reassigning the data source each time a single update is made, or after a batch update.

func refresh() {
    self.viewModel
        .refresh()
        .subscribeNext({ result in
            self.updateDataSource()
            self.tableView.reloadData()
        }, error: { error in
            self.logger.error(error.localizedDescription)
        })
}

func updateDataSource() {
    self.tableDataSource.tableSectionForIndex(0)?.dataSource = viewModel.collection
}

此方法有效,b ut只是暂时的解决方法。随着 TableViewDataSource 的增长和变得越来越复杂,此方法使用命令性的过程性代码变得越来越复杂,这与我在编写类时要实现的目标相反。

This approach works, but only temporarily as a workaround. As a TableViewDataSource grows and becomes more complex, this method becomes increasingly more complex with imperative, procedural code, the opposite of what I set out to achieve when writing the class.

问题

是否有任何解决方法可以坚持使用本机Swift Array 的效果等同于通过引用传递基础 NSArray NSMutableArray

Is there any workaround to stick to native Swift Array's to achieve the equivalent of passing a Foundation NSArray or NSMutableArray by reference?

奖金问题

有人可以为我提供一些类/结构设计吗?

Can someone provide me with some class/struct design tips to accomplish the desired goal in pure Swift?

推荐答案

简单的解决方案是将数组包装在一个类中。类实例通过引用传递,因此问题得以有效解决:通过任何对类实例的引用对数组的更改会影响数组,如通过每个引用看到的那样类实例。

The simple solution is to wrap the array in a class. The class instance is passed by reference so the problem is effectively solved: a change to the array through any reference to the class instance affects the array as seen through every reference to that class instance.

所讨论的类非常轻巧-基本上,它只是用作将数组与之一起携带的薄包装,并且客户端可以访问该数组直接通过类实例-或相反,您可以将类设计为 management ,即,该类故意提供了类似于数组的API,可将客户端与底层实现隔离。两种方法都可能合适;我当然都做过。

The class in question can be extremely lightweight - basically, it just serves as a thin wrapper that carries the array along with it, and a client accesses the array directly through the class instance - or, just the opposite, you can design the class to manage the array, i.e. the class deliberately presents an array-like API that shields clients from the underlying implementation. Either approach might be appropriate; I've certainly done both.

这里是第一种情况的例子。我的模型对象是属于UIDocument子类的数组。我的视图控制器是UITableViewController。用户将要在表中查看,添加和编辑模型实体。因此,UITableViewController需要访问UIDocument的数组(恰好称为 people )。

Here's an example of the first kind of situation. My model object is an array belonging to a UIDocument subclass. My view controller is a UITableViewController. The user is going to view, add, and edit model entities in the table. Thus, the UITableViewController needs access to the UIDocument's array (which happens to be called people).


  • 在Objective-C中,我的UITableViewController只是持有对数组 self.people 的引用,它是一个NSMutableArray。这只是一个指针,因此对 self.people 的更改也就是对UIDocument的 people 的更改-它们是一个

  • In Objective-C, my UITableViewController simply held a reference to the array, self.people, which was an NSMutableArray. This was just a pointer, so changes to self.people were also changes to the UIDocument's people - they are one and the same object.

在Swift中,我的UITableViewController持有对UIDocument对象 self.doc 。该数组现在是Swift数组,位于它的内部,因此我可以将其称为 self.doc.people 。但是,这太重写了!相反,我创建了一个计算所得的变量属性 self.people ,该属性充当 self.doc.people 的网关:

In Swift, my UITableViewController holds a reference to the UIDocument object, self.doc. The array, which is now a Swift array, is "inside" it, so I can refer to it as self.doc.people. However, that's too much rewriting! Instead, I've created a calculated variable property self.people which acts as a gateway to self.doc.people:

var doc : PeopleDocument!
var people : [Person] { // front end for the document's model object
    get {
        return self.doc.people
    }
    set (val) {
        self.doc.people = val
    }
}

嘿,我很高兴,问题解决了。每当我说诸如 self.people.append(newPerson)之类的内容时,我都会直接传递到UIDocument的模型对象 people 我实际上是在补充。因此,该代码的外观和工作方式与在Objective-C中一样,完全没有大惊小怪。

Hey presto, problem solved. Whenever I say something like self.people.append(newPerson), I'm passed right through to the UIDocument's model object people and I'm actually appending to that. The code thus looks and works just like it did in Objective-C, with no fuss at all.

这篇关于是否可以通过引用而不是副本将数组分配给类属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆