关系列表中的 iOS 领域过滤器对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37193959/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 09:03:51  来源:igfitidea点击:

iOS Realm Filter objects in a list of a relationship

iosswiftrealm

提问by Daniel Storch

I have three objects nested via lists like this:

我通过这样的列表嵌套了三个对象:

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
}

Getting all canteens with all the lines and meals is no problem. What im doing right now is this:

让所有食堂的所有线路和膳食都没有问题。我现在在做的是:

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

But now i only need the meals which are vegan. So im looking to get the selected canteen with all the lines, but only with meals which are vegan. Is this possible in realm, to filter lists in retrieved objects?

但现在我只需要素食餐。所以我希望得到所有线路的选定食堂,但只提供素食。这是否可以在领域中过滤检索到的对象中的列表?

回答by Thomas Goyne

Realm doesn't have any sort of concept of a deep-filtered view, so you can't have a Results<Canteen>which restricts the Lists contained in related objects to vegan meals.

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

There are several similar things which you can do. You could add inverse relationship properties, and then query Mealobjects instead:

你可以做一些类似的事情。您可以添加反向关系属性,然后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)

(Or rather, you will be able to once Realm 0.102.1 is out; currently this crashes).

(或者更确切地说,您将能够在 Realm 0.102.1 发布后;目前这会崩溃)。

If you just need to iterate over the meals but need to do so from the Canteen down, you could do:

如果您只需要遍历餐食但需要从食堂开始这样做,您可以这样做:

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
        }
    }
}

This unfortunately has some duplication due to needing to repeat the filter for each level of the references.

不幸的是,由于需要为参考的每个级别重复过滤器,因此存在一些重复。

回答by Dejan Skledar

Try this:

尝试这个:

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 { 
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
}
.vegan == true } line.meals = List<Meal>(meals) return line } can.lines = List<Line>(lines) return can }

回答by Daniel Storch

Realm allows it to use functions as parameter for the filtering. So this is my solution which im currently using.

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

The two filter functions:

两个过滤函数:

    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
    }

The functions filter all meals which are not vegetarian or vegan when the user has selected showVegetarianOnly = true. Also it filters all lines which than have no meal left (nothing is vegetarian or vegan).

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

Most important functions of the TableView:

TableView 最重要的功能:

##代码##