UITableView keep the scroll at the correct position while updating NSFetchedResultsController - ios

I am developing an iOS application that mainly use a UITableView.
It retrieves pages of articles from a server. We have got >25000 articles; so I have implemented a pull-to-refresh and infinite scrolling to travel across the title collection.
The ones downloaded persist using core data; NSFetchedResultsController is used to automatically update the UITableView.
However, I have implemented the infinite scrolling to be in both direction; up and down. Since the user will be allow to scroll down the 25000 article titles, I have to remove the one that the user has already scrolled. If the user scrolls up, I have to re-insert title above the current one.
Doing so, I have got a moving window inside the article collection.
I display my articles by date group using the section and header.
The problem is that because the infinite scrolling goes in both direction, I often delete or add article at a higher position in the table.
Infact to achieve that, I have got to change the predicate associated to NSFetchedResultsController.
This result by scroll being messed up. I have made it jump back to the position where it was supposed to be ish. It is not nice because it is a jump (animation:NO), if I put the animation ON, it goes all around the place before going back to the right position. And the position is not exactly the one it should be.
I am not sure I well explained my problem. I think the problem might be in the way I am using the UITableView but I am not sure how I should use it to make this better.
Cheers

If you only store article titles in Core Data, I think it can handle 25.000 titles.
However I think that the problem you've got is with the pagination of the visible elements of the table
Here is a link that I used to handle something that you requested. You'll have to tweak a little bit to use Core Data and a remote source.
Please post some code if you can so we can have a look.

Related

Preload tableView cells and prevent reloading

I already found entries with that topic on this page and also a website that provides a tutorial for that problem. But nothing worked very well.
The tutorial sad I should double the height of my tableView so cells loaded earlier, but with a higher tableView I never reached the last cells.
My problem is, I use a tableView to display my apps mainpage. This mainPage shows every time a topic and if its necessary for that topic it shows for example a cell with a map, one with pictures and sometimes not. Problem now, if I trying to scroll to my view its always lagging because it loads a map or this pictures. And scrolling back again because the loaded cells already deleted. I used a tableView because of the possibility to switch celltypes(mapCell, pictureCell, textCell) on and off.
I understand this feature, because of memory issues but in my case its not that much and it would be better if all my cells be preloaded and stay in memory until I change the topic.
Is there a swifty way to told my tableView to have this behavior?
Thanks a lot and nice greetings
I would suggest a different approach. Set up your table view controller to install placeholder images in your cells, trigger an async download that you cache to disk, and then update the cell with it's downloaded content if it's still visible when the download is finished.
There are various third party frameworks that do all this housekeeping for you.
Declare a cell array.
Follow these steps whenever change in your topic.
Clear you array
Create and configure all cells add to your array.
Return these cells to datasource methods using row index. Don't use tableview dequeue method here.

Best approach for UITableViewCell with complex format

I'm new to iOS development pondering how best to approach a fairly simple design problem. I want to display a set of items, each one of which has the structure as sketched. In a given set, not more than 10's of items.
Each item includes a thumbnail image, a heading, a blurb, and a set of buttons. There are two complications:
The amount of text and number of buttons is variable.
The text requires some internal formatting (italics and bold).
I've considered these approaches:
Use a table view, with custom, resizable UITableViewCell, probably using something like OHAttributedLabel for the text. For the variable number of buttons, either lay these out programmatically or possibly use the new collection view (for older iOS, have to use 3rd party grid view).
Use a table view with custom cell based on UIWebView.
Do the whole set as one UIWebView.
Use a table view with sections; each item having its own section and parsing out the buttons and text to rows.
Would love to get suggestions about how a more experienced iOS dev would approach this.
EDIT: I am now considering that the best way may be:
5) Use UICollectionView for the whole thing.
UPDATE: In the end, I laid the whole thing out in code as a custom table cell (ie., #1). This was a good choice, not only for the reasons given in the answer, but because as someone new to iOS development, it's something I needed to get under my belt. Didn't even use collection view for the buttons, because I was worried about performance and also the hassle of supporting iOS5.
I do think that using collection view for the whole design (#5) would have been an elegant solution, and I actually started down that path. However, some complications not shown in the simplified pic above made that unwieldy.
2nd UPDATE: #1 turned out to be a dead end. My final solution used a UIWebView (#3) - see answer.
I have found some resources that might be useful to some people who is doing complex tableviewcell and want fast scrolling. I am still developing it, but I want to share this first to you guys.
Facebook iOS release note: they mentioned techniques: core text, pre/asynchronous calculation of table height, do a lot of things on background thread, save layout attribute in core data. http://www.facebook.com/notes/facebook-engineering/under-the-hood-rebuilding-facebook-for-ios/10151036091753920
Fast scrolling sample: https://github.com/adamalex/fast-scrolling
Apple's sample project TableViewSuite. The 4th example.
https://developer.apple.com/library/ios/#samplecode/TableViewSuite/Introduction/Intro.html
Very close to solution..YES
I know this is an old thread, but I found it very interesting, as I am just now getting around enough as an iPhone developer to reach these types of performance concerns. I found a very interesting article on Facebook's site by Facebook Engineering describing how they implemented UITableView and overcame the dynamic sizing issues, also with rapid content management. It seems they precalculated using deeper objects and kept everything asynchronous and pre-cached where possible. I'm going to provide a link to the article, but I'm going to copy the section that tackles exactly this problem. I hope you find it useful. Here's the link, https://www.facebook.com/notes/facebook-engineering/under-the-hood-rebuilding-facebook-for-ios/10151036091753920, and the most relevant excerpt:
(Re-)Building for Speed
One of the biggest advantages we've gained from building on native iOS has been the ability to make the app fast. Now, when you scroll through your news feed on the new Facebook for iOS, you'll notice that it feels much faster than before. One way we have achieved this is by re-balancing where we perform certain tasks. For example, in iOS, the main thread drives the UI and handles touch events, so the more work we do on the main thread, the slower the app feels. Instead, we take care to perform computationally expensive tasks in the background. This means all our networking activity, JSON parsing, NSManagedObject creation, and saving to disk never touches the main thread.
To give another example, we use Core Text to lay out many of our strings, but layout calculations can quickly become a bottleneck. With our new iOS app, when we download new content, we asynchronously calculate the sizes for all these strings, cache our CTFramesetters (which can be expensive to create), and then use all these calculations later when we present the story into our UITableView.
Finally, when you start Facebook for iOS, you want to see your news feed, not a loading spinner. To provide the best experience possible, we now show previously-cached content immediately. But this introduces a new problem: If you have a lot of stories in your news feed, UITableView throws a small spanner in the works by calling the delegate method -tableView:heightForRowAtIndexPath: for each story in your news feed in order to work out how tall to make its scrollbar. This would result in the app loading all the story data from disk and calculating the entire story layout solely to return the height of the story, meaning startup would get progressively slower as you accumulate more stories.
The solution to this particular problem has two main parts. Firstly, when we do our initial asynchronous layout calculations, we also store the height of the story in Core Data. In doing so, we completely avoid layout calculation in -tableView:heightForRowAtIndexPath:. Secondly, we've split up our "story" model object. We only fetch the story heights (and a few other things) from disk on startup. Later, we fetch the rest of the story data, and any more layout calculations we have to do are all performed asynchronously.
All this and more leads to high frame rates while scrolling and an app that remains responsive.
I originally accepted (and implemented) #Daij-Djan's answer, but now I believe the best approach is #3 (UIWebView). It comes down to performance.
UITableView strains to perform well with custom cells with subviews, especially in the context of cells with varying heights. The rows of buttons make the scrolling choppy. As suggested by Apple in Cells and Table View Performance , I made sure that subviews were all opaque, however there is no way to follow the suggestion of "Avoid relayout of content."
Add onto that dynamic cell heights and attributed strings and these tables scroll pretty poorly. I suppose the next optimization would be to override drawRect, but at that point I decided to try UIWebView.
UIWebView is not without its performance issues either! Its scrolling performance degrades pretty fast as the content grows, however, I can manage that by hiding content and letting user "open" it as desired.
no 1 is maybe the most work directly followed by #2 BUT
as ACB said, it's also the most flexible and IMO will surely provide the best look'n'feel
no 3 works but will not feel as smooth / alway be tad 'html-ish'
no 4 sounds like highway to hell (later on. it will be a PITA to modify/maintain)

ios - Making UIScrollView scroll smoothly

In my iPad application, i've a scroll view that lists images of 20 video albums. The list of 20 images will be sent by server.
Now when the user reaches end of scroll view, i've to send a request to get next 10 videos details.
After fetching the data, i want to add them to the scroll view at the end. But I want to delete the 10 videos at the beginning. So that at a time scroll view will show only 20 video details all the time.
When user scrolls again to the end, i'll send request to server, get next 10 video details and add them to the scroll view, remove 10 beginning video details from scroll view...... and similarly when user scrolls to the beginning i'll fetch 10 previous videos and repeat the same.
Here i want to make sure the scrolling must be smooth and don't want to have flickers in scroll view. can some one suggest to have better scroll view coding to achieve my requirements please?
If your code contains scroll.pagingEnabled = YES; Then please remove this part of code.
It will surely work.
The real problem here will be in setting up cell recycling. It's not that hard to do, I have a couple examples of which you can look at, one being here. You'll need to make some changes to that code of course, it is set up in "pages" — Only one view on screen at any one time, and I don't think that's what you want.
Aside from that...
Your critical part here will be in designing your data source in a way that allows removing of old items, and adding new items, without skipping items.
For instance, the way I might approach this is to render the "last" item in your scroll view, the same as you want the first item in the scrollview to be. When the user gets to the last item, set your content offset to the start of the scrollview without animation (haven't actually tried this, so there may be a jolt that you don't want, test it and see). This will give the appearance of endless scrolling. Your data source would simply overwrite old indexes when adding new items, instead of adding to the end of an array for instance.
If you are presenting then in the form of a grid view, I suggest you take a look at AQGridView. That grid view supports cell queueing and dequeueing, which does exactly what you describe.
You can also use the delegate method scrollViewDidScroll: to determine if you're at the bottom of the scrollview and trigger the download of the next set of albums.

UITableView Core Data reordering (next)

UITableView Core Data reordering
I'm having troubles with the solution above. If I do updates one by one (ie one move or one delete at a time) it works when back to noedit mode. But with more updates I get application crash. (I'm using a fetchcontroller)
Could someone try this from a tableview not populated :
- create 3 rows
- hit edit mode and move 1st cell to 3rd position, still in edit mode delete the second cell.
- back to noedit mode it crash for me
Besides this I'm trying to make it work in grouped style and with several sections, where you can move cells to any section. Is someone knows an application doing this correctly ?
Thank you
Well after days trying different solutions it seems I finally get what I wanted.
In addition to Ryan Ferretti solution I had to put a flag to bypass tableview updates when commiting moved modifications on CoreData, to get it work with nsfetchedresultcontroller delegate.
It is describe on Apple documentation, see User-Driven Updates : http://developer.apple.com/library/ios/#documentation/CoreData/Reference/NSFetchedResultsControllerDelegate_Protocol/Reference/Reference.html
I now get a tableview grouped style and can move rows from any section to another one, sorted like I want.
So don't forget this flag. :-)

creating a dynamically expanding feed in rails

So what I have in my view atm is just a list of every item in my class. What I want to be able to do is have it only display the first ten or so, and put a button at the bottom that will then load the next ten into the page, and so on. Anyone mind pointing me towards a nice tutorial that will show me how to implement this?
I believe the functionality you are requesting is similar to "infinite scroll", which appends additional results as you scroll towards the bottom the page. You don't really need a button, unless you want to specifically design it this way.
A nice tutorial on infinite scrolling can be found here: https://github.com/amatsuda/kaminari/wiki/How-To:-Create-Infinite-Scrolling-with-jQuery

Resources