iOS Realm过滤关系列表中的对象

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS Realm过滤关系列表中的对象相关的知识,希望对你有一定的参考价值。

我有三个通过列表嵌套的对象,如下所示:

class Canteen: Object {

        dynamic var name: String?
        let lines = List<Line>()
}

class Line: Object {

        dynamic var name: String?
        let meals = List<Meal>()
}

class Meal: Object {

        dynamic var name: String?
        dynamic var vegan: Bool = false
}

获得所有线路和餐点的所有食堂都没有问题。我现在正在做的是:

let predicate = NSPredicate(format: "name == %@", selectedCanteenType.rawValue)
canteens =  realm.objects(Canteen).filter(predicate)

但现在我只需要素食主义者的饭菜。因此,我希望获得所有线路的选定食堂,但只有纯素食品。这是否可以在领域中筛选检索到的对象中的列表?

答案

Realm没有深层过滤视图的任何概念,所以你不能有Results<Canteen>将相关对象中包含的Lists限制为纯素餐。

你可以做几件类似的事情。您可以添加反关系属性,然后查询Meal对象:

class Canteen: Object {
    dynamic var name: String?
    let lines = List<Line>()
}

class Line: Object {
    dynamic var name: String?
    let meals = List<Meal>()
    let canteens = LinkingObjects(fromType: Canteen.self, property: "lines")
}

class Meal: Object {
    dynamic var name: String?
    dynamic var vegan: Bool = false
    let lines = LinkingObjects(fromType: Line.self, property: "meals")
}

let meals = realm.objects(Meal).filter("vegan = true AND ANY lines.canteens.name = %@", selectedCanteenType.rawValue)

(或者更确切地说,你将能够在Realm 0.102.1出局时;目前崩溃了)。

如果你只需要迭代吃饭但需要从食堂下来,你可以这样做:

let canteens = realm.objects(Canteen).filter("name = %@ AND ANY lines.meals.vegan = true", selectedCanteenType.rawValue)
for canteen in canteens {
    for line in canteen.lines.filter("ANY meals.vegan = true") {
        for meal in line.meals.filter("vegan = true") {
            // do something with your vegan meal
        }
    }
}

遗憾的是,由于需要为每个级别的引用重复过滤器,因此存在一些重复。

另一答案

试试这个:

let predicate = NSPredicate(format: "name == %@", "")
var canteens: [Canteen] = realm.objects(Canteen).filter(predicate).map { can in
    // Iterate through all the Canteens
    let lines: [Line] = can.lines.map { (line: Line) in
        // Iterate through all the lines in each canteene
        // Filter all the Meals that are NOT vegan
        let meals = line.meals.filter { $0.vegan == true }
        line.meals = List<Meal>(meals)
        return line
    }
    can.lines = List<Line>(lines)
    return can
}
另一答案

Realm允许它使用函数作为过滤参数。所以这是我目前正在使用的解决方案。

两个过滤功能:

func vegetarianFilter(_ meal: Meal) -> Bool {

        if showVegetarianOnly {
            if(meal.veg || meal.vegan){
                return true
            }

            return false
        }

        return true
}

func filterEmptyLines(_ line: Line) -> Bool {

       if(line.meals.filter(vegetarianFilter).count > 0){
           return true
       }

       return false
}

当用户选择showVegetarianOnly = true时,这些功能可以过滤所有非素食或素食的餐点。它还过滤掉所有没有剩饭的线(没有素食或素食)。

TableView最重要的功能:

    override func numberOfSections(in tableView: UITableView) -> Int {
            return canteenDay?.lines.filter(filterEmptyLines).count ?? 0
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return canteenDay?.lines.filter(filterEmptyLines)[section].meals.filter(vegetarianFilter).count ?? 0
    }

   override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = UITableViewCell()

        let meal = canteenDay!.lines.filter(filterEmptyLines)[indexPath.section].meals.filter(vegetarianFilter)[indexPath.row]

        cell.textLabel?.text = meal.meal

       return cell
    }

以上是关于iOS Realm过滤关系列表中的对象的主要内容,如果未能解决你的问题,请参考以下文章

使用 Swift 过滤 Realm 对象

如何从 SwiftUI 和 Realm 中另一个列表中的对象中添加和删除列表中的对象

过滤具有多对多关系的对象,检查它是不是包含列表中的至少一个元素

编辑片段中的列表视图对象

如何通过 NSDate 属性过滤 Realm 对象

iOS - 将元素附加到领域中的列表不会保留元素