PFQueryTableViewController reload table when back btn pressed - ios

Using Parse, after I'm logged in I am presented PFQueryTableViewController that displays a list of tasks and another detail view controller that allows me to edit the task detail and segue back. The issue right now is that the PFQueryTableViewController does not reflect the new changes after I finished editing and popping the task detail view off the stack. However the table view list does get updated when I go back to the login screen(view before the PFQueryTableViewController) and re-enter the table view again. I've tried the following:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.tableView reloadData];
}
and also
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self loadObjects];
[self.tableView reloadData];
}
Yet they don't seem to take effect. My guess is that the data is updated after the view is popped off and the table view appears. I'm just wondering if anyone has any insight on this while I'm investigating. Thanks!

You could try re-querying the queryForTable method in viewDidAppear (this would naturally use an API request on every view appearance however)
- (void)viewDidAppear:(BOOL)animated {
[self queryForTable];
}

This answer assumes that you are using Local Datastore and want to see changes made in it be reflected in a PFQueryTableViewController.
Because the ParseUI classes do not implement any form of caching though the local datastore, changes made in the detail view will not appear in the PFQueryTableViewController until the save operation has completed and the tableView has fetched the new items from Parse.
One solution to your problem would be adding a category to the PFQueryTableViewController that modifies how it fetches data to include what is in the Local Datastore as well.

You should make sure the data is saved before popping your view controller.
Use Parse's save method with completion handler.
[request saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (succeeded) {
[self.navigationController popViewControllerAnimated:YES];
}
}];

You can use [self loadObjects] to trigger a refresh for all objects in the PFQueryTableViewController.

Related

How can to come back to my view when I confirm form?

I’m I downloaded MZFormSheetController library for my app.
I’ve got a problem on my popup. When I am on my TableViewController, I tap on a row to get popup to open up so that I can change the name. The popup opens, I set the name and when I tap on the button to correct the name, I call the button method but i can’t close my popup while reload my list.
- (IBAction)modifierTournoi:(id)sender {
//code to update database
//this method close the popup but don't call method viewWillAppear to reload database
//I don't know what method i can use..?
[self dismissFormSheetControllerAnimated:YES completionHandler:^(MZFormSheetController *formSheetController) {
}];
}
Before that, I used the method popViewControllerAnimated to come back to my list while recharging my list.
- (IBAction)modifierJoueur:(id)sender {
//code to update database
[self.navigationController popViewControllerAnimated:true];
}
Can you help me please ?
Thank you very much.
It looks like there is a specific completion handler for this purpose built into the library you are using:
- (IBAction)modifierTournoi:(id)sender {
//code to update database
//this method close the popup but don't call method viewWillAppear to reload database
//I don't know what method i can use..?
[self dismissFormSheetControllerAnimated:YES completionHandler:^(MZFormSheetController *formSheetController) {
// Reloading your database should work in here.
}];
}
The reason viewWillAppear will not be being called is because rather than placing a viewController modally above your window, I imagine MZFormSheetController will be adding a UIView above all presented UIViews, so viewWillAppear will never be called. But as I said above, you should be able to reload in the completion handler block.

My NSString object is not being updated until I leave my main viewController and go back?

I have been trying to figure this out for the last couple of hours and still cannot figure it out or find anything related that might help me out.
I have a method showFriendRequestData and this method makes a server call to get a JSON response. I take my data that I get back and store it into an NSMutableArray. I than make an NSString object and store the total amount of items in the array to a string value.
I then add the value to a UILabel object and try to display it. I have tried calling this method showFriendRequestData in my viewDidAppear method like this.
-(void)viewDidAppear:(BOOL)animated{
[self showFriendRequestData];
}
But ONLY when I leave the mainViewController and go BACK does the label update..... Make no sense. Am I calling this method I made in the wrong place?? Any help or guidance would be great. I want the label to update the moment I login into my main view controller.
You must invoke [super viewDidAppear:animated];
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self showFriendRequestData];
}
Setting your data too late?
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// ...
}
See guidelines-for-viewwillappear-viewdidappear-viewwilldisappear-viewdiddisappear for complete instructions.

UICollectionView refresh data

I am using a CollectionView which displays an array of objects.
On clicking a button i fill this array with a new set of data.
I want to refresh the CollectionView with this data.
Is there any statement to update this instead of comparing each items and selectively deleting and adding? The reloadData usually ends up in the following error.
CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION
In Short, I am looking for the following steps...
1)Fill the datasource array, show the data.
2)Fill the datasource array with new data, refresh the CollectionView to show the data.
Thanks in Advance
Try - (void)performBatchUpdates:(void (^)(void))updates completion:(void (^)(BOOL finished))completion.
In your case, you want "an all new set of data", so to speak, so e.g:
[myCV performBatchUpdates:^{
// one of:
// a)
[myCV deleteSection:someIndexSetForTheEntireSection];
[myRealDataSource empty:someIndexSetForTheEntireSection];
//
// OR b)
[myCV deleteItemsAtIndexPaths:someSetOfIndexPaths];
[myRealDataSource removeIndexPaths:someSetOfIndexPaths];
// Either case:
NSArray *indexPaths = [myRealDataSource getNewDataAndReturnIndexPaths];
// if a)
[myCV insertSections:newIndexSetForNewSection];
// Either case:
[myCV insertItemsAtIndexPaths:newIndexSetForInsertions];
}
completion:^(BOOL finished) {
NSLog(#"Done.");
// Maybe signal something else if you want.
}];
performBatchUpdates:completion: will expect the deletions & insertions from the original data source check entering the function to add up to the correct data source size leaving the method. It will loudly complain otherwise.
If you only have one section (section 0), you can be much more general than specific index paths if you are always "removing everything" and "inserting a complete new set".
Another option to to use KVO to listen on insertions and removals from the data source and simply reloadData, reloadItemsAtIndexPaths: or reloadSections: as appropriate.
I prefer the reactive KVO version, as I tend to use collection views with Core Data, and not pseudo-static or in-memory NSArray's.
To figure out the CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION issue, I'd setup a breakpoint on all exceptions, and try to discover what is really triggering the issue. Likely your datasource is gone and there's a bad access when you try to read/write from it.
Suppose you arrive on your view then you can add data to your array in viewDidLoad method like so:
-(void)viewDidLoad
{
[super viewDidLoad];
// If you have already data
self.arr_sample=(NSArray *)array;
/*
When you want to download data from server than you have to call reloadData
method of collection because all delegate method already called before view load.
So loading data will take time to load data than you have to call all delegate
method of collectionview by calling reloadData method.
*/
[self loadData];
// Do any additional setup after loading the view from its nib.
}
but first of all you have set the delegate of collectionview .
do you want to download data from server than you can call reloaddata method of collection view. such as
-(void)loadData
{
// Do your downloading code her and call to reload data method of collectionview
[collectionview reloadData];
}
now again do you want to refill your array with new data on your button click than you can do
-(void)refillData
{
// Download new data code here and follow
[array removeAllObjects];
array=(NSArray *)newarray;
[collectionview reloadData];
}

Get images from internet CollectionView

This is my first question so excuse me for being a newbie.
I am working with a CollectionView that shows images downloaded from the internet. The problem appears when I try to do it asynchronously.
#interface myViewController
{
NSArray *ArrayOfSections
}
#end
-(void)viewDidLoad{
[self performSelectorInBackground:#selector(refreshImages) withObject:nil];
}
-(void)refreshImages{
... //Get information from the net
NSArray internetInfo = ...;
[self performSelectorOnMainThread:#selector(refreshCollectionView:) withObject:internetInfo waitUntilDone:NO];
}
-(void)refreshCollectionView:(NSArray tempArray){
ArrayOfSections = tempArray;
}
This code is not working. It shows an empty CollectionView, although I have double checked that the information stored on ArrayOfSections is correct.
Moreover, if I do it synchronously (I change only viewDidLoad).
-(void)viewDidLoad{
[self refreshImage];
}
Everything works fine. I am going bananas. Please help
I think it's because you're not telling the collection view to reload. Your refresh method updates the model but not the view.
If you're fetching the data on a background thread, the main thread can continue it's lifecycle, which involves querying the collection view datasource and delegate methods then updating the view, but it will be doing this too soon in your case, as the model isn't ready. That's why you need to tell it to do that again, when the model is ready, at the end of your data fetch. Since you block the thread when doing it synchronously, it won't reach the collection view methods until the model is ready, which is why it works that way.

Master-Detail Application with Core Data

From Xcode 4.2 Master-Detail template (for iPad) with Core Data, I modified the data model and added additional text view objects to the nib file.
Code for moving data from managed object to interface objects is in ConfigureView in DetailViewController and it's working fine.
I'm now trying to auto save the interface object data to managed object data when I move from one item to another in the popover.
I added the code for save in viewWillDisappear in DetailViewController, but this doesn't seem to fire. Am I missing something?
- (void)configureView { // Update the user interface for the detail item.
if (self.detailItem) {
self.sname.text = [self.detailItem valueForKey:#"sname"];
self.saddress.text = [self.detailItem valueForKey:#"saddress"];
}
}
- (void)viewWillDisappear:(BOOL)animated {
[self.detailItem setValue: self.sname.text forKey:#"sname"];
[self.detailItem setValue: self.saddress.text forKey:#"saddress"];
NSError *error; if (![self.detailItem.managedObjectContext save:&error]) {
NSLog(#"Unresolved error %#, %#",error,[error userInfo]);
exit(-1); //fail
}
[super viewWillDisappear:animated];
}
First, in a MasterDetail application the detailViewController is usually always be visible and not disappear. So that is why viewWillDisappear is not being called. Of course I'm not sure about the particulars of your app architecture, so I may be wrong.
Secondly, consider the use case if the user changes some data then switches to another application. Then while in the other application, the system terminates your app. The changes that your user made will be lost and will run counter to what they expect.
Unless you are saving a lot of data for the interface in detailViewController, consider saving the data after the user changes data in the interface rather than when the user switches from managedObject to managedObject in the popoverViewController. i.e. when the user edits some data in a textView or textfield, perform a save on the managedObjectContext.
Good Luck!

Resources