iOS 8.3: UICollectionView & multithreading: What is the best approach? - multithreading

For an iOS application wherein a UIViewController has a collectionView whose datasource (an NSArray) is contained in a separate model class. This array is getting updated [adding / removing items to it] through an NSNotification which in turn requires a web API call [on another thread]. When web service returns information then the datasource is updated and so also UICollectionView needs to be updated. This process is continuous & occurs at random times.
The question is how the UICollectionView's UI updation can be done in a safe manner so that it do not result in issues where UICollectionView start complaining that no. of rows / section before update is not same as after update
Can anybody suggest an approach so that multithreading do not have any impact on UICollectionView and one can safely use UICollectionView's various UI manipulation api like insertSections, insertItemsAtIndexPath etc. In this process the UICollectionView is continuously changing and so also its data source.

Related

Catel Edit Master-Detail View multiple times

I'm trying to edit a Master-Detail View multiple times in Catel.
My question is, if there is no common way in catel to handle a Master-Detail-View and multiple editions using the SaveViewModelAsync and CancelViewModelAsync methods?
The workflow works when my Master-ListItem is no UserControl with it's own ViewModel and when I change the selected Master-ListItem after save or cancel, so that a new ViewModel will be created. But I don't want to null or change the selection after a save/cancel. Also I have maybe to create a UserControl + ViewModel for the Master-ListItems.
Restrictions of the question:
I have got the information from Geert van Horrik from the discussion of his answer, that
multiple edit cycles are not supported directly
one Model should only be accesd by one ViewModel
Problem:
I can use the the SaveViewModelAsync and CancelViewModelAsync only once. After that, the ViewModels which are alive
will get no updates from the Model
don't create a BackUp from the Data, so that the changes can be reverted again
Code to Reproduce:
I have created a WPF Project, where I tested this all.
Possible solution:
I could use the EditableObjectHelper and handle this by myself
I have to instantiate the VewModel again, after the save or cancel, like it happends on a selection change in my Example Code
Restricion of the solution:
If I use a specialized UserControl for the ListItems of the Master-View, 2 ViewModels are looking on 1 Model. After the SaveViewModelAsync the ViewModel doesn't get any Notifications of the Model. So I would have to instantiate this ViewModel again too. But I would Breake the 1-1 relation of the ViewModel-Model.
My conclusion:
It seems, that I have to instantiate all these ViweModels and handle this workflow all by myself. It seems, that the ViewModelLifetimeManagement.PartlyManual (CloseViewModelOnUnloaded is Obsolete) doesn't work here. On selection change, always a new ViewModel will be created, the old one will probably just not be closed.
I don't want to misuse the framework. Maybe I have missed something. I hope somebody can help me or give me a tip, how to handle this.
Catel calls Save / Cancel as soon as the view model get's unloaded. If you want to do "intermediate" saves without changing the data model, you can:
Save the master list which will save the dirty models (you can directly modify the models from within your vm's)
Create a custom command (SaveData) that you can run from an explicit button (or input gesture binding) to save the data without calling SaveAsync on the vm
After the answer of Geert van Horrik, I currently ended up , don't using the SaveViewModelAsync and CancelViewModelAsync methods and handle the save and cancel by my own, so that the notification will not breake. I'm using the GetChildViewModels() method on the ViewModelBase and the EditableObjectHelper.CancelEditObject(Model);

Restoring Core Data Master-Detail selections across runs

I'm trying to make a row selection in an NSTableView persist across app runs.
I have an NSTableView that acts as a Master view, and an NSCollectionView for the detail view. My sample project is here:
http://www.filesend.net/download.php?f=3f34594d71e32b2c1fbef768eccb56b0
These two views are bound appropriately to NSArrayControllers with Cocoa bindings. These are, in turn, bound to a Master Entity, a Detail Entity and a one-to-many relationship “myChildren” in a CoreData store. The “myDetailAC” Content Set is bound to the CD relationship. In my App Delegate, I create some sample data in the applicationDidFinishLaunching callback.
This all works swimmingly well once the app is up and running… selecting rows of the Table causes the detail NSCollectionView to show the details for the master item. In fact, what I've built serves as a good starting example for Master-Detail setup using Core Data and Cocoa bindings.
The problem is this: when I quit the app and restart it, I would like the TableView row to be selected with the most recent master selection (and automatically the appropriate detail data set).
One of my attributes in my CD Master entity is isSelected, which is set based on which row of the NSTableView was last selected.
I have attempted to override NSArrayController in “MasterAC.m" for the master table. In here, I've attempted to call setSelectionIndexes from within it to alter array controller's selection based on the isSelected flag. I do so from within the array controller's arrangeObjects method.
No dice.
Can anyone help out with persisting the Table Selection across runs of the sample app?
In short, if I quit the app with “Parent #3” selected, then running the app again will cause “parent #3” to be selected along with its detail info.
Some other suggestions on SO deal with this using NSUserDefaults, but not Core Data.
Restoring the selection in an NSTableView (NSWindowRestoration)
What might be the easiest solution, if you’re targeting newer OSes, is just to use "state restoration." It’ll reach into the master table and essentially re-click the selection for you, and it even scrolls to the right point. It’s kind of magical when it works.

IOS Core-Data concurrency issues

I once again come about my RSS Reader iApp which, at the moment, is designed the following way:
Data model: Category -> Feed -> Post
Master View: Feeds grouped by categories
Detail View: Posts for a given Feed
All of the views and the app delegate only interact with the same _mainMOC (ManagedObjectContext).
Each of the created NSOperations will use its own _localMOC which is connnected to the same NSPersistentStoreCoordinator.
When the App starts, it creates for each of the Feeds a fetchOp NSOperation which it adds to an NSOperationQueue. This should ensure the RSS Feeds will be individually downloaded, parsed, then their contents inserted Post by Post in CoreData.
The AppDelegate observes the NSManagedObjectContextDidSaveNotifications and merges the modifications if the notification it receives is not _mainMOC. It then sends a specific NSNotification to notify the each of the views that a reloadData is required.
Questions:
Do I still need to enclose my _mainMOC save: operations in performBlock blocks?
Should each of my views only use a _localMOC instead of the _mainMOC?
Isn't it redundant to have each view's local NSFetchedResultsController re-perform a fetch before a reloadData?
Should I make any non-read-only Core-Data Operation a queued NSOperation, even at the view level?
How could I make all of this smoother (it still isn't and I still have a few horrendous bugs so redesign is a possibility)...
Thanks for your help.
1) & 2) It doesn't appear these are absolutely required: we are in the main thread, after all.
3) This couldn't hurt: especially if the NSFecthedResultsController uses a variable NSPredicate (see here).
4) I am going to do it anyway as it doesn't hurt.
5) Keep in touch...

When core data is changed, how to update the table view data?

Using NSXMLParser to get data from an xml file on internet with an update button to get update database and store it by using xcode template core data.
However, when I updated all core data, console can only show right data until I quited the app and run it again.
Any way to update all data correctly without quiting the app?
Thanks for that answer.
With using Xcode template (Navigation-based Application with core data), fetchedResultsController and managedObjectContext and so on are all included. Yet, every time I changed xml file and run parser to store data again, both my table view and nslog messege come up with a list of wrong data, eg, list of numbers only while my data contains lots of strings.
Display comes back to normal only I killed and rerun app again.
Any ideas?
Using CoreData the simplest thing to do is to use a NSFetchedResultsController. You can set your view controller to be the delegate for the NSFetchedResultsController, which will give you notifications when your data changes. You can then update your table appropriately.
This tutorial might help: http://www.raywenderlich.com/999/core-data-tutorial-how-to-use-nsfetchedresultscontrolleY

Reverting CoreData data

I have an NSTableView which is populated via a CoreData-backed NSArrayController. Users are able to edit any field they choose within the NSTableView. When they select the rows that they have modified and press a button, the data is sent to a third-party webservice. Provided the webservice accepts the updated values, I want to commit those values to my persistent store. If, however, the webservice returns an error (or simply fails to return), I want the edited fields to revert to their original values.
To complicate matters, I have a number of other editable controls, backed by CoreData, which do not need to resort to this behaviour.
I believe the solution to this problem revolves around the creation of a secondary Managed Object context, which I would use only for values edited within that particular NSTableView. But I'm confused as to how the two MOC would interact with each other.
What's the best solution to this problem?
The easiest solution would be to implement Core Data's undo functionality. That way you make the changes to Core Data but if the server returns the error, you just rollback the changes. See the Core Data docs for details.

Resources