LoginSignup
18
16

More than 3 years have passed since last update.

[Swift] お前らのNSFetchRequestの使い方は完全に間違えてる [CoreData]

Posted at

NSFetchRequestにGenericsが導入されてキャストの嵐から解放されて久しいですが、どうもGenericsの使い方が全く分かっていないサンプルコードがあふれかえっているようなので、ここで改めて正しいNSFetchRequestの使い方を紹介しておきます。

エンティティサンプル

エンティティは特に何でもよいのでごく単純な以下のものを使います。
エンティティ名はクラス名と同じです。

class Company: NSManagedObject {
    @NSManaged var name: String
}

悪い例

僕が怒り心頭の悪い例はこちらです。

func fetchAllCompanies() -> [Company] {
    let context: NSManagedObjectContext = ...

    let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Company")
    do {
        guard let companies = try context.fetch(request) as? [Company] else {
            fatalError("Can not cast fetch result.")
        }
        return companies
    }
    catch {
        print("Fetch error:", error)
        return []
    }
}

NSFetchRequestの型パラメータをNSFetchRequestResultとしています。
これが完全な誤りです。
使い方を誤っているために本来必要ない[Company]へのダウンキャストの必要性が発生しています。

正しい例

こちらが正しい使い方です。

func fetchAllCompanies() -> [Company] {
    let context: NSManagedObjectContext = ...

    let request = NSFetchRequest<Company>(entityName: "Company")
    do {
        return try context.fetch(request)
    }
    catch {
        print("Fetch error:", error)
        return []
    }
}

NSFetchRequestの型パラメータにCompanyを用いることで、NSManagedObjectContext#fetch(_:)の戻り値の型は[Company]に確定します。
ダウンキャストは不要なのです。

おわりに

某所でNSFetchRequest<NSFetchRequestResult>を使っているサンプルを発見してしまい、なんとなく検索してみると同様のサンプルがいまだに数多く残っていたので怒りに任せて書きました。
簡単にするための機構をあざ笑うかのようなこの所業はさすがに見逃せなく、煽りタイトルとさせていただきました。
僕はただ、正しい使い方を広めたかっただけです。
罵りは甘受します。

18
16
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
18
16