jessesquires / JSQMessagesViewController

An elegant messages UI library for iOS
https://www.jessesquires.com/blog/officially-deprecating-jsqmessagesviewcontroller/
Other
11.14k stars 2.81k forks source link

CoreData Example #187

Closed bassrock closed 10 years ago

bassrock commented 10 years ago

Does anyone have a core data example they would be willing to share? I'm trying to implement it with CoreData, but I am getting a very slow UI on message updates, inserts and initial page loading.

jessesquires commented 10 years ago

hey @bassrock -- are you using NSFetchedResultsController? Using this with small batch sizes should help performance.

bassrock commented 10 years ago

Yes I am it is set 20. The issue is I am scrolling it to the bottom so the user can see the most recent message. Not sure how to do that part properly.

On Mar 8, 2014, at 11:47 PM, Jesse Squires notifications@github.com wrote:

hey @bassrock -- are you using NSFetchedResultsController? Using this with small batch sizes should help performance.

— Reply to this email directly or view it on GitHub.

thieu75 commented 10 years ago

Hi all!

If it can help, i'm using CoreData with Magical Record

Here is a snippet of my code //CoreData if (!fromPush && !_loadHistory) { NSMutableArray predicates = [NSMutableArray array]; NSPredicate gameSenderId = [NSPredicate predicateWithFormat:@"senderId == %@", _game[@"senderId"]]; NSPredicate *gameTargetId = [NSPredicate predicateWithFormat:@"targetId == %@", _game[@"targetId"]]; [predicates addObject:gameSenderId]; [predicates addObject:gameTargetId];

    NSPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicates];

    self.localMessages = [[Messages findAllSortedBy:@"date" ascending:NO withPredicate:compoundPredicate] mutableCopy];
    //current user avatar
    int i = 0;
    if (self.localMessages.count > 0)
        for (Messages *object in self.localMessages) {
            if (i < 10) {
            [self.messages insertObject:[NSKeyedUnarchiver unarchiveObjectWithData:object.jsmessage] atIndex:0];
            [self.topicType insertObject:object.topicType atIndex:0];
            [self.senderOfMessage insertObject:object.senderOfMessage atIndex:0];
            [self.localMessagesUuid addObject:object.uuid];
            i++;
            } else {
                [object deleteEntity];
            }
        }

    [self.tableView reloadData];
    [self scrollToBottomAnimated:YES];
}

As you can guess, i'm buffering 10 messages on local. The rest is on Parse.com. I had no issue with scrollToBottom. To be honest, the tricky part is about managing push notification to update the ChatVC and History retrieving

bassrock commented 10 years ago

@thieu75 yea but that implementation would not allow us to use NSFetchedResultsController to its full extent. Correct?

thieu75 commented 10 years ago

Changing your implementation is out of boundaries ?

bassrock commented 10 years ago

I'd prefer to keep the implementation to using NSFetchedResultsController if possible because Im adding messages elsewhere and it automatically picks up the changes. They way I have it works but is slow on first load.

thieu75 commented 10 years ago

Ok ! I have almost the same problematic so i using the Send method from others viewControllers. Just have to be careful to init the difference array. I'm fetching messages from the viewDidLoad.

I'm quite new to iOS programming, it is possible that my pattern is not the best pattern ever but the result is what i'm expected.

jessesquires commented 10 years ago

@bassrock -- you could load locally stored messages on viewDidLoad and fetch in the background. when the fetch is complete, grab the main thread, and reload the tableView with your fetched results and rely on that for the remainder of the view controller lifecycle. (throwing away your initial local copy).

however, my experience with NSFetchedResultsController has been generally good regarding performance. I suspect that your fetch is not configured quite right, or you are storing huge amounts of data (like blobs) and fetching that is causing performance issues.

bsjcho commented 10 years ago

@jessesquires could you elaborate on what it means to be faulting correctly? even a link to a resource that could explain it further would be greatly appreciated. cheers

jessesquires commented 10 years ago

hey @bsjcho -- check out this article: https://developer.apple.com/library/mac/documentation/cocoa/Conceptual/CoreData/Articles/cdFaultingUniquing.html#//apple_ref/doc/uid/TP30001202-CJBDBHCB

bsjcho commented 10 years ago

thanks @jessesquires !

bassrock commented 10 years ago

@jessesquires but my locally stored messages are stored within core data. I am not storing blobs. I think the issue is I am setting the batched results to something small like 20. Then what happens is i have the app auto scroll down. If I turn off the scrolling down it loads fine. Do you have any ideas on how to load the latest messages first and then when the table scrolls up to have the NSFetchedResultsController grab the next set?

jessesquires commented 10 years ago

hey @bassrock - sorry for the delayed response.

at a very high level:

  1. grab latest first: you should set the predicate on your fetch to check the message date, and set sort descriptors to sort accordingly
  2. fetch on scroll: UITableView (and UICollectionView if you are planning to use v5.0) inherits from UIScrollView and UITableViewDelegate inherits from UIScrollViewDelegate, thus you can use the various scroll view delegate methods to detect scrolling, then fetch accordingly.