how to reload tableview of another uiviewcontroller in current viewcontroller - ios

Please help me out. I am very sorry if it is duplicate but i didn't get required answer that is why i am asking again.
I want to reload table of anotherview in my first view.
Thanks in adavance.

In the first viewcontroller.m, I put this in the viewDidLoad method:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handle_data) name:#"reload_data" object:nil];
-(void)handle_data {
[yourtableview reloaddata];
}
In the second viewcontroller.m:
[[NSNotificationCenter defaultCenter] postNotificationName:#"reload_data" object:self];

Create property for UITableview with nonatomic and retain.. (view controller 1)
in View Controller 2 create object of viewcontroller 1.
now with help of viewcontroller 1 object you can access it.
Example:
In ViewController2 .m file:
ViewController1 *objV1 = [ViewController1 alloc]initWithNibName....];
[objV1.yourTableView reloadData];

Do it in below way:
Suppose you have 2 view controller.
ViewController1
ViewController2
And you have UITableView object tblTable in ViewController2.
in ViewController2.h file:
#property(nonatomic, retain) UITableView *tblTable;
in ViewController2.m file:
#synthesize tblTable;
Now in in ViewController1.m file:
ViewController1 *objV1 = [ViewController1 alloc]initWithNibName....];
[objV1.tblTable reloadData];
I hope it will be helpful to you.
Let me know in case of any difficulty.
Cheers.

I had similar issue and I was using storyboard this is how I fixed it. Suppose u want to reload the table which is in ViewController2 from a function in ViewController1. Do the following:
#import "ViewController2.h"
Now put this code in the function or any button action under which u want to reload
ViewController2 *ob= (ViewController2*)[self.navigationController topViewController];
[ob.viewController2Table reloadData];

Related

Refresh table from another UIViewController

I have two view controllers one of them (ViewController) has a table called tableView.
I would like to refresh this table from my other view controller (pageView).
I have tried this in the pageView:
ViewController*refresh;
[refresh.tableView reloadData];
But this is not working.
The connecting segue between the two view controllers is a push segue
What should I do? Should I do it through a storyboard segue?
Option 1
#Class2
#property (nonatomic) BOOL shouldRefresh; // in .h file
- (void)viewWillAppear:(BOOL)animated // in .m file
{
[super viewWillAppear:animated];
if (_shouldRefresh) [self.tableView reloadData];
}
#Class1
// Add this in any method where you want it to refresh and push to view
ClassTwoController *viewController = [[ClassTwoController alloc] init];
[viewController setShouldRefresh:YES];
[self.navigationController pushViewController:viewController animated:YES];
*UPDATE:
Option 2
#Class 2
// Add this line in viewDidLoad in same class you want the tableView to refresh
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(refreshTableWithNotification:) name:#"RefreshTable" object:nil];
// Add this method just beneath viewDidLoad:
- (void)refreshTableWithNotification:(NSNotification *)notification
{
[self.tableView reloadData];
}
#Class1
// Call this when ever you want to refresh the tableView in Class2
[[NSNotificationCenter defaultCenter] postNotificationName:#"RefreshTable" object:nil userInfo:nil];
/* Add this line in viewDidLoad method in ViewController (by using this line you are adding notification observer to ViewController class) */
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reloadTableview:) name:#"ReloadTableview" object:nil];
/* Add this method in ViewController class(this method call when you post notification in pageView) */
- (void)reloadTableview:(NSNotification *)notif
{
[tableView reloadData];
}
/* add this line when/where you want to refresh your (this line post notification which added in ViewController) */
[[NSNotificationCenter defaultCenter] postNotificationName:#"ReloadTableview" object:nil];
If second view controller is already loaded then you can use NSNotification in firstviewcontroller. This notification will invoke a method in second view controller. In this method write a code to reload a tableview.
If I understand correctly, you want to reload a table view that exists in the previous view controller of your navigation stack. If so, you can access it through the navigation controller's viewControllers property.
NSUInteger indexOfTableController = self.navigationController.viewControllers.count - 2;
ViewController *tableController = (ViewController*)[self.navigationController.viewControllers objectAtIndex:indexOfTableController];
[tableController.tableView reloadData];
Most often this happens because you're not initializing the reference to your second controller properly and it stays nil. Has to be something like this.
#implementation
{
ViewController *refresh;
}
- (void) openNewController
{
refresh = [[ViewController alloc] init];
[self.navigationController pushViewController:refresh animated:true];
}
- (void) refreshNewController
{
[refresh.tableView reloadData];
}
#end
Okay for sake of example lets call the previous ViewController VC1 and the current ViewController VC2.
So you do a push segue from VC1 to VC2. What you could do is: pass a reference of the TableView to VC2 during the segue. So you would create a public UITableView tblView variable in VC2 and then in VC1 implement the prepareForSegue method
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"Segue_Identifier_From_StoryBoard"])
{
// get your destination view controller
VC2 *vc2 = [segue destinationViewController];
vc2.tblView = TableView;
}
}
Then in VC2, you could just call [tblView reloadData];
Just make sure you nil the tblView reference once you are done with VC2.
In ViewController1 :
> Create property for UITableview with nonatomic and retain
> Now Create table Object.
In ViewController2.m:
ViewController1 *objV1 = [ViewController1 alloc]initWithNibName....];
[objV1.yourTableView reloadData];
You can check the adress of viewcontroller.tableview and refresh.tableView and i think they would be not the same;
you can make singleton for viewcontroller and then invoke for example
viewcontroller *vc = [viewcontroller sharedInstance];
[[vc tableview] reloadData];
In your pageView create a method
-(void) reloadVCController{
ViewController*vc=[[ViewController alloc]init]];
[vc.tableview reloadData;
}
And use it where you want to call it
[self reloadVCController];
ViewController*refresh;
[refresh.tableView reloadData];
By seeing the above code you are not assigning your ViewController instance to refresh. When executing reloadData() your refresh will be nil so obviously it won't react to any action.
ViewController*refresh = originalInstance; //assign your original instance here
[refresh.tableView reloadData];
this would work and the main point to be noted here is your refresh viewcontroller should be the top most instance in stack because any UI operation should happen in main thread.
Use NSnotification center add observer in that view controller and write method for reload table.
[self.tableView reloadData];
And from current view post notify that observer.
In case you have tried all the answers, make sure that before reloading the tableView, the dataSource is actually updated with new/additional/ content.
Reloaddata needs to execute within the parentviewcontroller because it invokes the tableview delegate methods to reload the table such as CellForRowAtIndexpath, and many more.
This means you need to define a public method in the parentviewcontroller that will contain the reloaddata command and call it from the child view controller.
public Method:
Parentviewcontroller.h
#interface
-(void) reloadTable:(id) sender;
parentviewcontroller.m
#implementation
- (void) reloadTable:(id) sender {
[self.tableview reloaddata];
return;
}
childviewcontroller.h
#import parentviewcontroller.h
#class parentviewController
#interface childviewcontroller :UIViewController (or UITableViewController)
#property (nonatomic, strong) parentViewController *parent;
childviewController.m
#implementation
#synthesize parent;
/* Note the parent instance is passed from the parent to the child view controller,
it is not allocated and initialised in the child controller - many ways to do this
depending on coding style */
/* after updating the data */
[parent reloadTable];
I think the problem is that you refresh controller view is not loaded. So, reloadTable message simply goes to nil. You can force a View Controller to load its view by calling view getter:
[viewController view];
So check if your tableView is nil and if it is, initialise it with described method.
As a make-up answer to emotality's:
If you want to skip the start-up animation, just simply set a bool property in your ClassTwoController to check if it's first time loading this view
ClassTwoController.h:
#property (nonatomic, assign) BOOL notFirstTimeRun;
ClassTwoController.m:
-(void)viewWillAppear:(BOOL)animated // in .m file
{
if(self.notFirstTimeRun) {
[self.tableView reloadData];
} else {
[self playStartUpAnime];
}
}
-(void)playStartUpAnimation // in .m file
{
//Place your codes for animation here
}
in your ClassOneController.m initialise it with the check bool:
ClassTwoController *viewController = [[ClassTwoController alloc] init];
viewController.notFirstTimeRun = YES;
If you have parent-child relationship you can add weak property to child viewcontroller like this
#property (nonatomic, weak) ParentViewController *parentController;
Then when you need to reload table you just call [parentController.tableView reloadData]
Other way would be using NSNotificationCenter. In controller you want to reload table you should subscribe to notification([[NSNotificationCenter defaultCenter] addObserver...]) and implement selector you supply to this method. In another controller you should post notification with that name.
Also you can just refresh on viewWillAppear if it suits your needs.

How can I pass data between two View Controllers in a Navigation Controller, with two Push Segue?

I have two view controllers inside a Navigation Controller.
In the first view controller I have two buttons. Both of them call the second view controller using a Push segue, but:
I need to know which button sent me in the second view controller. How?
In the second view controller I have a UIDatePicker and a Button "Ok": how can I send the chosen date to the first view controller when Ok is pressed? (And how do I receive them?)
EDIT:
I don't know if my problem is clear: now I know how to pass data from the first view controller to the second view controller with prepareForSegue, but what I really need is to pass data (the picked date) from the second view controller to the first, and how can I do it without a prepareForSegue (when Ok is pressed)?
EDIT2:
I made it. It was so simple, guys...
I decided to use modal segue:
Firstviewcontroller.h:
+(FirstViewController *)getInstance;
Firstviewcontroller.m:
static FirstViewController *instance =nil;
+(FirstViewController *)getInstance
{
return instance;
}
and in its ViewDidLoad:
instance = self;
Secondviewcontroller.m, in the OkButton IBAction:
SecondViewController *secondViewController = [SecondViewController getInstance];
//...
//modify what I need to modify in secondviewcontroller
//...
[self dismissModalViewControllerAnimated:YES];
That's it.
Thank you all anyway.
Assign Identifier to each segue in storyboard and implement
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"YOUR_SEGUE_NAME_HERE"])
{
// Get reference to the destination view controller
YourViewController *vc = [segue destinationViewController];
[vc setDelegate:self];
// Pass any objects to the view controller here, like...
[vc setMyObjectHere:object];
}
}
For more info about How to use storyboard and pass value check this article or this discussion on stackoverflow
for the second question you can use delegate pattern
IN SecondViewController.h
#protocol SomethingDelegate <NSObject>
- (void)dateChanged:(NSString *)dateStr; //you can use NSDate as well
#end
#interface ViewController2 : UIViewController
#property(weak) id<SomethingDelegate> delegate;
#end
in .m file
-(void) OkClicked{
[_delegate dateChanged:#"YOUR_DATE_VALUE"];
}
In FirstViewController.h
#import "SecondViewController.h"
#interface FirstViewController : UIViewController<SomethingDelegate>
in .m
-(void)dateChanged:(NSString *)dateStr{
// do whatever you need with dateStr
//also i made some change in prepareForSegue method
}
Note:- take care your naming convenes for VC
just pass the button id to the second viewcontrol.
use delegates to sent the data from second viewcontroller back to first view controller
regards
Johan

Xcode 5, How do I call a method when the user leaves the app?

Hello I do not have very much programming experience and I'm trying to call a method when the user leaves the app. I know that I am going to use the app delegate methods applicationDidEnterBackground, but how do I make that call a method that is in my ViewController class?
Thanks so much for any help!
ViewController.h:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <ADBannerViewDelegate>
{
//Images and buttons
}
-(void)stop;
#end
You can use a notification here. Create a listener for this notification in the viewDidLoad of the viewController and assign the function to it.
eg:
in yourView controller add the following in the viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(notificationEnabled) name:UIApplicationDidEnterBackgroundNotification object:nil];
You can either
observe UIApplicationDidEnterBackgroundNotification inside your ViewController, or
invoke your ViewController method inside appDelegates applicationdidEnterBackground: method. App delegate should have a pointer that points to the rootViewController, ie: your ViewController
goodluck!
edit:
...
-(void)applicationDidEnterBackground:(UIApplication *)application {
UIViewController *uvc= [UIApplication sharedApplication].keyWindow.rootViewController;
ViewController *myvc = (ViewController*) uvc;
[myvc stop];
}
.
When you close or leave your App, AppDelegate methods automatically called, you not need to call them in some specific ViewController.
For doing something when your App is in background you can implement your logic in AppDelegate's applicationDidEnterBackground: method.
Or if your App is not running(means closed) AppDelegate Method didFinishLaunchingWithOptions: is called.
I didn't get the purpose of calling the method inside UIViewController. Eventhough you can create an instance of your viewcontroller inside applicationDidEnterBackground and call the corresponding method in viewcontroller using that object
you can do this by creating an instance of that View and then calling specific method of that view
otherwise if your view is opened then you can find it by follwing code & then call specific method by using that obj as follow in your applicationDidEnterBackground
NSArray *AllViewControllers = [self.navigationController viewControllers];
for (UIViewController *aViewController in AllViewControllers) {
//NSLog(#" >> Nav Stack %#", [aViewController class]);
if ([aViewController isKindOfClass:[YourViewController class]]) {
[(YourViewController *)aViewController yourMethodToCall];
break;
}
}

Update tableView data

I have a UITableView embedded in a UIView that I can't figure out how to update. When I come to this page with the UITableView embedded in the UIView there's a button that when pressed brings up a modalForm. There is a textField that the user enters a name into and then presses another button to "Create" the object, dismiss the modalForm, and update the app data. However, I'm not sure how to refresh my UITableView data… Is there a way to tell the UITableView to refresh when the modalForm view is dismissed?
EDIT: I know i need to send this message [tableView reloadData]; in order to refresh, but I'm wondering where I can put it so it gets called upon dismissal of the modalForm?
In the view controller that is presenting and dismissing the modal, you should be calling the dismissViewControllerAnimated:completion method to dismiss the modal. The modal should not dismiss itself. You can use a completion block to execute whatever code you would like that will execute when the modal is finished dismissing. Example below.
[self dismissViewControllerAnimated:YES completion:^{
//this code here will execute when modal is done being dismissed
[_tableView reloadData];
}];
Of course don't forget to avoid capturing self strongly in the block.
If you end up having the modal dismiss itself, you will need either a delegate method so the modal can communicate back to the presenting view controller, or a notification sent by the modal and captured by the presenting view controller, or you could implement viewWillAppear: in the presenting view controller. This method will fire everytime the view is about to appear. Which means the very first time as well as after a modal is dismissed and is about to show the view it was presenting over top of.
----------------------------------------------------------------------------------------
Below is an example of writing your own protocol and using it.
MyModalViewController.h
#protocol MyModalViewControllerDelegate <NSObject>
//if you don't need to send any data
- (void)myModalDidFinishDismissing;
//if you need to send data
- (void)myModalDidFinishDismissingWithData:(YourType *)yourData
#end
#interface MyModalViewController : UIViewController
#property (weak) id <MyModalViewControllerDelegate> delegate;
//place the rest of your properties and public methods here
#end
The where ever you want to in your MyModalViewController implementation file, call your delegate method of choice. You should first make sure your delegate actually responds to the selector though.
MyModalViewController.m
if ( [self.delegate respondsToSelector:#selector(myModalDidFinishDismissing)] )
[self.delegate myModalDidFinishDismissing];
In your viewcontroller that is presenting the modal, you need to state in the header file that you conform to the protocol, you need to set the delegate of the modal as the viewcontroller, and make sure you actually implement the delegate method you intend on using.
MyPresentingViewController.h
#interface MyPresentingViewController : UIViewController <MyModalViewControllerDelegate>
MyPresentingViewController.m
myModal.delegate = self;
- (void)myModalDidFinishDismissing {
//do something
[tableView reloadData];
}
You can have a delegate variable in your modal form class. When you dismiss your modal form, you can call something like [delegate performSelector:#selector(modalFormClosed)] which calls the [tableView reloadData].
#interface ModalForm : UIViewController
#property (nonatomic, weak) id delegate;
#end
#implementation ModalForm
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.delegate performSelector:#selector(modalFormClosed)];
}
#end
In your class that uses the ModalForm:
myModalForm.delegate = self;
And make sure you have the modalFormClosed method too:
- (void)modalFormClosed {
[self.tableView reloadData];
}
Or you can send a NSNotification (look into NSNotificationCenter) when your modal form disappears.
I wish I had the reference, but some years ago I saw a note from Apple saying a modal view should never dismiss itself. Instead you call a method on a presenting view controller. In this method the presenter dismisses the modal view controller. Typically I put a category on my UIViewControllers:
#interface UIViewController (Extension)
-(void)simpleDismissAnimated:(BOOL)animated;
#end
#implementation UIViewController (Extension)
-(void)simpleDismissAnimated:(BOOL)animated {
[self dismissViewControllerAnimated:animated completion:nil];
}
Either include it in all your view controller subclasses, or in your pch file.
So have your modal view controller call:
[self.presentingViewController simpleDismissAnimated:YES];
Then in your presenting view controller, override the implementation of simpleDismissAnimated: to something like:
-(void)simpleDismissAnimated:(BOOL)animated {
[_tableView reloadData];
[self dismissViewControllerAnimated:animated completion:nil;
}
That should take care of it.
Try this line:
[self.tableView reloadData];
You can try putting [tableView reloadData] in viewWillAppear method where your tableView is.
I had the same problem. ReloadData didn't work me. I solved it so that i made new method like this:
- (void)insertNewString:(NSString *)text{
if (!_yourArrayWithData) {
_yourArrayWithData = [[NSMutableArray alloc] init];
}
[_yourArrayWithData insertObject:text atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
and when i want to add something to tableView, i use button with action like this:
- (IBAction)SaveNewPhrase:(id)sender {
NSString *mainText = _NewPhraseTextView.text; //I take nsstring from textView
if([mainText isEqual:#""]){
return;
}else{
NSMutableArray *contentFile = [NSArray arrayWithContentsOfFile:docPathContents()];
NSMutableArray *copyContentFile = [[NSMutableArray alloc] init];
//save array with new item
[copyContentFile addObject:mainText];
[copyContentFile addObjectsFromArray:contentFile];
[copyContentFile writeToFile:docPathContents() atomically:YES];
[self insertNewString:mainText]; //refresh tableView
[_NewPhraseTextView resignFirstResponder];
}}
I hope, that it helps.

Updating uilabel in view controller underneath another

I have two view controllers, FirstViewController and FourthViewController. FirstViewController is my initial view controller. I present FourthViewController with
UIViewController *fourthController = [self.storyboard instantiateViewControllerWithID:#"Fourth"];
[self presentViewController:fourthController animated:YES completion:nil];
Then, in FourthViewController's .m I'd like to change the text of a UILabel in FirstViewController. So I use
UIViewController *firstController = [self.storyboard instantiateViewControllerWithID:#"First"];
firstController.mainLab.text = [NSMutableString stringWithFormat:#"New Text"];
However, after I use
[self dismissViewControllerAnimated:YES completion:nil];
I find that my mainLab's text has not updated. Does anyone know why?
When you are calling this line from FourthViewController.m you are actually creating a new instance of FirstViewController, rather than using the already created one.
UIViewController *firstController = [self.storyboard
instantiateViewControllerWithID:#"First"];
You can tackle this in two ways.
1) Using notification
post a notification from FourthViewController when label text need to be changed.
[[NSNotificationCenter defaultCenter] postNotificationName:#"updateLabel"
object:self];
In your FirstViewController viewDidLoad methodcreate an observer that waits for this notification to get fired.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(updateLabelCalled:)
name:#"updateLabel"
object:nil];
Implement updateLabelCalled: and update label.
- (void) updateLabelCalled:(NSNotification *) notification
{
if ([[notification name] isEqualToString:#"updateLabel"]){
//write code to update label
}
}
2) Implementing delegate
It is already explained here in stackoverflow. The basic idea is you create a FourthViewController delegate, and create a delegate method to updateLabel. FirstViewController should implement this method.
If you want to update the label on first screen and nothing else then go for notifications. It's better rather you write the delegate. Because you want to update only label text thats it.

Resources