0

I would like to create a function that would handle any type of object which have overriden init functions. As far I've got working with only overriden init function but if i want to do smth else with these objects every time i have to write extra code with some logic parts. To avoid that and makes code clean i have to make generic functions witch going to have as an argument T.Type.

This is my sample code which shows working parts :

import Foundation
import CoreData


extension Sample {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Sample> {
        return NSFetchRequest<Sample>(entityName: "Sample");
    }

    @NSManaged public var smth: String
    @NSManaged public var smth1: Double

    convenience init(smth: String, smth1: Double, insertIntoManagedObjectContext _context: NSManagedObjectContext!) {
        let _enitity = NSEntityDescription.entity(forEntityName: "Sample", in: _context)
        self.init(entity: _entity, insertInto: _context)
        self.smth = smth
        self.smth1 = smth1
    }

}

And then I initialize the object like this :

    let _context = DataBaseController.getContext()

let _sample: Sample = Sample(smth: smth, smth1: smth1 insertIntoManagedObjectContext: _context)
    DataBaseController.saveContext()

By following exapmle from here : Example

I've implemented these functions :

func addRecord<T: NSManagedObject>(_ type : T.Type) -> T {
        let _entityName = T.description()
        let _context = DataBaseController.persistentContainer.viewContext
        let _entity = NSEntityDescription.entity(forEntityName: _entityName, in: _context)
        let _record = T(entity: _entity!, insertInto: _context)
        return _record
    }

    func recordsInDataBase<T: NSManagedObject>(_ type : T.Type) -> Int {
        let _records = allRecords(T.self)
        return _records.count
    }

    func allRecords<T: NSManagedObject>(_ type : T.Type, sort: NSSortDescriptor? = nil) -> [T] {
        let _context = DataBaseController.persistentContainer.viewContext
        let _request = T.fetchRequest()
        do {
            let _results = try _context.fetch(_request)
            return _results as! [T]
        } catch {
            print("Error : \(error)")
            return []
        }
    }

My question is : How could I invoke my overriden init function from the class with passing also these 2 extra arguments which is smth and smth1?

let _sample = DataBaseController.Instance.addRecord(...)

Thanks in advance!

EDIT :

Is it going to be like this ? :

let _sample = DataBaseController.Instance.addRecord(Sample.self.init(smth: smth, smth1: smth1, insertIntoManagedObjectContext: _context))
Community
  • 1
  • 1
yerpy
  • 1,366
  • 3
  • 17
  • 44
  • What's the point of `addRecord`? `let _sample: Sample = Sample(smth: smth, smth1: smth1 insertIntoManagedObjectContext: _context)` already adds a new object to the database. – Sweeper Feb 17 '17 at 11:04
  • So there is no point to try it in this way ? Then whenever I am going to call other methods i need to as a argument send `Sample.self` and it is going to know that i am pointing on instance of `Sample` ? – yerpy Feb 17 '17 at 11:08
  • I don't really get what you mean by that. What is your ultimate goal? – Sweeper Feb 17 '17 at 11:10
  • To make my code clear without unnecessary redeclaration of getting informations from DB as well as saving it. – yerpy Feb 17 '17 at 11:11
  • I actually have a workaround in mind, I'll test it and update my answer. – Sweeper Feb 17 '17 at 11:21
  • @Sweeper Al'right! – yerpy Feb 17 '17 at 11:34
  • See the edited answer! – Sweeper Feb 17 '17 at 11:41

1 Answers1

1

You can't do that.

In the example you linked, it is showing how to save and query the database using neat little functions. You can't magically pass extra parameters to the functions and expect them to be accepted and used to create the new "record".

The answerer actually showed you how to use the functions if you scroll down a bit:

let name = "John Appleseed"

let newContact = addRecord(Contact.self)
newContact.contactNo = 1
newContact.contactName = name

That is how you use addRecord. You call addRecord, pass in WhateverType.self and assign the return value to a variable. After that, you set the variable's property directly, not by using the initializer.

I have come up with this (not very elegant) solution:

extension NSManagedObject {
    func initialize(with properties: [String: Any]) {

    }
}

class Sample : NSManagedObject {
    override func initialize(with properties: [String : Any]) {
        self.smth = properties["smth"] as! String
        self.smth1 = properties["smth1"] as! Double
    }

    @NSManaged var smth: String
    @NSManaged var smth1: Double

    convenience init(properties: [String: Any], insertIntoManagedObjectContext _context: NSManagedObjectContext!) {
        let _enitity = NSEntityDescription.entity(forEntityName: "Sample", in: _context)
        self.init(entity: _enitity!, insertInto: _context)
    }
}

Now all NSManagedObject has this initialize(with:) method. So in the addRecord method, you can call that to initialize a new managed object with desired properties:

func addRecord<T: NSManagedObject>(_ type : T.Type, properties: [String: Any]) -> T {
    let _entityName = T.description()
    let _context = DataBaseController.persistentContainer.viewContext
    let _entity = NSEntityDescription.entity(forEntityName: _entityName, in: _context)
    let _record = T(entity: _entity!, insertInto: _context)
    _record.initialize(with: properties)
    return _record
}

Example usage:

addRecord(Sample.self, properties: ["smth": "Hello", "smth1": 1])

The bad thing about this is of course that there is no type safety. Every property you pass to addRecord is of type Any.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • Yeah, I'm going to think about this. Thanks for your answer ! I got your point! – yerpy Feb 17 '17 at 11:45
  • 1
    I still do not get how top software architect at companies like Apple can brag about their crappy design. I mean Core Data is like designed by some indie developer for quick MVP project and Apple decided to give it a go without even doing a little review on it. How crappy mind their architects have. That aside they advertise this as a god of ORM libraries. So fucking disappointing library like thing from Apple. I am not even using advanced Core Data functionalities but I already wanna spit on faces of those architects out of my frustration. Helper library should not be pain in the ass – Farid Dec 22 '22 at 19:27