Right now, in FirstviewController, I got a button, when i clicked it, I get the value back using delegate. Right now, I want to send this value to SecondViewcontroller and reload it's tableview data. How to do that? How about use nsnotificationcenter, but i have tried, it's not working. I post the notification in the delegate that implemented in Firstviewcontroller. the code like this:
FirstviewController.m
// delegate that get selected cat
- (void)didSelectSubCat:(SubCat *)cat;
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"DidSelectCat" object:self userInfo:#{#"catId": cat.catId}];
}
SecondViewcontroller.m
- (void)awakeFromNib
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(selectedCat:) name:#"DidSelectCat" object:nil];
}
- (void)selectedCat:(NSNotification *)notif
{
NSLog(#"userinfo: %#", [notif userInfo]);
}
In SecondViewCOntroller create protocol with a methode
#protocol TeamListViewControllerDelegate <NSObject>
-(void)SecondViewController:(SecondViewController*)teamListViewController data:(NSString*)data
#end
declare delegate
#property(nonatomic,assign) id<TeamListViewControllerDelegate> delegate;
In firstViewcontroller follow that protocol and implement that method and inside that method refresh table.
I hope this will help.
Related
I have a VideoListController. It has list of videos with download button. When I press the download button, the control is transferred to DetailViewController. In DetailViewController, I am using AFNetworking to download file.
If I go back to VideoListController from DetailViewController. How can I know progress of download or when download gets completed from VideoListController. I want to know this because based upon that I will reload the list to show play button instead of download.
I think that the best solution for your problem would be to create a custom delegate protocol that the DetailViewController and the VideoListController can use to communicate with each other. Check this post for additional information How to use custom delegates in Objective-C
In a nutshell the strategy is the following:
1. The DetailViewController defines a delegate protocol that it uses to pass events to its delegate
2. The VideoListController becomes the delegate to that it knows whenever an upload has progressed or been completed
3. The VideoListController keeps track of which DetailViewControllers have completed the download
Here is come code:
DetailViewController.h:
#class DetailViewController;
#protocol Delegate <NSObject>
- (void) detailViewController: (DetailViewController *) theDetailViewController didFinishDownloadingVideoWithResults:(BOOL)successful;
#end
#property (nonatomic, weak) id<DetailViewController> delegate;
DetailViewController.m:
Whenever a download is complete do the following:
if ([[self delegate] respondsToSelector:#selector(detailViewController:didFinishDownloadingVideoWithResults:)]){
[[self delegate] detailViewController:self didFinishDownloadingVideoWithResults:YES];
}
Now, in the VideoListController.m make sure you establish yourself as the delegate of the DetailViewController.
[theDetailViewController setDelegate:self];
And implement the delegate method. You can for instance have a dictionary that defines which DetailViewControllers have completed the download:
- (void) detailViewController: (DetailViewController *) theDetailViewController didFinishDownloadingVideoWithResults:(BOOL)successful{
detailViewControllersDownloadInformation[theDetailViewController] = #(successful);
}
Now, whenever you need to check if a DetailViewController did indeed complete a download, all you have to do is check that dictionary
if (detailViewControllersDownloadInformation[theDetailViewController] && detailViewControllersDownloadInformation[theDetailViewController] == #(YES)){
// Did download a video
}
Keep in mind that the solution I provide will only let you know if the download has been completed. If you also want to keep track of the progress you need to pass that as an additional parameter in the delegate. We are also assuming that you keep all of the DetailViewControllers in memory. If you release and reuse them you will need to keep track of which element was downloaded in a different data structure.
I got it working using NSNotificationCenter.
In viewDidLoad of DetailViewController, I added this
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieDownloadDidFinish)
name:#"MovieDownloadDidFinishNotification"
object:nil];
When download gets complete. I call this:
[[NSNotificationCenter defaultCenter] postNotificationName:#"MovieDownloadDidFinishNotification" object:self];
I remove the observer from DetailViewController when when backbutton in navigation controller is clicked
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"MovieDownloadDidFinishNotification" object:nil];
And added method in DetailViewController that is called when download gets completed.
-(void) movieDownloadDidFinish {
NSLog(#"MovieDownloadDidFinish on DetailViewController");
}
Now in viewDidAppear of VideoListController, I added the observer
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieDownloadDidFinish)
name:#"MovieDownloadDidFinishNotification"
object:nil];
And in viewDidDisappear Of VideoListController, I remove the observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"MovieDownloadDidFinishNotification" object:nil];
And added method in VideoListController that is called when download gets completed.
-(void) movieDownloadDidFinish {
NSLog(#"MovieDownloadDidFinish On VideoListController");
}
In this way, when DetailViewController is visible, the method movieDownloadDidFinish of DetailViewController is called and similarly movieDownloadDidFinish of VideoListController is called when VideoListController is visible.
I have a modalViewController that comes up over the top of a viewController with a tableView. When the user clicks a button on the modalViewController I want to reload the tableView within the viewController with this:
[tableView1 reloadData];
I do not want to put the reload in the viewDidAppear or viewWillAppear methods as they get called when i do not need the tableView to reload (i.e. when the user clicks the back button to return to the tableView).
Is there a way to do this?
Try
1) write one method which reloads the table data.
2) Call it on the back button clicked.
This is the classic delegate pattern problem, in your modal view controller you need a delegate reference to the current view controller presenting it
//Modal
#protocol ModalVCDelegate
- (void)tappedBackButton;
#end
#class ModalVC: UIViewController
#property id<ModalVCDelegate> delegate;
#end
#implementation
- (void)backButtonTapped:(id)sender
{
if (self.delegate)
[self.delegate tappedBackButton];
}
#end
Now, in your presenting VC, just process this delegate message
//Parent VC
- (void)showModal
{
ModalVC *vc = [ModalVC new];
vc.delegate = self;
//push
}
- (void)tappedBackButton
{
[self.tableView reloadData];
//close modal
}
You can use delegate . If find it more harder then alternative is to use NSNotificationCenter. You can see accepted answer for Refreshing TableView. This is really very short, easy and understandable way.
using Notification like bellow Method:-
Create NSNotificationCenter at yourViewController's ViewdidLoad Mehod
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(ReloadDataFunction:)
name:#"refresh"
object:nil];
[super viewDidLoad];
}
-(void)ReloadDataFunction:(NSNotification *)notification {
[yourTableView reloadData];
}
Now you can Call this Notification from your modelViewController BackButton or else you want from calling this Refresh notification like putting this line of code:-
[[NSNotificationCenter defaultCenter] postNotificationName:#"refresh" object:self];
NOTE: postNotificationName:#"refresh" this is a key of particular Notification
Try to use this one
Make a Button and click on this button and than you can reload your data.
This button make custom and use it on background.
- (IBAction)reloadData:(id)sender
{
[tblView reloadData];
}
You can use NSNotification to refresh table on ViewController.
Inside viewController :
-(void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
Write code in viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reloadMainTable:)
name:#"ReloadTable"
object:nil];
- (void) reloadMainTable:(NSNotification *) notification
{
[tableView reload];
}
Inside ModelViewController:
[[NSNotificationCenter defaultCenter]
postNotificationName:#"ReloadTable"
object:nil];
Here you can also send custom object instead of nil parameter. But be care full about removal of NSNotification observer.
I have a project i'm working on which involves 3 tabs in a UITabBarController (all done in a storyboard).
Each tab is running off a different view controller.
I have a button on tab 1 that performs a calculation and returns a result in a text box. I want it so that when I hit calculate, the result is also returned in a text box in tab 2.
I'm not really sure how to pass data between UIViewControllers so any help is appreciated.
as per vshall says you can do this stuff like bellow:-
yourAppdelegate.h
#interface yourAppdelegate : UIResponder <UIApplicationDelegate,UITabBarControllerDelegate>
{
NSString *myCalResult;
}
#property (nonatomic,retain) NSString *myCalResult;
yourAppdelegate.m
#implementation yourAppdelegate
#synthesize myCalResult,
yourCalclass.h
#import "yourAppdelegate.h"
#interface yourCalclass : UIViewController
{
yourAppdelegate *objAppdelegate;
}
yourCalclass.m
- (void)viewDidLoad
{
objAppdelegate = (yourAppdelegate *) [[UIApplication sharedApplication]delegate];
[super viewDidLoad];
}
-(IBAction)ActionTotal
{
objAppdelegate.myCalResult=result;
}
Now you result stored in objAppdelegate.myCalResult you can use this variable in your another tab with creating object of yourAppdelegat. Hope its helps you
You can define a variable in app delegate and store the result in that variable for class one. And once you switch the class you can fetch that value in your class two by creating an instance of your appDelegate and assign it to your textfield.
As Sanjit has suggested, NSUserDefaults is also a very convenient and clean way to achieve this.
Thanks.
If you don't really need to store the computed value but just notify the other controller in tab2 that the value changed, you can use NSNotificationCenter to post an NSNotification.
When you initialize the controller in tab2 you'll need to add it as an observer of the notification.
Something like that:
in tab1:
NSNumber *value = nil; // the computed value
[[NSNotificationCenter defaultCenter]
postNotificationName:#"com.company.app:ValueChangedNotification"
object:self
userInfo:#{#"value" : value}];
in tab2: register as an observer (in init or viewDidLoad methods)
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(valueChanged:)
name:#"com.company.app:ValueChangedNotification"
object:nil];
the method that will be called when the notification is posted:
- (void)valueChanged:(NSNotification *)note
{
NSDictionary *userInfo = note.userInfo;
NSNumber *value = userInfo[#"value"];
// do something with value
}
Don't forget to remove the controller from the observers in viewDidUnload or sooner:
[[NSNotificationCenter defaultCenter] removeObserver:self];
I do have two ViewController class, one firstviewController other secondViewController in first viewcontroller i call this [self dimissModalViewControllerAnimation:NO];
to dimiss the view! now i need to dimiss the same view from another secondViewController class.
So do i need to call super in that!
[super dismissModalViewControllerAnimated:NO];
Or Do i need to create any protocol for dismissing the view! from another secondViewController class.
Can any guide me with this issue.
you can register a notification in firstViewController's viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleNotification:) name:#"MyNotification" object:nil];
Add the event handler in firstViewController
- (void)handleNotification:(NSNotification*)note {
[self dismissModalViewControllerAnimated:NO];
}
Then you can trigger the event in secondViewController
[[NSNotificationCenter defaultCenter] postNotificationName:#"MyNotification" object:nil ];
You should only be using super when you're overloading a method definition, e.g.:
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Login / Signup";
}
Typically, if you're trying to tell one view to do something from another view, delegates are your friend. You could create a weak delegate variable to hold a reference to the view controller to be dismissed, and call [delegate dismissModalViewControllerAnimated:NO];
I have a UIViewController that has an UIPopoverController that has an UINavigationController then a UIViewController. How can I from the child UIViewController call a method (eg. -(void)update) in the parent UIViewController? tried many combinations but still didn't work.
In your child:
#interface MyChildController:UIViewController {
MyParentController *parent;
}
#property(nonatomic, assign) MyParentController *parent;
#end
#implementation MyChildController
#synthesize parent;
...
In your parent controller, when instantiating your child:
MyChildController *newChild = [[[MyChildController alloc] initWithNibName:nil bundle:nil] autorelease];
newChild.parent = self;
...
now in your child you have a ref to your parent that you can use. For instance, some method in your child:
- (IBAction)someAction {
[self.parent doSomethingParentsDo];
}
One possible approach would be to use NSNotificationCenter. In the viewDidLoad: method of the parent ViewController, register it as an observer of a certain notification (I'll use #"DummyNotification" as the notification name in my example). Then post that notification from the appropriate method in the child ViewController. The result will look something like this:
ParentViewController.m
- (void) viewDidLoad
{
/* existing code */
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(update) name:#"DummyNotification" object:nil];
}
- (void) update
{
//method body
}
ChildViewController.m
//put this line wherever you want the ParentViewController to call -update
[[NSNotificationCenter defaultCenter] postNotificationName:#"DummyNotification" object:self];
Reference:NSNotificationCenter Class Reference
Also, this question is tagged as iPhone, but Apple's UIPopoverController documentation states that the class is used specifically for iPad, and will not work on other devices. Is this question tagged wrong?
Reference: UIPopoverController Class Reference