Objective-C – reloading a UITableView without noticing the user - objective-c

How can I reload a UITableView without noticing the user behind the iDevice?
I'm updating my UITableViews datasource in -applicationWillEnterForeground: by sending a notification to my RootViewController that observes the notification and runs a selector that calls [self.table reloadData] but I want this update to be made in stealth and not showed to the user.
It seems that -viewWillAppear: is fired before -applicationWillEnterForeground:

I'm a little confused by your question, but I think what you're looking for is a way to reload the data before it appears on screen, yes?
I'd say figure out a way to call your data refresh method directly, not via a notification. The notification de-couples the data refresh from -applicationWillEnterForeground, giving the view time to appear.
Sequence is probably something like this:
applicationWillEnterForeground
viewWillAppear
The view appears.
Notification observer method is called
a) Notification observer method calls [self.table reloadData]
Table view refreshes on-screen.
What you want is to couple your notification method to a method that gets called before the view appears. Call it directly from applicationWillEnterForeground or viewWillAppear.
That way it'll play out like this:
applicationWillEnterForeground
a) your data refresh method is called. (no need to call [self.table reloadData], the tableView hasn't loaded the data at all yet.)
viewWillAppear
The view appears.
Table view is loaded with already refreshed data.
or like this:
applicationWillEnterForeground
viewWillAppear
a) your data refresh method is called. (no need to call [self.table reloadData], the tableView hasn't loaded the data at all yet.)
The view appears.
Table view is loaded with already refreshed data.

Related

View-based NSTableView is only redrawn when focus is changed

I'm writing a simple Cocoa app with GUI that only consists of a simple table whose data may update sometimes. But when data actually updates, table's rows in most cases disappear completely. But as soon as I change focus (click on desktop if my app's a primary window or click on app's window if it's not), everything shows up properly
Data is handled in a separate singleton class that runs a thread that actually looks after data source and publishes NSNotification when data changes. Window controller receives that notification, extracts new data and triggers [tableView reloadData] - that's where the problems begin
Window controller is a data source and delegate for the table and implements numberOfRowsInTableView method and viewForTableColumn method. When the problem occurs, numberOfRowsInTableView is called and returns non-zero value, but viewForTableColumn isn't called at all
I expect the table to be properly redrawn whenever [tableView reloadData] is called and wherever my focus is, but on practice everything just disappears and properly redrawn only after I change focus
Fixed it. The problem was updating GUI from background thread

Storyboard and memory management

I am using storyboard and i stumbled upon something i have not been able to grasp.
I am putting up my view controller programmatically with performSegueWithIdentifier:.
It works like a charm, but what i noticed was that every single time i do this, i create a new instance of that viewController, and so, i have memory that keeps piling up. When i simulate a memory warning, i see that for each time i have been calling performSegueWithIdentifier:
i have a new instance of the view controller, and it NEVER gets deallocated. So memory just piles up and i cannot release it, which eventually causes a crash.
I just go to the view controller like this:
// If sales are registered, go to view
[self performSegueWithIdentifier:#"previousSaleSegue" sender:self];
What am i missing here?
You'll be stacking view controllers on top of each other instead of returning to a previous one. Assuming you are using a navigation controller, you'll be doing this:
A --push--> B --finished! Push---> New A ---Push---> B ---Finished! push--->A ...
What you should be doing is:
A --push--> B --finished! Pop -
^-----------------------------/
You're using modal segues by your comments, in this case you need to add an action to your return button to dismiss the view controller (returning to the previous one) instead of presenting another instance. The principle is the same. You'd use
[self dismissViewControllerAnimated:YES completion:nil];
If you're certain that viewcontroller instance does not get deallocated it must be because you keep reference to it somewhere (it could be a cycle on the controller itself).

Xcode: Reloading a portion of controller with each view

I am working on an IPhone app that, through viewDidLoad, makes a connection and pulls data into a table. I would like the controller, or at least the table, to reload every time the controller is displayed, even if someone just switched from one tab to another or closed and re-opened the app on this controller. Is there a way to do this? I can't seem to find anything, it's also kind of a hard thing to search for. I have found discussions of when to put code in viewDidLoad but not another method that is run every them the controller displays.
Thanks,
Cheryl
You want to use
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
//code to reload table viewdata
}
Each time the view appears this method is called. I use this a lot in my app.
There's no way to do it by injecting code in only one place.
You can think of a workaround, like for example sending custom "reload request" notification from required parts of code:
viewDidAppear: in your view controller
applicationDidBecomeActive: (if table is presented)
tabBarController:didSelectViewController: (if switched onto controller with the table)
tabBar:didSelectItem: (same as above)
etc.
In you view controller simply observe this notification and reload data when required.
Although, whats more important: do you really need to reload data under such harsh requirements? In most cases data reload happens when
view controller's viewDidLoad: is called
it is manually initiated (button, for example)
long time passed since the last update was received
Otherwise it's just an overkill.

viewWillAppear getting called before viewDidDisappear of another controller gets finished

I have 2 view controllers say VC-1, VC-2. I have VC-2 displayed over VC-1 through navigation stack. VC-1 has textView and VC-2 has webView. Now I need to update the VC-1's content as soon as VC-2 is popped off. Hence I am using viewDidDisappear method of VC-2 to set the content and using that in viewWillAppear of VC-1 to update the textView (VC-1's content). But before viewDidDisappear finishes itself viewWillAppear of VC-1 gets executed and the content is not updated. I have checked this by NSLogging. viewDidDisappear has some file reading stuff so I guess that is causing the problem. How can I make the WillAppear(of VC-1) to get called after DidDisappear(VC-2) gets finished?
-viewWillAppear: is called before your view comes on screen at all. -viewDidDisappear: is called after your view is wholly gone from the screen. Therefore on any sort of animated transition, e.g. a navigation stack pop/push, the incoming VC's -viewWillAppear: will necessarily be called before the departing VC's -viewDidDisappear: is called. This is perfectly correct.
You should probably take the work you're doing in -viewDidDisappear: and move that to -viewWillDisappear: instead.

How to dismiss UIActionSheets and UIPopoverControllers without knowing who presented them

In my client application I have an idle timeout control mechanism and when the user does not do anything with the app for a specified time interval, I display a warning and throw him back to the login screen. This control happens in my container view where I initiate all of my other views. When the idle time is up, I pop this container view to its caller, i.e the login screen.
The problem is, if the user does sthg that displays an action sheet or a popover and then does not do anything until the idle time is up, when I throw him to the login screen the action sheets and the popovers also remain on the login screen since I don't dismiss them.
To solve this, I can think of making all the action sheets and the popovers retained members of my view controllers and then dismissing them on the viewWillDisappear methods of their owners. But I have so many view controllers, so I'm looking for other ways, if there are any.
So, the question is how can I make all these action sheets and popovers go away from my login screen without knowing who their callers are?
I would register the UIPopover instance to listen to some notification.
[[NSNotificationCenter defaultCenter] addObserver:_myPopOver
selector:#selector(myDismissPopover)
name:#"dismissPopover"
object:nil];
And add extension to UIPopover class.
- (void) myDismissPopover {
[self dismissPopoverAnimated:YES];
}
When I need to dismiss popover, I just need to post notification.
[[NSNotificationCenter defaultCenter] postNotificationName:#"dismissPopover"
object:nil];
I'll write down my own solution as we've talked with bshirley in the comments of the question.
I've implemented a mechanism like this to solve the problem:
In my login view controller, I create an NSMutableArray that will keep all my action sheets and popover controllers that are going to be dismissed. Then I store this array in a global dictionary. I access this dictionary via a utility method. Then all through the application, whoever creates an action sheet or a popover controller, adds the component to this array (retrieves the array from the global data, modifies it and then saves it back to the global data). Then when the user is thrown back to the login screen, in viewWillDisappear of my login view controller, I loop through this array and call the appropriate dismiss method by checking if the UIView I get from the array is an action sheet or a popover controller. Then I remove all the elements of this array and then store it back in the global data, again.
Hope this helps anyone who needs to implement a similar mechanism. Your comments will be appreciated.