I have a uitable in one of the Tabview of a tabbarcontroller application. Now depending on some action in other tabview, the uitable should reload (refresh) for updated data at backgrouns. However, I am not able to get it using either reloadData or beginupdates-endUpdates.
Can someone please help in this kind of scenario.
Thanks in advance.
I would recommend use a combination of NSNotification as well as viewWillAppear/viewDidAppear for this.
When the viewWillAppear - reload the tableview (You may refine it by looking for change in data since you last time displayed the data)
- (void)viewWillAppear:(BOOL)animated
{
// Your other code here...
[self.tableview reloadData];
}
Once the view has appeared and in background the data is changed by some other object - ask that object to send notification and in your tableview's viewcontroller register for that notificaiton in viewWillAppear & deregister in viewWillDisappear
The other object should send/post notification like this (just after the data change)-
[[NSNotificationCenter defaultCenter] postNotificationName:#"com.yourcompany.appname.XYZdataChangeNotification" object:nil];
All the below code in your viewController (which has table to be updated) -
Register like this -
- (void)viewWillAppear:(BOOL)animated
{
// Your other code here...
[self.tableview reloadData];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleNewDataReceivedNotification:) name:#"com.yourcompany.appname.XYZdataChangeNotification" object:nil];
}
Notification handler in your view controller -
- (void)handleNewDataReceivedNotification:(NSNotification *)notification
{
// Your other code here...
[self.tableview reloadData];
}
And de-register like this -
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"com.yourcompany.appname.XYZdataChangeNotification" object:nil];
}
All the above code can be refined but it should give you an idea. Please feel free to ask if any questions/concerns.
Related
I'm not sure about how to achieve this and hence i'm asking this question.
I have 2 ViewController(VC) named abVC and xyVC.
abVC contains only TableView and xyVC contains only a button.
When i tap a button on xyVC, it should reload tableview inside abVC without moving to that abVC.
Is it possible ? If yes.. then please help me,How to do that?
You can do it with both block and NSNotification.
With block you can implement it as follows:
make a property as follows in xyzVC.h:
#property(strong,nonatomic)void(^callBack)();
Synthesize this property in xyzVC.m
#synthesize callBack
Call this block in Buttons click event
- (IBAction)btnClick:(UIButton *)sender {
if (callBack)
{
callBack();
}
}
Implement it in abcVC where you want call back:
[abVC setCallBack:^{
//reload your tableview here
}];
With NSNotification you can implement it as follows:
Register for receiving notification in abcVC.m
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reloadTableView) name:#"ReloadTable" object:nil];
- (void)reloadTableView{
// Reload your tableview here
}
Now post the notification from xyzVC
- (IBAction)btnClick:(UIButton *)sender {
[[NSNotificationCenter defaultCenter] postNotificationName:#"ReloadTable" object:nil];
}
Note: If you are using NSNotification then don't forget to remove it when your view controller is dismissed
I hope this will help you :)
Add this line in your button action method
[[NSNotificationCenter defaultCenter] postNotificationName:#"ReloadTable" object:nil];
Add this code where you have implemented table, so in abVC:
inside viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reloadTableViewData) name:#"ReloadTable" object:nil];
Add following method
- (void)reloadTableViewData{
[self.myTableView reloadData];
}
Implement dealloc method (to prevent crash)
- (void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"ReloadTable" object:nil];
}
I dont want to add observer in viewDidAppear and remove in viewDidDisappear.Will not serve my case.
I have tried doing it in dealloc.
My root VC is in navController.Then a second VC is pushed in navController, where I addObserver for notifications to be sent from rootVC.The problem is when I pop the secondVC its dealloc is not called immediately or may be somtimes not called alltogether.
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(newMessagesNotification:) name:_newMessageNotificationListenerName object:nil];
}
- (void)newMessagesNotification:(NSNotification *)notification {
//some implementation
}
If you do not want to remove in the ViewDidDisapear than i think you should remove it right after you called the navigationCotnroller pop methode. But I think we can't tell you the exact moment when you should remove because we don't know when you want to remove it and why it isn't good in the ViewWillDisapier or in the ViewDidDisapier.
I am trying to understand how updating of a viewController that is currently visible works.
I have ViewControllerA and ClassA. I want to tell ViewControllerA to reloadData on the tableview from ClassA. What is the best way to go about doing this?
I have found this question and answer but I dont think this will work in my situation or I am not understanding it correctly.
The easiest way without knowing your setup would be to use NSNotificationCenter. Here is what you could do:
In ViewControllerA add in hooks for NSNotificationCenter:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
//Register for notification setting the observer to your table and the UITableViewMethod reloadData. So when this NSNotification is received, it tells your UITableView to reloadData
[[NSNotificationCenter defaultCenter] addObserver:self.table selector:#selector(reloadData) name:#"ViewControllerAReloadData" object:nil];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
//Need to remove the listener so it doesn't get notifications when the view isn't visible or unloaded.
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Then in ClassA when you want to tell ViewControllerA to reload data just post the NSNotification.
- (void)someMethod {
[[NSNotificationCenter defaultCenter] postNotificationName:#"ViewControllerAReloadData" object:nil];
}
Answers here about using NSNotificationCenter are good. Be aware of a few other approaches:
A common one is the delegate pattern (see here and here).
Another is that the view controller observes the model change using KVO. (see here and here).
Another good one, often overlooked, which can probably be used in your case is the "do almost nothing" pattern. Just reloadData on your table view when viewWillAppear.
Key value Coding , NSNotificationCentre and Delegates are preferred. But NSNotificationCentre is easiest in your case.
The UIViewController that contains UITableView must add observer like this :
Init :
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(methodToReloadTable:)
name:#"TABLE_RELOAD"
object:nil];
In delloc method :
[[NSNotificationCenter defaultCenter] removeObserver:self];
Post it from any XYZ class like on any UIButton action :
[[NSNotificationCenter defaultCenter]
postNotificationName:#"TABLE_RELOAD"
object:self];
Advantage of NSNotificationCentre is that they can add observers in multiple classes ..
I want to show a full page image Ad every time a UIViewController is shown.
I think I have to call the method inside a viewDidAppear or ViewWillAppear, but they are being called once.
- (void) viewDidAppear:(BOOL)animated{
[self showAds];
}
- (void) showAds{
//Do Something
}
What should I do to call a method every time a uiviewcontroller is shown( even if its already created)?
ViewWillAppear will be called every time a UIViewController is shown,but won't be called when the app is back to foreground.
you can use Notification to achieve your goal by following code,
This scenario is specially when your app is in background and user press HOME button to active it.
Register for Notifcation when your application enterForground in viewDidLoad only.
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(handleEnteredBackground)
name: UIApplicationDidBecomeActiveNotification
object: nil];
write a method to invoke when application enterForground
-(void)handleEnteredBackground
{
NSLog(#"%s",__FUNCTION__);
// Your stuff here
}
Dont forget to Remove Observer in viewDidUnload method
[[NSNotificationCenter defaultCenter] removeObserver:self];
Post New Notification everytime your application enterForground
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidBecomeActiveNotification object:nil];
}
ViewWillAppear should be called every time. Use:
- (void) viewWillAppear:(BOOL)animated{
[self showAds];
}
Hi I am using NSNotificationCenter defaultCenter to implement the 'like' and 'comment' functions in my app.
//In Answer Table View
#implementation AnswerTableView
- (id)initWithParentController:(UIViewController *)pController andResourcePath:(NSString *)thisResourcePath {
....
// Notification to reload table when a comment is submitted
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reloadTable)
name:#"Comment Submitted"
object:nil];
// Notification to reload table when an answer is liked
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reloadTable)
name:#"Answer Liked"
object:nil];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
//In custom button implementation - THIS BUTTON IS CREATED IN EVERY CELL OF THE TABLEVIEW
#implementation UICustomButton
-(id)initWithButtonType:(NSString *)type {
self = [super init];
if (self) {
//Initialization done here
}
return self;
}
- (void)buttonPressed {
if ([btnType isEqualToString:#"like"]) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"Answer Liked" object:nil];
}
else if ([btnType isEqualToString:#"comment"]) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"Comment Submitted" object:nil];
}
}
However, I realize that after using these functions for a while, the response speed of the table reload gets slower and slower (to a point where it crashes).
Did I miss out anything in the implementation i.e. deallocating etc
You are repeatedly adding observers and the slowdown occurs because the notification code has to cycle over more and more observers to send notifications. You are probably crashing because you are leaking so many of these views.
Put a log statement in your dealloc to see if these instances are ever cleaned up. Also there can be timing issues with removeObserver in a dealloc method. try to remove the observer before dealloc if you can.
Sometimes its good to queue the event with Grand Central Dispatch to make sure its running on the main thread.
dispatch_async(dispatch_get_main_queue()