Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use NSSet created from Core Data

I have the following core data model: enter image description here enter image description here

where Person to Codes is a one-to-many relationship.

I have a function which returns a Person record and if the code person.codes returns an NSSet of all the codes associated with that Person. The issue that I am having is how to use the NSSet.

person.codes.allObjects.first returns this data:

<Codes: 0x60000213cb40> (entity: Codes; id: 0xb978dbf34ddb849 <x-coredata://A2B634E4-E136-48E1-B2C5-82B6B68FBE44/Codes/p1> ; data: {
    code = 4LQ;
    number = 1;
    whosAccount = "0xb978dbf34ddb869 <x-coredata://A2B634E4-E136-48E1-B2C5-82B6B68FBE44/Person/p1>";
})

I thought if I made person.codes.allObjects.first of type Codes, I would be able to access the code and number elements but I get an error: error: value of type 'Any?' has no member 'number'

Also, how can I search this data set for a particular code or number.

I appreciate that this is proabably a simple question but have searched and read the documentation to no avail. I suspect that may base knowledge is not sufficient.

Update

I have a CoreDataHandler class which contains the following code:

class CoreDataHandler: NSObject {
    //static let sharedInstance = CoreDataHandler()

    private static func getContext() -> NSManagedObjectContext {
        let appDelegate = NSApplication.shared.delegate as! AppDelegate

        return appDelegate.persistentContainer.viewContext
    }

    static func fetchPerson() -> [Person]? {
        let context = getContext()

        do {
            let persons: [Person] = try context.fetch(Person.fetchRequest())
            return persons
        } catch {
            return nil
        }
    }

I can fetch a person using:

let row = personTableView.selectedRow
let person = CoreDataHandler.fetchPerson()?[row]
like image 230
pdoak Avatar asked Dec 24 '22 02:12

pdoak


2 Answers

Core Data supports widely native Swift types.

Declare codes as Set<Codes> in the Person class.

It's much more convenient than typeless NSSet.
You get a strong type and you can apply all native functions like filter, sort, etc. without type cast.

like image 161
vadian Avatar answered Dec 29 '22 12:12

vadian


let codes = person.codes as! Set<Code>

Once that is done you can access the properties. Searching can be done by filtering for instance

let filteredCodes = codes.filter({ $0.code == "XYZ" })

will return all objects that has the code "XYZ". Or to get only one you can use

let code = codes.first(where: {$0.id == 1})

which will return the first object that has id = 1

A simple example getting all Person objects that has a given code

func findWithCode(_ code: String) -> [Person] {
    guard let persons = CoreDataHandler.fetchPerson() else {
        return []
    }

    var result = [Person]()
    for person in persons {
        let codes = person.codes as! Set<Code>
        if codes.contains(where: { $0.code == code }) {
            result.append(person)
        }
    }

    return persons
}
like image 32
Joakim Danielson Avatar answered Dec 29 '22 11:12

Joakim Danielson