Hig*_*asy 4 class-design foundation swift
背景:
我设计了TableViewDataSource
一个为UITableViewDataSource
和提供实现的类UITableViewDelegate
.您实例化TableViewSection
对象,这些对象将传递给TableViewDataSource
用于配置单元格,节标题,句柄选择,行插入等的对象.
该TableViewSection
对象具有一个名为的属性dataSource: [AnyObject]?
,该属性在设置时用于计算该部分中的行数,并为该单元配置块提供一个对象:
// 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
Run Code Online (Sandbox Code Playgroud)
我想做的是从我viewModel
到我的数组中分配对数组的引用tableSection.dataSource
,让我viewModel
更新数组,然后更新表视图.在Swift中,您不能通过引用传递数组.解决方法似乎是使用a 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)
})
}
}
Run Code Online (Sandbox Code Playgroud)
在refresh()
对方法viewModel
点击我的API服务,更新它collection
的响应特性,并提供了对结果next
的事件RACSignal
(RACSignal
是提供一类反应可可真的,除了点).
我找到了一种解决方法,包括每次进行单次更新时或批量更新后重新分配数据源.
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
}
Run Code Online (Sandbox Code Playgroud)
这种方法有效,但只能暂时作为解决方法.随着TableViewDataSource
增长并变得越来越复杂,这种方法变得越来越复杂,必要的程序代码,与我在编写类时要实现的目标相反.
题
是否有任何解决方法可以坚持使用本地Swift Array
来实现相当于通过基金会NSArray
或NSMutableArray
参考?
奖金问题
有人可以为我提供一些类/结构设计技巧,以实现纯Swift中的预期目标吗?
简单的解决方案是将数组包装在一个类中.类实例通过引用传递,因此问题得到了有效解决:通过对类实例的任何引用对数组的更改会影响数组,如通过对该类实例的每次引用所看到的那样.
有问题的类可以非常轻量级 - 基本上,它只是作为一个包装数组的瘦包装器,客户端通过类实例直接访问数组 - 或者恰恰相反,您可以将类设计为管理数组,即类故意呈现类似于数组的API,以保护客户端免受底层实现的影响.这两种方法都可能是合适的; 我当然都做到了.
这是第一种情况的例子.我的模型对象是属于UIDocument子类的数组.我的视图控制器是一个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
}
}
Run Code Online (Sandbox Code Playgroud)
嘿presto,问题解决了.每当我说出类似的话self.people.append(newPerson)
,我就会直接传递给UIDocument的模型对象,people
而我实际上是在追加它.因此,代码看起来和工作方式就像在Objective-C中一样,完全不用担心.
归档时间: |
|
查看次数: |
989 次 |
最近记录: |