1

SwiftUI を使用して古い iOS ベースのプロジェクトの macOS ターゲットを作成しています。これは Core Data ドリブン アプリケーションであり、macOS ターゲットでは、主に Paul Hudson のブログで説明されているように、動的 @FetchRequest を使用して一般的な List を正常に実装しました。

私は主に、Apple のSwiftUI チュートリアルに従い、提供されているサンプル コードをコピーして、ターゲットを構築しました。

List以前に使用された条件付き if ステートメントは、3 つの UI コントロールに基づいて各 SwiftUI を積極的にフィルタリングしました。

を実行する 3 つの UI コントロールの画像

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

}
4

2 に答える 2

0

これは、述語の構成を別の方法で考えようとしたときに偶然見つけたハッキン​​グされたソリューションであるため、私の回答は不正な回答です。(私が書いた述語の構文を理解するという実際の問題についての注意深い考えを示すものではありません!)

したがって、この応答は私の元の質問には答えません - @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])
于 2020-06-12T11:59:33.540 に答える