Core Data: delay calling endUpdates till viewWillAppear - ios4

I have a Core Data app with a tab-bar controller that displays 2 view controllers. If I add something in the first tab's view controller, it should display in the 2nd tab's VC. Both VCs are based off a NSFetchedResultsController which is based off the same entity; the only difference is that one has a predicate and the 2nd VC doesn't.
This works fine for the normal template, and when data is added from the 1st VC, it gets updated instantly in the 2nd tab using controllerWillChangeContent and controllerDidChangeContent. The problem is that if the user adds or deletes any rows in the 1st VC, when the user comes to the 2nd tab they don't see the rows animatedly inserted or deleted... everything's already there.
What I would like to do, in the 2nd tab's VC, is delay calling the [self.tableView endUpdates] (which causes the animated inserting/deleting of rows in the table) till the user actually goes to that tab, in that VC's viewWillAppear. I've tried this, but doesn't seem to work:
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
tableviewUpdates = TRUE;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (tableviewUpdates) {
tableviewUpdates = FALSE;
[self.tableView endUpdates];
}
}
This works if adding one row at a time and then switching to the 2nd tab, but not if I add multiple rows in the 1st tab and then switch.
Any help would be appreciated.

You're working against the purpose of the NSFetchedResultsController which is to make updating the tableview automatic and effortless.
I'm pretty sure, however, that if you override all the FRC delegate methods you can block all the automatic updates.
You might want to rethink this design. Are users really going to expect to see changes in one view reenacted in a second? Will they understand they are watching a rewind of the previous changes or will they intuitively think that the app is doing something to their data on its own?
The standard UI grammar teaches users to expect that one change animates once and then subsequently just shows up in a standard display. I would suggest you test this design with naive users carefully before deploying such a non-standard interface.

Related

Is there a way to dynamically switch between FetchRequest and SectionedFetchRequest?

I've been playing around with CoreData in the last couple days, trying to build an app to review money spent on shopping. Right now its still pretty simple with just a single Data Model for the individual shops.
I have a list view displaying all of them and I've integrated sorting into the list, first through older workarounds around the predicates, but than I found this video from this years wwdc and I basically just copied. I've really been fascinated by the grouping feature from the SectionedFetchRequest and I wanted to integrate it, while maintaining the original non sectioned List. So I thought I'd skip the FetchRequest in my List and just pass the results to the list view instead of the SortDescriptor
MainView{
ListView(descriptor: SortDescriptor)
}
ListView{
FetchRequest(sortDescriptors: descriptor)
}
changed to:
MainView{
ListView(FetchRequest(sortDescriptors: descriptor))
}
ListView{
FetchedResults
}
But that still leaves me unable to just push a button to turn sectioning on or off.
I'm kind of stuck on how to go on from here.. First idea coming to my mind is creating a wrapper around the ListView handeling which FetchRequest to send out to the ListView based on Button toggle state like
MainView{
Wrapper(sortDescriptors, toggleState)
}
Wrapper{
ListView(FetchRequest(sortDescriptors: descriptor))
}
ListView{
FetchedResults
}
but I still would have the problem that I'd need 2 Variables in my ListView, one for the normal, and one for the sectionedFetchResults.
Has anyone an idea how to handle this ?
TLDR I want to dynamically switch between FetchRequest and SectionedFetchRequest
According to the documentation you can't not section a SectionedFetchRequest, therefore you would have to support both. Therefore, I would make two separate sub views, and show them in a parent view that has logic to control which one is shown. You would need to do this anyway if you are supporting pre-iOS 15 OS's.
MainView{
if sectioned
ListViewSectioned(sortDescriptors: descriptor, sectionID: sectionID)
} else {
ListView(sortDescriptors: descriptor)
}
}
ListView{
FetchRequest(sortDescriptors: descriptor)
}
ListViewSectioned{
SectionedFetchRequest(sectionIdentifier: sectionID, sortDescriptors: descriptor)
}
The main view doesn't have to know any more to choose and set up the different list views. I didn't put an OS check in, but you will need that as well.

Why isn't MvxStandardTableViewSource SelectedItem updating properly?

I'm trying to bind a UITableView to an ObservableCollection<MyTypeViewModel> using MvxStandardTableViewSource, and I'm getting weird behavior and bindings that aren't working
The (partial) code is this:
tblFeatures = new UITableView ();
mSource = new MvxStandardTableViewSource(tblFeatures, "TitleText Name");
var set = this.CreateBindingSet<MyTypeView, MyTypeViewModel> ();
set.Bind(mSource).To (vm => vm.Objects);
set.Bind(mSource).For(s => s.SelectedItem).To (vm => vm.SelectedObject);
set.Apply ();
What I'm seeing is that when I select an item in the table, it does update SelectedObject with the new value. But when I change SelectedObject by some other means, the table does not update the displayed selected item. I have verified that the SelectedObject really is being changed, by setting a breakpoint and by binding another control to it; the other control (a label) does change as the selection changes, but the UITableView does not.
Am I doing something wrong, or could this be an issue in MVVMCross?
The selecteditem binding was requested as a 'nice to have' and was mainly requested for the user story where a user clicks on a list item - so this is currently a 'one way to source' implementation.
The very basic details and some code can be found via - https://github.com/slodge/MvvmCross/issues/278
In truth, the current binding is abusing the 'selected' paradigm - as it doesn't really reflect the selection state of the cell and also has no handling of mutiselect - instead it just lets the viewmodel know the latest tapped item.
If there are genuine user stories/requirements for full two'way binding, then these should be addable - eg if the user story were for scrolling the item into view then 'scrollToRowAt' could be used - see How to scroll UITableView to specific position - but this again might not be true 'selection' within the uitableview.
if you wanted to implement this yourself it should be fairly straight-forward to override the binding with your own one (see the custom binding n+1 in http://mvvmcross.wordpress.com for an intro on custom bindings).
could this be an issue in MVVMCross?
Overall I think I'd categorise it as a known limitation of that particular binding caused by lack of user demand and by some confusion over whether selection genuinely means selection in the touch screen era.
if it was logged as a bug I'd say it wasn't.. If it was logged ss a feature request I'd try getting as much user input as i could about what devs really want from this, whether they want true cell selection or scroll into view, both or something more.
By other means you mean not from UI thread I presume. Please try by invoking the change on UI thread.

#SetViewInfo - Issue when clearing filter

I have a problem that have me stumped.
I have been searching for a solution, but haven't found a working one yet. The solutions I seen introduces other issues.
Here is the scenario:
I have a frameset with two frames: 'Navigator' and 'Main'.
In the 'Navigator' frame I display a form called 'Navigator'. It contains an outline, to display a menu.
In the 'Main' frame I display the view selected by the user in the navigator.
So this is a very traditional Notes client application.
I now want to add a checkbox at the top of the view (in the action bar), allowing the user to filter the view by his/her own name. I use #SetViewInfo for this, and it all works perfect.
The issue is when the user switch views. The #SetViewInfo filter stays active when switching to a different view, so after some searching I found some solutions:
In http://www-01.ibm.com/support/docview.wss?uid=swg21204481 IBM suggests to put the following code in the QuerySave event:
#SetViewInfo([SetViewFilter]; temp ; 0 ;1)
When I am switching view or closing the view, I get the error message "Cannot execute the specified command".
In http://www-10.lotus.com/ldd/bpmpblog.nsf/dx/using-setviewinfo-in-a-notes-client-application-to-create-a-user-specific-view Andre Guirard suggests to put the following code in the QuerySave event:
#SetTargetFrame("frameName");
#UpdateFormulaContext;
#Command([OpenView]; #Subset(#ViewTitle; -1));
#SetViewInfo([SetViewFilter]; ""; "columnName"; 1)
I modify this to match my frame name and the programatic name of the first column in my view:
#SetTargetFrame("Main");
#UpdateFormulaContext;
#Command([OpenView]; #Subset(#ViewTitle; -1));
#SetViewInfo([SetViewFilter]; ""; "Adjuster"; 1)
This works perfectly when switching between view. But when I close the application while I am in this particular filtered view, the application is re-opened automatically. This happens no matter if the filter is enabled or not when closing the view.
However, when the view repopens, the frameset is not reloaded, it is just the view with the built-in view navigator to the left.
I finally got this to work by (in the built-in view navigator) selecting another view that the one where I filter data. This fixed the issue for a while, but then it starts again, and the filtered view is active in the navigator.
Obviously it is the OpenView command that is causing this, but if I remove just that line, I get the "Cannot execute the specified command" error again.
Any suggestions/pointers? I am using Notes 8.5.3 running on Windows 7 Professional.
This question can also be found in the IBM developerWorks forum for Notes 8.5:
http://www-10.lotus.com/ldd/nd85forum.nsf/DateAllThreadedWeb/08c73910571306c485257b2b0061ef91
First thing, I would suggest to make sure your view frame is always called "NotesView". You will have much less compatibility issues if you do this.
Secondly, I presume when you say you put it in the QuerySave event you really mean the QueryClose event? Views do not have a QuerySave event.
Thirdly, I find the #UpdateFormulaContext line is not needed. This is what I have in my view QueryClose...
#SetTargetFrame("NotesView");
#Command([OpenView]; #Subset(#ViewTitle; -1));
#SetViewInfo([SetViewFilter]; ""; "<programmaticColumnName>"; 1)
And I can close the app while in the view without any problems.

Issue with Map view delegate method 'mapView:regionDidChange:' do not call

while using map view in my application some times MKMapKit delegate method 'mapView: regionDidChange' do not call.
Its happens only when I drag the map. but when i zoom in or Zoom out Its working perfectly. So its create issue related to place new annotations on map while dragging the map.
I have do this code in mapView:regionDidChange:
int j=0;
-(void) mapView:(MKMapView *)mapsView regionDidChangeAnimated:(BOOL)animated{
zoomLevel = self.mapView.region.span.latitudeDelta;
if (![appDelegate internetConnected]){
return;
}
if (appDelegate.isMapViewRegionChanged) {
if (j==0) {
j++;
return;
}else{
j=0;
appDelegate.isMapViewRegionChanged = FALSE;
return;
}
}
[self callGetMapViewWithObject:nil];
}
/*
first boolean is to check Internet connection.
[appDelegate internetConnected]
Second condition is to return when we navigate from any view controller too map View controller.
appDelegate.isMapViewRegionChanged
Third is a method to place new annotations.
[self callGetMapViewWithObject:nil];
*/
I checked all conditions and booleans but my coding is not reason for this bug.
so may be its related to region did change method.
So while using my app with map, 20% of time its behave like Ideal(method do not call).
can some one help me out with this.
Thank you in advance.
EDIT It broke randomly, so I now call the function again (undoing what I said below), no changes extra... and um, it works. I feel like I'm flipping a coin.
I just had this happen because I have a subclassed MKMapView. I don't know if you're subclassing this or not, but for some reason Apple's super functions, eg: -(void) scrollViewDidScroll; called super but was not intercepted properly and skipped that call.
When I removed the "overridden" call, that was just a call to [super scrollView], it started working properly.
I don't know why apple's code is broken that way (calling super doesn't have the same effect not overriding it), but make sure you're not subclassing these:
ScrollView functions
MKMapView functions...
or perhaps using the WildCard Gesture Recognizer provided very kindly by the answer to why Map Views don't respond to touchesBegan/Moved etc here: How to intercept touches events on a MKMapView or UIWebView objects? .
If this doesn't help, ensure you don't have a view on top of the other views, improper delegates, xibs are arranged and hooked up, the usual stuff.

Creating a new NSManagedObject within an NSPersistentDocument refuses to save even though undo shows as possible

I have a CoreData / NSPersistentDoc app. It works fine.
I added a new entity to the MOM, and updated the version.
Now, when I create new instances of that Entity inside the MOC, the "Save" menu item remains disabled until/unless I create any instances of the old Entities that were already in the app.
The red dot button on titlebar correctly goes black to show that the document has changed - but OS X / NSDocument refuses to acknowledge this - it is impossible to do a Save.
Any ideas?
I found the cause / solution - it was my own bug, but this answer may help others with similar issues.
I was using Apple's official approach for enabling the Copy/Paste menu items (by implementing validateMenuItem), and returning true/false for copy and paste at the right times.
And I was returning NSPersistentDocument's implementation for everything else (which included Save, although I didn't see that).
Then, when I added my new NSManagedObject, I added a sub-view, and sub-view-controller, and I delegated the validateMenuItem to this - i.e. so that it could handle it's own copy/paste status.
...but I had no code path for "if it's not copy paste, and it's not handled by the child, and it's not handled by my NSPersistenDocument subclass ... then hand it to NSPersistentDocument to decide"...
...and so the Save menuitem was never being enabled.

Resources