PageViewController : Determining "next" and "previous" when using Core Data - ios

I am converting an app to use Core Data from previously just being in-memory objects. This app fetches data from a remote API and, previously, created objects in memory with an incrementing ID and I figured out which direction the user was navigating (turning pages) in based on whether this incrementing ID was getting larger or smaller. And based on that populated child view controllers (being given to the PageViewController) with the correct info. The object selection logic was in the didFinishAnimating pageViewController delegate method because it was only called once per page transition.
Now I'm storing some objects in Core Data and I need to know what is "next" and "previous" in order to properly set the next and previous view controllers being fed to the PageViewControllers. As before I'm fetching from a remote API but now creating Core Data managed objects based on the data retrieved from the API.
I could make my own incrementing counter field in Core Data but I wondered if there is a better way to do this? I don't want to use Core Data like a RDBMS.
More generally - how are people using Core Data to power PageViewController apps with a dynamic object collection with potentially no "last page"?
Note: This project is written in Swift.

It turns out the API I am speaking to (MediaWiki category enumeration) can return results in a timestamped fashion - I can use these timestamps as a way to determine in which direction I am going. So the lessons from this is :
See what facilities the remote API has to determine result ordering; in this case chronological ordering fit the bill.
If the results are truly un-ordered and coming from a remote source then you'll have to apply some kind of local ordering so that paging works predictably.

Store the results in an array. Pass the array (and the object to display) from one view controller to the next (dependency injection). The view controller can ask the array what index the object is at and adjust from there.

Related

Swift/iOS - Sharing Model State between View Controllers

I have a question regarding sharing a model's state between View Controllers.
Let's take an example: the Twitter app. In the timeline feed, you see a list of statuses, which are loaded from the API, serialised as models. And in the mentions feed, you also have a list of Statuses. They also are loaded from the API, serialised as models, but as different instances. If a user taps the heart button on the mentions feed, it should show up as a liked tweet in the timeline feed as well. But that means sharing the state of two different model instances that represent the same status update.
The approach I'd take to solve this inconsistent state is use a "cache" of Statuses. I'd put it in the Status model as a static property, like so:
static var cache: Array<Status> = Array<Status>()
and use helper methods to always use a single instance for each post, no matter from what view controller they are loaded/modified.
Is that anti-pattern? Is there a better way to do it?
Just to rephrase first.
Get API A returns arrayA[ X, Y, Z]
Get API B returns arrayB[M, Y, F]
View controller A shows array A
View controller B shows array B
Objects are not persisted
User modifies Y in View controller A, but view controller B does not show update.
Option 1: Put all objects into one array and add a mechanism to know
which should be displayed in A and B view controllers
Option 2: When update in either array occurs, update other array if
element exists
Option 3: Get API A and Get API B handlers store results in arrayC or
dictionaryC, but also maintain arrayA and arrayB. However A and B no
longer hold instances of objects, rather references to the objects in
arrayC or dictionaryC. This is really just an implementation of
option 1. I'd got with a dictionaryC where key is the uuid of the object stored in value, and array A & B just store keys.
Sure there are other options, like sending a notification so other view controller knows to refresh data.
I don't think you should go down the road of keeping different instances in sync though.
If I'm not mistaken Twitter use Firebase, so autoupdating is just thanks to live observing of database. You should probably think about observing changes in your objects and update collections that your views are basing on appropriately. I don't know your exact architecture though.

Realm over CoreData should I use NSFetchedResultController or a Dictionary?

I'm working on an app using Core Data and NSFetchedResultController but for many reasons I would like to switch it to use Realm.
I saw that there is a "Realm version" of the NSFetchedResultController on github but It wouldn't be compatible with my current code using Core Data.
The view controller is displaying a list of People from the same school, like an address book.
This list is a sublist of a people who studied in the same city.
So I was thinking to make 1 unique request to the database to retrieve the list of all people and then filter locally this list within 1 Dictionary per school [String: AnyObject] with String as Section name within the tableView and AnyObject an array of people.
first solution, make a NSFetchedResultController for each school with a predicate filtering the location. Then all delete actions etc.. are handled by the delegates -> this is not compatible with Realm
Create those dictionaries and update them for each actions... -> this works with Realm but it's very annoying to code.
Any better solution?
EDIT:
I need to clarify my request:
I'd like to write a class that inherit UITableViewController.
This class has a list of people sorted in the alphabetical order
The tableview has section with the first letter of their firstname
The tableview controller needs to handle updates of the data model (insert, update, delete)
As we might move from CoreData to Realm, I'd like to write code that is compatible with both so that I don't need to modify it again later. The only "smart" way I found to do it so far is to forget about the NSFetchedResultController and the RBQFetchedResultsController, because they are respectively linked to CoreData and Realm, and then use data structure like Dictionaries.
Just to clarify, you're creating a UITableView with multiple sections; 1 per school, and you want to sort a flat list of people in a Realm database into the table based on their school, correct?
If that Realm fetched results controller you mentioned (I'm guessing it's RBQFetchedResultsController) doesn't fit your app's architecture, then yeah, dictionaries would be the way to go, but it shouldn't hopefully be as 'manual' as you'd think.
The good thing about Realm Results objects are that they are 'live' in the sense that if a new item is added to Realm after the Results query was made, it'll be retroactively updated to include the new item. That being the case, as long as you're managing a dictionary of Results objects that each relate to fetching the people for each specific school, the only manual aspect would be managing the table sections themselves.
The only thing to be aware of is you'll need a mechanism to be notified when a new person has been added to a specific school (in order to know to refresh that section of the table view), but for now, it would be best if you did that in your own logic (Either through a callback block, or a delegate call).
On a sidenote, we're in the middle of adding a set of new APIs to make implementing native fetched results controller behaviour possible in Realm (i.e., automating the need to post a notification when a new object is added). We haven't got a proper release date confirmed yet, but it should be within the first quarter of 2016! :)

iOS Best practice for handling model objects

There are different levels I'm asking this question at.
Case 1: Let's think about the typical drill-down design. Say a table view controller has an array of custom objects, and tapping a cell will push a view controller that allows the user to modify the object represented by the cell. In this case, should the pushed view controller have the custom object as a property of its own, or use a data source/delegate protocol to edit the custom object but not own it.
Case 2: A similar but slightly different situation is this. I'm using a singleton store to handle an array of bank accounts in my app. A view controller will show a list of the accounts, and I'm wondering if I should have the array of accounts as a property in my view controller or get the array via the store. (The array of accounts is accessed quite often.) I guess the only difference is a single object vs. an array of objects. I'm curious about how heavy these arrays can be, so whether it's faster to load the array from the store each time or have it as a property in the view controller.
Case 3: When should the local file system be used? In my app's example, bank accounts are accessed quite often, so I have them unarchived and set as properties upon launching the app, but for much bigger data, I only load them from the file system when they should be displayed or edited. I'm still not sure what the right way is.

Persist different objects (types) as single object - CoreData - (Favorites example)

My question is how to implement this correctly and with good design.
I would use Core Data for this.
Problem description:
Let's suppose that we have two object types (classes) in the system, Location and Event. They are retrieved from webservice, and there is no need to persist it.
Any of these two kind of objects can be added (saved) to favorites and it should be persisted locally.
Additional requirements:
show and manage favorites - let say in FavoritesViewController (I would use here NSFetchedResultController)
display (cell) of favorites is different, according to favorite type (location or event)
in Location/Event details view controller, there will be an action to add/remove to/from favorites, and the state of that action should be set according to favorites existance
in the future, it can be another object type which can be added to favorites (for example, Drink).
I have a dilemma about the best way to implement this. Should I store locations and events directly as separate entities (model objects), and somehow retrieve it in a single fetch, in order to get and manage the list of favorites. Or, maybe use an interface/protocol (for example Favorable), and create and store Favorite objects, and each object which can be added to favorite should implement favorable and will be converted to Favorite object, but in this case, it will limit favorites to only attributes that Favorite object exposes.
You should make a simple Core Data model with the two entities. It is very straight forward. Your table view would have two type of cells (with different identifiers) that display the data as needed.
You can use these to entities (subclasses of NSManagedObject) throughout your app. You should perhaps persist them anyway (so they are available if the internet goes down and allow the user to continue working with them). The favourite instances can be marked with a BOOL property.
One design consideration, though: maybe you want to create an optional relationship between Location and Event. Some events might be tied to a particular location and you will need this info as well. With Core Data this is really easy to do.

Passing Core Data Results Between View Controllers / Storyboard Scenes

Fairly new to Objective C and trying to work within Storyboards given it's the newest and greatest from Apple.
I'm curious, at a high level, what the preferred or best practice is for passing data between storyboard scenes where Core Data is the backend? In other words, very simple example, one scene returns a set of data, then uses a seque to point to detail (i.e., passes some identifier from the set of data to the next scene which then displays additional information based on the passed data).
Thanks.
I would pass the data as an object of some kind (either an array if that is what you are creating from the Core Data call, or a ManagedObject if you are only getting one "record" from Core Data). If there isn't a good reason for making another FetchRequest, it is best to avoid doing so.
Passing this way means a Public Property on the receiving ViewController, and then you can set the value of that property in the prepareForSegue method. If you need a complete example, I can add one later.

Resources