UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

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?

2      

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 {
        @FetchRequest(
            entity: Category.entity(),
            sortDescriptors: [
                NSSortDescriptor(keyPath: \Category.name, ascending: true),
            ],
            predicate: NSPredicate(format: "name == %@", item)
        )
        let results: FetchedResults<Category>
        return results.count > 0
    }

2      

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

@Environment(\.managedObjectContext) private var viewContext

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Category.name, 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.

2      

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.

2      

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
    }

3      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

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

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

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.