我尝试为realm结果创建通用的UITableView dataSource类,但是当我尝试发送不同的realmResults时 结果片剂;<>对象<>>在示例结果上我收到此错误消息:
无法转换类型'结果''项目'>'预期的元素类型'结果'对象''
class RealmResultsTableViewDataSource: TableViewDataSource {
var realmResults:[Results<Object>]
var notificationTokens: [NotificationToken] = []
init(tableView: UITableView, realmResults: [Results<Object>], configCell: @escaping TableViewConfigCellBlock, canEdit: TableViewCanEditCellBlock?, canMove: TableViewCanMoveRowBlock?, commitEditing: TableViewCommitEditingStyleBlock?) {
self.realmResults = realmResults
super.init(tableView: tableView, dataSource: [], configCell: configCell, canEdit: canEdit, canMove: canMove, commitEditing: commitEditing)
addTokens(for: realmResults)
}
deinit {
for token in notificationTokens {
token.stop()
}
}
override var sections: Int{
get { return realmResults.count }
}
override func numberOfRows(section: Int) -> Int {
return realmResults[section].count
}
// MARK: Add tokens
func addTokens(for results: [Results<Object>]) {
for result in results {
let notificationToken = result.addNotificationBlock { [weak self] (changes: RealmCollectionChange) in
guard let tableView = self?.tableView else { return }
switch changes {
case .initial:
// Results are now populated and can be accessed without blocking the UI
tableView.reloadData()
break
case .update(_, let deletions, let insertions, let modifications):
// Query results have changed, so apply them to the UITableView
tableView.beginUpdates()
tableView.insertRows(at: insertions.map({ IndexPath(row: $0, section: 0) }),
with: .automatic)
tableView.deleteRows(at: deletions.map({ IndexPath(row: $0, section: 0)}),
with: .automatic)
tableView.reloadRows(at: modifications.map({ IndexPath(row: $0, section: 0) }),
with: .automatic)
tableView.endUpdates()
break
case .error(let error):
// An error occurred while opening the Realm file on the background worker thread
fatalError("\(error)")
break
}
}
notificationTokens.append(notificationToken)
}
}
override func dataSourceObject(on indexPath: IndexPath) -> Any {
return realmResults[indexPath.section][indexPath.row]
}
}
和
让领域=试试!境界()
let result = realm.objects(Project.self).filter("id < 10").sorted(byKeyPath: "id", ascending: true)
tableViewDataSource = RealmResultsTableViewDataSource(tableView: tableView, realmResults: [result], configCell: { (tableView, indexPath, object) -> UITableViewCell in
let cell = tableView.dequeueReusableCell(withIdentifier:ProjectListTableViewCell.cellIdentifier , for: indexPath)
return cell
}, canEdit: nil, canMove: nil, commitEditing: nil)
import RealmSwift
class Project: Object {
dynamic var id: Int = 0
dynamic var name: String = ""
}
解决方案:
class RealmResultsTableViewDataSource<T: Object>: TableViewDataSource {
var realmResults:Results<T>
var notificationTokens: [NotificationToken] = []
init(tableView: UITableView, realmResults: Results<T>, configCell: @escaping TableViewConfigCellBlock, canEdit: TableViewCanEditCellBlock?, canMove: TableViewCanMoveRowBlock?, commitEditing: TableViewCommitEditingStyleBlock?) {
self.realmResults = realmResults
super.init(tableView: tableView, dataSource: [], configCell: configCell, canEdit: canEdit, canMove: canMove, commitEditing: commitEditing)
addTokens(for: self.realmResults)
}
deinit {
for token in notificationTokens {
token.stop()
}
}
override var sections: Int{
get{
return 1
}
}
override func numberOfRows(section: Int) -> Int {
return realmResults.count
}
// MARK: Add tokens
func addTokens(for results: Results<T>) {
let notificationToken = results.addNotificationBlock { [weak self] (changes: RealmCollectionChange) in
guard let tableView = self?.tableView else { return }
guard tableView.dataSource === self else { return }
switch changes {
case .initial:
// Results are now populated and can be accessed without blocking the UI
tableView.reloadData()
break
case .update(_, let deletions, let insertions, let modifications):
// Query results have changed, so apply them to the UITableView
tableView.beginUpdates()
tableView.insertRows(at: insertions.map({ IndexPath(row: $0, section: 0) }),
with: .automatic)
tableView.deleteRows(at: deletions.map({ IndexPath(row: $0, section: 0)}),
with: .automatic)
tableView.reloadRows(at: modifications.map({ IndexPath(row: $0, section: 0) }),
with: .automatic)
tableView.endUpdates()
break
case .error(let error):
// An error occurred while opening the Realm file on the background worker thread
fatalError("\(error)")
break
}
}
notificationTokens.append(notificationToken)
}
override func dataSourceObject(on indexPath: IndexPath) -> Any {
return realmResults[indexPath.row]
}
override func removeObject(indexPath: IndexPath) {
// assertionFailure("you can use ramoveObject int \(String(describing: self))")
}
}
答案 0 :(得分:1)
AFAIK,Realm Swift还不支持多态性。
目前的解决方案是使用组合而不是继承。 关于它有很多好的论据(Gang of Four和Joshua 布洛赫提到了这种方法的一些着名支持者。)
另一方面,我们正考虑允许继承,但它 不允许查询。例如:动物由两个延伸 狗,猫和鸭。您将无法使用for查询Animals 腿和所有的狗和猫,但不是鸭子。我们觉得这会是 这是一种非常严重的行为,但却渴望倾听更多意见。
这里讨论(这里讨论产品的java版本,所以它只是你的起点......):https://github.com/realm/realm-java/issues/761
最简单的解决方案[但如果你需要将这些方法与Object的其他子类重用]可能不是最好的解决方案 带有“项目”的“对象”