您知道为什么此过滤器无法正常工作吗?
for item in activeItems {
print("item.product: \(item.product), \(item.spaceRequired)")
}
返回
item.product: nil, 40.0
过滤产品为零的地方
let f1 = activeItems.filter{$0.product != nil}
print("f1: \(f1)")
print("f1.count: \(f1.count)")
返回计数为零,但数组似乎仍然包含一个项目
f1: LazyFilterSequence<Results<AssortmentItem>>(_base: Results<AssortmentItem> <0x109ce2c90> (
[0] AssortmentItem {
...
f1.count: 0
然后过滤并映射 spaceRequired
let f11 = f1.filter{$0.product!.isProduct == true}.map({$0.spaceRequired})
print("f11: \(f11)")
返回具有单个项目的相同数组
f11: LazyMapSequence<LazyFilterSequence<Results<AssortmentItem>>, Double>(_base: Swift.LazyFilterSequence<RealmSwift.Results<Merchandise_Manager.AssortmentItem>>(_base: Results<AssortmentItem> <0x109ce2c90> (
[0] AssortmentItem {
然后尝试减少崩溃
let w = f11.reduce(0,+)
这似乎可以解决问题
let width = Array(activeItems.filter{$0.product != nil}).filter{$0.product!.isProduct == true}.map({$0.spaceRequired}).reduce(0,+)
这是 Swift 5 或 Realm 中的错误吗?
编辑:看起来这是 Realm 处理事物时的一个错误。
下面需要澄清的是一组更完整的 Realm 对象。
import Foundation
import RealmSwift
let activeDate: NSDate = Date() as NSDate
let defaultWidth: Double = 40.0
class MyObject: Object {
@objc dynamic var number: Int = 0
@objc dynamic var name: String?
let items = List<ChildObject>()
}
extension MyObject {
var activeItems: Results<ChildObject> {
let activeDate = activeDate // Some globally defined value
let active = items.filter("startDate <= %@ && (endDate >= %@ || endDate == nil)", activeDate, activeDate).sorted(byKeyPath: "number")
return active
}
/// Works Correctly
var totalWidth: Double {
let width = Array(activeItems.filter{$0.product != nil}).filter{$0.product!.isProduct == true}.map({$0.spaceRequired}).reduce(0,+)
let width2 = Array(activeItems.filter{$0.product == nil}.map({$0.spaceRequired})).reduce(0,+)
return width+width2
}
/// Crashes
var totalWidth: Double {
let width = activeItems.filter{$0.product != nil}.filter{$0.product!.isProduct == true}.map({$0.spaceRequired}).reduce(0,+)
let width2 = activeItems.filter{$0.product == nil}.map({$0.spaceRequired}).reduce(0,+)
return width+width2
}
}
class ChildObject: Object {
@objc dynamic var parent: MyObject?
@objc dynamic var number: Int = 0
@objc dynamic var product: Product?
@objc dynamic var name: String?
@objc dynamic var spaceRequired: Double = 40.0
@objc dynamic var startDate: NSDate?
@objc dynamic var endDate: NSDate?
}
extension ChildObject {
var spaceRequired: Double {
if let p = product {
return p.width
} else {
return defaultWidth
}
}
}
class Product: Object {
@objc dynamic var isProduct: Bool = false
@objc dynamic var width: Double = 30.0
}
最佳答案
这里存在一些问题,但主要问题是 Realm 结果是实时更新的;而您可以使用 Swifty 过滤数据
let f1 = activeItems.filter{$0.product != nil}
它将给出间歇性的结果,因为 Realm 不知道哪些项目被过滤或未被过滤,因为 .filter { 不是 Realm 函数,并且 Realm 不知道在结果中更新什么。
您通常应该使用内置的 Realm 过滤机制
let results = realm.objects(ItemClass.self).filter("product != nil")
这些结果将实时更新 - 如果对象离开过滤器参数,结果将随之而来。如果对象与过滤器匹配,结果也会更新。
我相信这个Github issue #2138提供了有关该问题的更多信息。
如果您绝对需要静态数据,那么我建议扩展 Results 类以返回数组;像这样
extension Results {
func toArray() -> [Element] {
return compactMap { $0 }
}
}
请记住,这将使用更多内存,因为 Realm 对象是延迟加载的,而数组则不是。
编辑:
问题中有一些附加信息,因此我制作了一个简单的示例来尝试复制该问题。有一个 HouseClass 对象,其中包含 RoomClass 对象列表,然后扩展 HouseClass 以返回其列表中所有房间的总宽度。
class RoomClass: Object {
@objc dynamic var room_name = ""
@objc dynamic var width = 0
@objc dynamic var length = 0
@objc dynamic var belongs_to_house: HouseClass!
}
class HouseClass: Object {
@objc dynamic var house_id = NSUUID().uuidString
@objc dynamic var house_name = ""
let rooms = List<RoomClass>()
override static func primaryKey() -> String? {
return "house_id"
}
}
extension HouseClass {
var totalWidth: Int {
let width = Array(rooms).map {$0.width}.reduce(0,+)
return width
}
var anotherTotalWidth: Int {
let width = rooms.map {$0.width}.reduce(0,+)
return width
}
}
然后是获取所有房屋并根据两个不同函数输出其房间宽度的代码(请参阅 HouseClass 扩展)
let houseResults = realm.objects(HouseClass.self)
for house in houseResults {
let w0 = house.totalWidth
print(w0)
let w1 = house.anotherTotalWidth
print(w1)
}
我添加了 100 个房屋,每个房屋有 3 个房间,并多次运行上述代码,没有崩溃。
关于swift - Filter Realm Results 数组返回应过滤的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55513645/