NEW: Start my new Ultimate Portfolio App course with a free Hacking with Swift+ trial! >>

SOLVED: How would I manually check that an attribute being saved to Core Data is unique?

Forums > SwiftUI

In "100 Days Of SwiftUI" and "SwiftUI by Example" and even some newer Hacking With SwiftUI videos, Paul provides a nice and easy way to make sure something you are trying to save in Core Data is unique... simply select the entity in the .xcdatamodeld, bring up the inspector, click + in the Constraints section and then name the item that is created after the attribute you want to be unique. Great! Awesome! Simple! I love it!!!

Just one issue... if you are hosting Core Data in Cloud Kit it hates it and it will crash and complains that you can't use such constraints with Cloud Kit. So I'm assuming that you just have to check manually with code instead prior to trying to save, but I'm not quite sure how. I know the string I'm trying to add, but I'm not really sure how to check that against the attribute in the Core Data entity that I need to be unique. Any thoughts?


I thought maybe I could do something like this based on the information in "How to filter Core Data fetch requests using a predicate", but Xcode informs me that "Property wrappers are not yet supported on local properties"

    private func checkItemExists(item: String) -> Bool {
            entity: Category.entity(),
            sortDescriptors: [
                NSSortDescriptor(keyPath: \, ascending: true),
            predicate: NSPredicate(format: "name == %@", item)
        let results: FetchedResults<Category>
        return results.count > 0


At the top of my view I'm already doing a @FetchRequest.

@Environment(\.managedObjectContext) private var viewContext

        sortDescriptors: [NSSortDescriptor(keyPath: \, ascending: true)],
        animation: .default
    private var labels: FetchedResults<Category>

If I can't use a FetchRequest later in a function as I mentioned in the previous post, is there something I could do with my labels var to see if it matches my string in .name? I suppose I could loop through that with a ForEach like I do to populate my list although I'm not sure how efficient that would be.


Looks like I had the right idea with trying to use NSPredicate, but the wrong syntax. After some digging around online I found that I could write my checkItemExists (now calling it itemExists) function like this (where item is my @State private var tied to my text field and viewContext is my managedObjectContext instance):

    private func itemExists(_ item: String) -> Bool {
        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Category")
        fetchRequest.predicate = NSPredicate(format: "name == %@", item)
        let results = try! viewContext.fetch(fetchRequest)
        return results.count > 0

Seems to be working, but if I got something wrong in that or there is a better way with SwiftUI, please let me know.


Instead of performing a fetch and counting the results, just use the count(for:) method:

    private func itemExists(_ item: String) -> Bool {
        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Category")
        fetchRequest.predicate = NSPredicate(format: "name == %@", item)
        return ((try? viewContext.count(for: fetchRequest)) ?? 0) > 0


Hacking with Swift is sponsored by Instabug

SPONSORED Catch bugs as soon as they happen and know exactly why a crash occurred. Instabug's SDK grabs all the logs they need to fix bugs, crashes and performance issues in minutes instead of days. Get screenshots, device details, network logs, repro steps, and tons of other critical insights needed to resolve issues and prioritize product backlogs straight from your dashboard. It only takes a minute to integrate!

Get started now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

Unknown user

You are not logged in

Log in or create account

Link copied to your pasteboard.