gpt4 book ai didi

swift - 是否可以通过引用而不是副本将数组分配给类属性?

转载 作者:搜寻专家 更新时间:2023-10-31 08:27:48 24 4
gpt4 key购买 nike

背景:

我设计了一个 TableViewDataSource 类,它提供了 UITableViewDataSourceUITableViewDelegate 的实现。您实例化 TableViewSection 对象,这些对象被传递给 TableViewDataSource,用于配置单元格、节标题、处理选择、行插入等。

TableViewSection 对象有一个名为 dataSource: [AnyObject]? 的属性,设置后用于计算该部分中的行数,并提供单元格配置 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更新数组,进而更新 TableView 。在 Swift 中,你不能通过引用传递数组。解决方法似乎是使用 NSMutableArray,但随之而来的是类型安全性的损失,以及在将对象从 Swift 来回转换为 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() 方法访问我的 API 服务,根据响应更新它的 collection 属性,并在RACSignalnext 事件(RACSignalReactive Cocoa 提供的类,实际上,除此之外)。

我找到了一种解决方法,它涉及在每次进行单个更新时或在批量更新后重新分配数据源。

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
}

此方法有效,但只是暂时的解决方法。随着 TableViewDataSource 的增长和变得越来越复杂,此方法变得越来越复杂,具有命令式的过程代码,这与我在编写该类时打算实现的目标相反。

问题

是否有任何解决方法可以坚持使用原生 Swift Array 来实现相当于通过引用传递 Foundation NSArrayNSMutableArray

奖励问题

有人可以为我提供一些类/结构设计技巧,以在纯 Swift 中实现预期目标吗?

最佳答案

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

所讨论的类可以非常轻量级 - 基本上,它只是作为一个薄包装器来携带数组,客户端直接通过类实例访问数组 - 或者,恰恰相反,您可以设计管理数组的类,即该类有意提供类似数组的 API,使客户端免受底层实现的影响。任何一种方法都可能是合适的;这两件事我当然都做过。

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

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

  • 在 Swift 中,我的 UITableViewController 持有对 UIDocument 对象 self.doc 的引用。该数组现在是一个 Swift 数组,位于它的“内部”,因此我可以将其称为 self.doc.people。但是,重写太多了!相反,我创建了一个计算变量属性 self.people 作为通往 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 中一样,一点也不麻烦。

关于swift - 是否可以通过引用而不是副本将数组分配给类属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25533122/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com