【问题标题】:iOS Realm Filter objects in a list of a relationshipiOS 领域过滤关系列表中的对象
【发布时间】:2016-09-08 16:53:19
【问题描述】:

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

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)

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

【问题讨论】:

    标签: ios swift realm


    【解决方案1】:

    Realm 没有任何深度过滤视图的概念,因此您不能拥有 Results&lt;Canteen&gt;,它将相关对象中包含的 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
            }
        }
    }
    

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

    【讨论】:

    • 谢谢,我最终过滤了 tableview 中的饭菜,就像你剪下的第二个代码显示的那样
    • 这让我省了很多麻烦。你得到一个赞成票:)
    【解决方案2】:

    试试这个:

    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
    }
    

    【讨论】:

    • 这在某种程度上可行,但是否有可能获得 var canteens: Results!而不是 [Canteen] 的新列表?
    • 当然,就像 let listCanteens = List(canteens)
    • Results 这是我需要的类型。这就是我在不使用.map 的情况下得到的。是否有另一种方法可以在不迭代的情况下实现这一目标?像子查询什么的?
    • map 并不是真正的“迭代”槽数组。检查此链接以了解有关map 的更多信息:sketchytech.blogspot.si/2015/06/…
    【解决方案3】:

    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
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多