Kapil Choubisa
Kapil Choubisa

Reputation: 5232

CoreData doesn't keep the sequence while saveContext

I am trying to insert data in CoreData. I have may records to insert, this should be all or none. So I am creating instance of NSManagedObject and inserting it to NSManagedObjectContext one by one.

When I call below method after inserting all records:

[_myManagedObjectContext saveContext:&error];

This method save all inserted records to persistent store. When I open the Sqlite file generated by core data, I found all the records inserted by my app.

Problem is the order is not same. e.g I inserted records based on serial number 1-100 in sequense, I am able to see random sequence in CoreData sqlite file.

I know that I should not worry about the entries on core data sqlite file I can always fetch records in sorted order using NSPredicate but I need to keep the sequence because in some circumstances I need to study the database file.

Can someone tell me what to do to let saveContext method save records in the same order those are inserted to context?

Upvotes: 0

Views: 753

Answers (3)

kalpesh
kalpesh

Reputation: 1287

  1. Add the createdAt field with the date data type your entity
  2. Add an extension to your entity

extension WLSections {
    override func awakeFromInsert() {
        super.awakeFromInsert()
        self.createdAt = NSDate()
    }
}


extension WLSections {
  public override func awakeFromInsert() {
        super.awakeFromInsert()
        self.createdAt = Date()
    }
}

Whenever you fetch the data just write in

  let sortedStocks = stocks.sorted { $0.createdAt! < $1.createdAt! }

Example code

func fetchMySymbolsStocks() -> [WLStocks]? {
    let fetchRequest: NSFetchRequest<WLSections> = WLSections.fetchRequest()
    fetchRequest.predicate = NSPredicate(format: "name == %@", AppConstant.Feature.mySymbols)
    
    var aryData = [WLStocks]()
    do {
      let sections = try CDManager.shared.mainContext.fetch(fetchRequest)
      for section in sections {
        if let stocks = section.relationship as? Set<WLStocks> {
          let sortedStocks = stocks.sorted { $0.createdAt! < $1.createdAt! }
          return sortedStocks
          
          print("called")
          break
          /*for stock in sortedStocks {
            if let symbol = stock.symbol {
              aryData.append(symbol)
            }
          }*/
        }
      }
    } catch {
      print("Failed to fetch sections: \(error)")
    }
    return aryData.isEmpty ? nil : aryData
  }

Upvotes: 0

Mundi
Mundi

Reputation: 80265

The easiest way is to implement the NSManagedObject subclass's awakeFromInsert method and set a date property to NSDate(). Now you have a sequence which is accurate to 10,000th of a second. When you need items in order, just sort by this date property.

Upvotes: 0

Duncan Groenewald
Duncan Groenewald

Reputation: 8988

The only way to reliably maintain order of your objects is to add an additional attribute on the object, such as 'index', and then set the value once the object has been created. Use this object to sort the results when you retrieve them or use the index to retrieve the objects in the required order.

Upvotes: 1

Related Questions