1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【SwiftUI × CoreData】NSPredicate を使って簡単に検索機能を実装する方法

1
Posted at

最近は復習ばかりしていて、なかなか新しい投稿ができていませんでした。
ですが改めてコードを見返している中で、
「CoreData って、実は検索がめちゃくちゃ簡単に作れる」
ということを再確認したので、この記事にまとめます。
今回は CoreData の “検索だけ” に特化した最小構成の方法 を紹介します。
CRUD や CoreData 導入の解説は省きます。
検索だけ取りたい人向けの記事です。

🔰 前提条件(CoreData の基本セットアップは済んでいる想定)
この時点で以下の準備ができていることを前提にしています:
CoreData(PersistenceController)が使える状態
Item という Entity がある
属性:
text(String)
createdAt(Date)
viewContext を ViewModel に渡せる構成
この記事では 検索フィルターの実装部分だけ を扱います。

🎯 やること
TextField の入力に応じて CoreData を検索
NSPredicate の CONTAINS[c] を使う
List にリアルタイムで絞り込み結果を表示
これだけで CoreData の検索は完成します。

📂 ListViewModel:検索ロジックの最小構成

import Foundation
import CoreData

class ListViewModel: ObservableObject {
    @Published var items: [Item] = []
    @Published var searchText = ""
    
    private let context: NSManagedObjectContext
    
    init(context: NSManagedObjectContext) {
        self.context = context
        fetchItems()
    }
    // 読み込み処理
    func fetchItems() {
        let request = NSFetchRequest<Item>(entityName: "Item")
        request.sortDescriptors = [NSSortDescriptor(key: "createdAt", ascending: false)]
        
        // 検索バーが空じゃなかったらpredicate実行
        if !searchText.isEmpty {
            request.predicate = NSPredicate(format: "text CONTAINS[c] %@", searchText)
        }
        
        do {
            // UIを更新 配列を新しいのに変更してる
            items = try context.fetch(request)
        } catch {
            print("❌ Fetch error: \(error.localizedDescription)")
        }
    }

📂 ListView:TextField の変更を検索へ反映

import SwiftUI
import CoreData

struct ListView: View {
    @StateObject var vm: ListViewModel
    
    init(context: NSManagedObjectContext) {
        _vm = StateObject(wrappedValue: ListViewModel(context: context))
    }
    
    var body: some View {
        NavigationStack {
            VStack {
                    TextField("検索", text: $vm.searchText)
                    .textFieldStyle(.roundedBorder)
                    .padding()
            }
            .onChange(of: vm.searchText) {
                vm.fetchItems()
            }

🔑 なぜこれで検索できるのか?
✔ searchText が変わる
→ .onChange が呼ばれる
→ fetchItems() 実行
→ NSPredicate が適用された結果を CoreData から取得
@Published items に代入
→ UI が自動で更新される
この一連の流れだけで検索が動きます。

🔍 NSPredicate よく使うパターン

"text CONTAINS[c] %@"       // 部分一致(大文字小文字無視)
"text BEGINSWITH[c] %@"     // 前方一致
"text ENDSWITH[c] %@"       // 後方一致
"isCompleted == true"       // Bool
"count >= %d"               // 数値比較
"createdAt >= %@"           // 日付比較

🎯 まとめ
CoreData の検索は NSPredicate を追加するだけ
CONTAINS[c] で部分一致検索ができる
TextField の onChange で簡単にリアルタイム検索
@Published 配列に新しい値を入れると UI が更新
ListView と ViewModel の 2 ファイルだけで完結できる
検索機能は CoreData と相性が良く、
ToDo・メモ・習慣アプリなどリスト系アプリで大活躍します。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?