Search code examples
ioscore-datansfetchedresultscontroller

Fetching single entity from to-many relationship core data iOS


I am having data model like this:

Conversation<---->>Message

I have created classes of both the above entities as:

Conversation {
    @NSManaged var messages: NSSet?
}

I am having object of Conversation and I am using NSFetchedResultsController to fetch all conversations and showing them on screen.

If I want to get a particular message from that conversation, then which way will be better:

(I am having method in Conversation as to get particular message and below are the contents of method)

1 Fetch request

func getParticularMessage(uid: String) -> Message {
    let pred = NSPredicate(format: "conversation == %@ AND uid == %@", self, uid)
    let entity = NSEntityDescription.entityForName("Message", inManagedObjectContext: moc)
    let fetchRequest = NSFetchRequest()
    fetchRequest.entity = entity!
    fetchRequest.predicate = pred

    do{
        let results = try moc.executeFetchRequest(fetchRequest)
        return results.first as! Message
    } catch {
        let resultError = error as NSError
        DDLogError(resultError.localizedDescription)
    }

}

2 iterate through NSSet

func getParticularMessage(uid: String) -> Message {
    for msg in messages {
      let singleMsg = msg as! Message
      if singleMsg.uid == uid {
         //this is the message which we want
         return singleMsg
      }
    }
}

Update

Let's say this getParticularMessage method is getting called very often (10 times each minute) while app is running.

This frequency is because app is chatting app and when we send any message and get the delivery status, read status it gets called.

As user can send message frequently in a minute, this method can get called very often.


Solution

  • Your code is dangerous because you don't know that you will find a result to return, if you don't you'll return nil and / or try to unwrap it.

    In some ways the efficiency depends on how big the database is, how many messages are in a conversation and how many of them are already loaded into memory.

    Generally the fetch will fare better, your other option requires all objects to be loaded to memory. If you know they're already loaded to memory (not faulted) then the loop should be faster...

    Finally, you shouldn't care right now. If you observe an issue then you should test to find out based on analysis of general usage conditions and extreme cases.