I have two viewcontrollers in my storyboard project. Once I click the tableview row in ViewcontrollerOne then it will display the contents of that row by passing value and settext to that labels in viewcontrollerTwo. But when I tried a third viewcontroller and by clicking the button is third viewcontroller am sending same arrayname with different values but its not displaying in the label in viewcontrollerTwo.
Why? How can I refresh the viewcontroller on viewdidload or while moving to viewcontrollerTwo ?
Currently, I add this code to viewcontrollerTwo's viewDidLoad: method.
[self.view setNeedsDisplay]
You can reload your view controller by putting this in your applicationDidBecomeActive
[yourcontroller reloadInputViews];
However, why don't you reload your tableview as you are using same tableview.
you can always use NSNotificationCenter to update your parent viewcontroller
At your parent viewcontroller put this:
//since child view controller calls turnItOff, notification center calls function "turnButtonCountinuesOff"
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(turnButtonCountinuesOff) name:#"turnItOff" object:nil];
turnButtonCountinuesOff is your function at parent viewcontroller
At your child viewcontroller put this:
//connect to parent UI view controller calls notification turnItOff.
[[NSNotificationCenter defaultCenter] postNotificationName:#"turnItOff" object:nil];
hope it helps.
Related
I have three View Controllers. Let's call them BaseVC, firstVC and secondVC. FirstVC is presented modally by BaseVC. SecondVC is pushed by firstVC. There is a one button on each firstVC and secondVC. By clicking them, I want to dismiss the current VC and let BaseVC do something. So I created a protocol, let BaseVC obey it, and set BaseVC as firstVC's delegate. When I set secondVC's delegate from firstVC, breakpoint show it succeeding. However when I call delegate from secondVC, it shows _delegate is nil.
Is it because delegate is always a weak property? So how could I pass delegate between View Controllers or is there any other way to solve this problem?
You can use postNotification while dismissing the VC and add the observer on baseVC to do some operation.
You could use [self.navigationController dismissViewControllerAnimated:YES completion:nil]; in button action to dismiss the view controller.
Before this you need to post the notification [[NSNotificationCenter defaultCenter] postNotificationName:#"NotificaitonBaseVC" object:nil]; and add the observer in baseVC's viewDidLoad method as follows
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(doSomeOperation:) name:#"NotificaitonBaseVC" object:nil];
Hi guys i have a dual viewcontroller.
My firstviewcontroller have a button and this button send NSNotification and secontviewController receive this notification and NSLOG any string.
But if i dont load secontView; my Notification is dont work ..
This codes in my firstViewController.m
-(IBAction)tapper:(id)sender {
[[NSNotificationCenter defaultCenter] postNotificationName:#"Twitter" object:nil];
}
and this codes in my secontViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector( receiveNotificaiton: ) name:#"Twitter" object:nil];
}
-(void)receiveNotificaiton: (NSNotification *) notification {
NSLog(#"TWÄ°TTER");
}
How can i load second viewDidload in first viewDidload or something else?
It sounds like you want your first view controller to present the second one. Correct?
If so you should not be using notifications. You can simply present the second view controller from the first, take a look at "Presenting View Controllers from Other View Controllers"
It's not the right way post a notification to a view controller which doesn't exist yet because (as you said) it can't execute the istruction for becoming observer. So a solution can be present the second view controller and passing the notification information. Using the notification center is a good solution if the second view controller is the top view controleller and something else post the notification. I hope i helped you.
I fixed my problem with prepareForSegue method , thx them all.
I have a UITabBarController with four tabs. In each of the view controllers presented when a tab is selected I have a reset button. Tapping the button will change the appearance of all the view controllers. In particular, it will change the text of some labels in the different view controllers.
Is there some recommended way to update all the view controllers of a UITabBarController at the same time i.e. to make them reload their views?
My current approach is to make those view controllers conform to a protocol
#protocol XYReloadableViewController
- (void)reloadContents;
#end
and then send the message -reloadContents to all the view controllers when the button is tapped:
- (IBAction)touchUpInsideResetButton {
// ...
NSArray *viewControllers = self.tabBarController.viewControllers;
for (UIViewController<XYReloadableViewController> *viewController in viewControllers) {
[viewController reloadContents];
}
}
Then in each of the view controllers I would have to implement that method:
- (void)reloadContents {
[self.tableView reloadData];
// other updates to UI ...
}
But that seems a little too complicated. So is there an easier way to tell the view controllers to reload their views?
Edit: And what happens if I present a UINavigationController in some of the tabs or a container view controller? I would need to pass the message along the chain of all its child view controllers...
You can create ReloadViewController and all you contrlollers inheritance
from him.
ReloadViewController have property UIButton and methods:
-(void)reloadContents;
-(IBAction)touchUpInsideResetButton:(id)sender;
in .m file:
-(void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reloadContents)
name:#"MyNotification"
object:nil];
}
- (IBAction)touchUpInsideResetButton:(id)sender
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"MyNotification"
object:nil];
}
in your viewControllers need only override method reloadContents
Notifications sound like a better fit for this. When view controllers need to be reset, broadcast an NSNotification and have any view controllers that might need to reset themselves listen for that notification, and trigger what they need to do. That way it doesn't matter how far down a navigation stack they are.
You might want to defer updates until the view actually appears. You could set a BOOL needsUpdate when the VCs receive the notification, but only do the actual update in viewWillAppear:, to save resources and prevent a large number of updates from going off at once (and perhaps blocking the main thread).
If this behaviour is common to all your view controllers, make a UIViewController subclass to prevent repeating code and have them all inherit from that. Alternatively, (if you're using Apple VC subclasses) make a category on UIViewController to add the notification methods.
I have 2 viewcontrollers with segue "page curl"
viewcontrollerA => pagecurl => viewcontrollerB
and Now I want to update viewcontrollerA since user make some change at viewcontrollerB.
I tryed:
UIStoryboard* sb = [UIStoryboard storyboardWithName:#"mystoryboard"
bundle:nil];
UIViewController* vc = [sb instantiateViewControllerWithIdentifier:#"ExampleViewController"];
[vc ViewDidLoad]; // or ViewWillAppear or ViewDidApear
it works only for the NSLog I put in those functions.
but none of them works with the function which check out Coredata and update the interface.
please help
try this code:
you add parent class
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(actionremovecalender:)
name:#"subMitReport"
object:nil];
-(void)actionremovecalender:(NSNotification *)notification
{
[self ViewDidLoad]
}
call child class
[[NSNotificationCenter defaultCenter]postNotificationName:#"subMitReport" object:nil]
You can send a NSNotification that the parent will receive, or you can set a delegate with a method implemented by the parent view.
In both cases, just reload the view.
In a one-to-one relation, you should prefer the delegation pattern. Just add a weak reference of viewcontrollerA to your viewcontrollerB. You can just call a method (in this case viewDidLoad method) of viewcontrollerA using the reference so you can refresh the views. But I'd prefer declaring a protocol for delegation to prevent tight coupling of two view controllers.
ViewWillApear or ViewDidApear will be called since there is any object changes in the viewcontroller, but if you want to change your viewcontrollerA from another viewcontrollerB, that require NSNotificationCenter to call the function from viewcontrollerA
you can always use NSNotificationCenter to update your parent viewcontroller
At your parent viewcontroller put this:
//since child view controller calls turnItOff, notification center calls function "turnButtonCountinuesOff"
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(turnButtonCountinuesOff) name:#"turnItOff" object:nil];
turnButtonCountinuesOff is your function at parent viewcontroller
At your child viewcontroller put this:
//connect to parent UI view controller calls notification turnItOff.
[[NSNotificationCenter defaultCenter] postNotificationName:#"turnItOff" object:nil];
hope it helps.
I need to call a delegate method on my main view controller ('showDetails:') from a popover view's pushed view (embedded in navigation controller). This is all from a storyboard setup.
The hierarchy is: Main view -> Popover (menu tableview embedded in navigation controller)->Popover secondary View (pushed onto popover navigation controller)
I know how to setup a delegate on the popover using prepareForSegue, but not on an inner view.
How can I call a delegate method on the main view from an inner (pushed) view of a popover?
Here is how I setup the delegate on a popover main view:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"segueSearchResults"]) {
//Dismiss User Popover
[self dismissUserPopover];
SearchResultsViewController *vc = segue.destinationViewController;
vc.searchDelegate = self;
self.searchPopover = [(UIStoryboardPopoverSegue *)segue popoverController];
self.searchPopover.delegate = self;
}
}
Instead Delegate i prefer "NSNotificationCenter" in your case
Add an observer to your ViewController for some action in uiview
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveActionNotification:)
name:#"someActionNotification"
object:nil];
Post Notification from your pushed View in PopOverController
Post Notification and method in your Viewcontroller will be called
[[NSNotificationCenter defaultCenter] postNotificationName:#"someActionNotification" object:self];
At the end Dont forget to remove Observer.
[[NSNotificationCenter defaultCenter] removeObserver:#"someActionNotification"];
When you need to communicate between two view controllers which are far apart in the VC hierarchy, trying to reference one from the other so you can directly call methods on it doesn't work so well -- there's several levels of indirection in between, and it's very fragile if you change your VC hierarchy later.
Look into notifications (NSNotificationCenter) instead; you can have one VC "broadcast" info for another to respond to, regardless of where they are in your app.