【问题标题】:Translate a nested Conditional If Statement into a complex NSCompoundPredicate将嵌套的条件 If 语句转换为复杂的 NSCompoundPredicate
【发布时间】:2020-06-12 00:36:04
【问题描述】:

我正在使用 SwiftUI 为基于 iOS 的旧项目编写 macOS 目标。是一个核心数据驱动的应用程序,对于 macOS 目标,我已经使用动态 @FetchRequest 成功实现了通用列表,主要如 Paul Hudson 在他的 blog 中描述的那样。

我主要通过关注 Apple 的 SwiftUI Tutorials 并复制提供的示例代码来构建目标。

之前使用的条件 if 语句根据 3 个 UI 控件主动过滤每个 SwiftUI List

// PART 1
    if (!self.appData.showFavouritesOnly
        || fetchedEvent.isFavourite)
// PART 2
    && (self.searchText.count == 0
        || (fetchedEvent.eventName?.contains(self.searchText) == true))
// PART 3
    && (self.filter == .all
        || self.filter.name == fetchedEvent.eventCategory
        || (self.filter.category == .featured && fetchedEvent.isFeatured)) {

现在我有一个使用谓词的通用 @FetchRequest,我想将此条件 if 语句转换为 NSCompoundPredicate

我将包含整个初始化程序,以便您了解动态@FetchRequest 是如何构建的,但它是我需要帮助的谓词...

init(sortDescriptors: [NSSortDescriptor],
     searchKey: String,
     searchValue: String?,
     showFavourites: Bool,
     filterKey: String,
     filter: FilterType,
     @ViewBuilder content: @escaping (T) -> Content) {

    let entity = T.entity
    let predicateTrue = NSPredicate(value: true)
// PART 1
    let predicateFavourite = showFavourites == false ? predicateTrue : NSPredicate(format: "isFavourite == TRUE")
// PART 2
    let predicateSearch = searchValue?.count == 0 ? predicateTrue : NSPredicate(format: "%K CONTAINS[cd] %@", searchKey, searchValue!)

    // The initialiser works perfectly down to this point...then...
// PART 3
    let predicateFilterName = filter == .all ? predicateTrue : NSPredicate(format: "%K == %@", filterKey, filter.name as CVarArg)
    let predicateFilterFeature = filter.category == .featured ? NSPredicate(format: "isFeatured == TRUE") : predicateTrue

    let predicateOr = NSCompoundPredicate(orPredicateWithSubpredicates: [predicateFilterName, predicateFilterFeature])
    let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicateFavourite, predicateSearch, predicateOr])

    fetchRequest =
        FetchRequest<T>(entity: entity,
                        sortDescriptors: sortDescriptors,
                        predicate: predicate)

    self.content = content
}

第 3 部分中包含的代码部分工作。在FilterType.allFilterType.featured 之间切换会产生预期的变化,但是我正在努力为选择另一个类别的“其他”情况编写谓词——即——不是精选,而是.lakes.rivers.mountains

为了完整起见,我还包括了枚举 Category 和结构 FilterType...

enum Category: String, CaseIterable, Codable, Hashable {

    case featured = "Featured"
    case lakes = "Lakes"
    case rivers = "Rivers"
    case mountains = "Mountains"
}

struct FilterType: CaseIterable, Hashable, Identifiable {

    var name: String
    var category: Category?

    init(_ category: Category) {
        self.name = category.rawValue
        self.category = category
    }

    init(name: String) {
        self.name = name
        self.category = nil
    }

    static var all = FilterType(name: "All")

    static var allCases: [FilterType] {
        return [.all] + Category.allCases.map(FilterType.init)
    }

    var id: FilterType {
        return self
    }

}

【问题讨论】:

    标签: if-statement core-data swiftui swiftui-list nscompoundpredicate


    【解决方案1】:

    我认为问题出在这里:

     let predicateFilterFeature = filter.category == .featured ? NSPredicate(format: "isFeatured == TRUE") : predicateTrue
    

    如果过滤器是.lakes 等,那么这个子谓词将为真,当与predicateFilterName 进行或运算时会覆盖它。尝试返回 FALSE:

     let predicateFilterFeature = filter.category == .featured ? NSPredicate(format: "isFeatured == TRUE") : predicateFalse
    

    【讨论】:

    • 谢谢你这个作品......一个完美运作的简单解决方案。我花了几个小时来解决这个问题,应该停下来仔细考虑一下。
    【解决方案2】:

    我的答案是欺诈性的,因为这是我在尝试以不同方式构建谓词后偶然发现的一个被黑的解决方案。 (它没有表现出对理解我写的谓词语法的实际问题的任何仔细思考!)

    所以这个回复没有回答我原来的问题——@pbasdf 已经回答了——尽管这个回复达到了相同的结果。

    所以也许是替代解决方案?!?

    let predicateTrue = NSPredicate(value: true)
    
    let predicateFavourite = showFavourites == false ? predicateTrue : NSPredicate(format: "isFavourite == TRUE")
    
    let predicateSearch = searchValue?.count == 0 ? predicateTrue : NSPredicate(format: "%K CONTAINS[cd] %@", searchKey, searchValue!)
    
    let predicateFilterFeatured = NSPredicate(format: "isFeatured == TRUE")
    let predicateFilterName = NSPredicate(format: "%K == %@", filterKey, filter.name as CVarArg)
    let predicateFilterCategory = filter.category == .featured ? predicateFilterFeatured : predicateFilterName
    
    let predicateFilter = filter == .all ? predicateTrue : predicateFilterCategory
    
    let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicateFavourite, predicateSearch, predicateFilter])
    

    【讨论】:

      猜你喜欢
      • 2012-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-16
      • 1970-01-01
      • 1970-01-01
      • 2012-02-17
      • 1970-01-01
      相关资源
      最近更新 更多