I am trying to send label data from one viewcontrol to be presented in another view control.
The code sends the info from the button, what I need to understand is how to send the Label info.
Opens the modal:
-(IBAction) showModal:(id)sender {
outputLabel.text=#"Nothing Chosen";
[[(ContentViewController *)self.parentViewController outputLabel]
setText:[sender currentTitle]];
switch (transitionStyle.selectedSegmentIndex) {
modalContent.modalTransitionStyle=
UIModalTransitionStyleCrossDissolve;
break;
}
[self presentModalViewController:modalContent animated:YES];
}
Received the modal back:
-(IBAction) hideModal:(id)sender {
outputLabel2.text=#"12" ;
[[(Corina3ViewController *)self.parentViewController outputLabel]
setText:[sender currentTitle]];
[self dismissModalViewControllerAnimated:YES];
}
I want to send the label info to the model. The label is "clearbLabel".
Create a label object in your modalView and set it at the - showModal: method
modalView:
// #interface
UILabel *clearLabel
// don't forget to #synthesize
-(IBAction) showModal:(id)sender {
// your code;
[modalView setClearLabel: clearLabel];
}
You can even nil it out after:
-(IBAction) hideModal:(id)sender {
// your code;
[modalView setClearLabel: nil];
}
Related
I'm checking if toViewController, which is the 2nd Tab in my tabBar, is of the class MatchCenterViewController, but the else statement is running instead, which tells me that it's not of that class.
I'm positive that the UIViewController in that tab is connected to MatchCenterViewController, so what else could cause this if statement to not work?
NSLog(#"numberOfMatches is 1");
UIViewController *toViewController = [self.tabBarController viewControllers][1];
NSLog(#"toViewController: %#", toViewController);
if ([toViewController isKindOfClass:[MatchCenterViewController class]]) {
NSLog(#"2nd matchcenter if statement works");
MatchCenterViewController *matchViewController = (MatchCenterViewController *)toViewController;
matchViewController.didAddNewItem = YES;
NSLog(#"alright they're set, time to switch");
}
else {
NSLog(#"toViewController is not MatchCenterViewController");
}
[self.tabBarController setSelectedIndex:1];
You can add NSLog(#"toViewController is of class: %#", NSStringFromClass([toViewController class]); and see the actual view controller class.
Or if didAddNewItem is a property that only MatchCenterViewController has, you can try this way:
if ([toViewController respondsToSelector:#selector(setDidAddNewItem:)]) {
// this is MatchCenterViewController
} else {
// this is not MatchCenterViewController
}
my problem is that I want to apply some settings to my running app on-the-fly.
I found a lot of tutorials on how to refresh the TableController, but this is not the case.
I have a UIViewController with some labels inside and one button, when I press the button I open as PopOver (so inside the current View) another ViewController, my settings page Controller. From here I can choose the color of the text labels and the language to apply in App.
Unfortunately I do not know how to apply this settings immediately.
Any help, with some code, would be awesome!
You should transfer instance of parent controller to popover.
func showPopover() {
var settingController = ...
var popoverController = ...
settingController.parentController = self
//show popover
...
}
In SettingController, you will have a variance parentController
Or you can refresh parent controller by override willViewAppear, didViewAppear.
Edit
(1)
#protocol MyDelegate {
-(void) refreshLable:(UIColor*)color;
}
#implement ParentController<MyDelegate> {
- (IBAction) showPopover {
ChildController *childController = ...
childController.delegate = self;
...//Show popover
}
- (void) refreshLabel:(UIColor *) color {
//Implement protocol with update label
}
}
#implement ChildController {
MyDelegate *delegate;
- (IBAction) changeColor {
Color *color=...
if (delegate != null) [delegate changeLabel:color];
}
}
(2)
#implement ChildController {
- (IBAction) changeColor {
Color *color=...
[[SystemManager instance] setColor: color];
//Here SystemManager instance if static variable
}
}
#implement ParentController {
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
//Get color from static variable
UIColor *color = [[SystemManager instance] getColor];
//Update label here
}
}
Hi I'm currently developing an app where you have a viewController with a UISwitch that i have got working with NSLog. My question is if you can change stuff in other viewControllers by creating a BOOL and then referring to that in the if statement? Heres some code:
UISwitch *mySwitch = [[UISwitch alloc] initWithFrame:CGRectMake(251, 111, 0, 0)];
[mySwitch addTarget:self action:#selector(changeSwitch:) forControlEvents:UIControlEventValueChanged];
[mySwitch setOnTintColor:UIColorFromRGB(0xac1f2d)];
[self.view addSubview:mySwitch];
- (void)changeSwitch:(id)sender{
if([sender isOn]){
NSLog(#"Switch is ON");
} else{
NSLog(#"Switch is OFF");
}
If you want to change something in another ViewController, you can do this by creating a reference to the other ViewController.
If you add public properties to the 'other' ViewController, you can change them in your if statement.
Say you have another VC, OtherViewController.
Create a BOOL property in it like:
#property(nonatomic) BOOL flag;
Implement the setter for the property in .m file of OtherViewController:
-(void)setFlag:(BOOL)flag {
_flag = flag;
if(_flag) { //if flag is true do something
//...........
}
else { //do anything else
//........
}
}
Now create a reference of OtherViewController instance in your first view controller, containing the switch. Say its referred by a property named other from the current view controller. Then you can trigger the required action on OtherViewController based on the switch's value from your present view controller like this:
- (void)changeSwitch:(UISwitch*)sender{
self.other.flag = sender.on;
}
This will call the setter of flag property in OtherViewController and would according to what you have written there.
Of course, the instance of OtherViewController should not be deallocated in between.
To expand on Stefan answer:
you would need to add property to the ViewController you want to change
so in ViewControllerA you would import the ViewControllerB header:
#import "ViewControllerB.h"
So that you can change that property in the method
- (void)changeSwitch:(id)sender{
ViewControllerB *viewcontroller = [[ViewControllerB alloc]init]];
if([sender isOn]){
viewcontroller.log = #"Switch is ON";
} else{
viewcontroller.log = #"Switch is OFF";
}
}
I'm interpreting your question to be asking whether you can change the state of another view controller using a switch on your existing view controller. The answer is yes.
You have a conditional to decide the state of the switch already. To make the connection you want to add a property to the view controller you are about to push. When you instantiate the new view controller, set the state of its property after checking if([mySwitch isOn]) (create an IBOutlet so you can check it at any time rather than responding to an IBAction), then push it. If you're going to get there via segue, you would check the state of the switch in prepareForSegue: instead.
Here's how you set the property in prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"uniqueSegueIdentifierFromIB"])
{
// Get a reference to the DestinationViewController
DestinationViewController *destinationVC = [segue destinationViewController];
// DestinationViewController has public #property (nonatomic) BOOL configurationOption;
if([mySwitch isOn])
{
[destinationVC setConfigurationOption:YES];
}
else
{
[destinationVC setConfigurationOption:NO];
}
}
}
Check the state of the new view controller's property in viewDidLoad: to decide how you want to configure it.
iOS unfortunately doesn't have a dropdown picker like html does with the tag. I decided that I was finally going to create one for my app, and it looks and works great. My dropdown object is a subclass of UITextField. However, I changed something and now it only works some of the time.
User interaction is enabled, but I don't want the textfield to be editable. The class in which my dropdown subclass resides is UITextField delegate, and should receive delegate methods for UITextField.
I have - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{ where I check to see if the textfield in question is a dropdown menu, and if it is, I call a method to instantiate a popover and disable editing, but the dropdown only appears on every other tap.
For example, i'll tap the "textfield" and my popover displays. I tap out so the popover goes away, then I tap on the "textfield" and nothing happens. I tap on the textfield once again and the popover appears. No idea why this is happening, here is what i'm doing:
.h
subclass : UIViewController<UITextFieldDelegate>
.m
dropdownTextField.delegate = self;
...
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
if(textField == self.measurementSelect){
NSLog(#"IM CALLED");
[self showPopover:textField];
return NO;
}
return YES;
}
-(void)showPopover:(id)sender{
if (_measurementPicker == nil) {
_measurementPicker = [[iPadMeasurementSelect alloc] initWithStyle:UITableViewStylePlain];
_measurementPicker.delegate = self;
}
if (_measurementPopover == nil) {
_measurementPopover = [[UIPopoverController alloc] initWithContentViewController:_measurementPicker];
[_measurementPopover presentPopoverFromRect:self.measurementSelect.frame inView:self.conversionView permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
}
else {
[_measurementPopover dismissPopoverAnimated:YES];
_measurementPopover = nil;
}
}
Every tap gets nslogged, so I assume my popover method is the culprit of this problem. Any ideas?
Let's rewrite by teasing apart existence of the UI elements and the visible state of the popover:
// canonical lazy getters for UI elements
- (iPadMeasurementSelect *)measurementPicker {
if (!_measurementPicker) {
_measurementPicker = [[iPadMeasurementSelect alloc] initWithStyle:UITableViewStylePlain];
_measurementPicker.delegate = self;
}
return _measurementPicker;
}
- (UIPopoverController *)measurementPopover {
if (!_measurementPopover) {
_measurementPopover = [[UIPopoverController alloc] initWithContentViewController:self.measurementPicker];
}
return _measurementPopover;
}
// now the show/hide method makes sense. it can take a bool about whether to show or hide
-(void)showPopover:(BOOL)show {
if (show) {
[self.measurementPopover presentPopoverFromRect:self.measurementSelect.frame inView:self.conversionView permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
} else {
[self.measurementPopover dismissPopoverAnimated:NO];
// if you want/need to create a new one each time it is shown, nil the popover here, like this:
// self.measurementPopover = nil;
}
}
When the textField begins editing, show the popover like this:
[self showPopover:YES];
And when the delegate gets the didEndEditing message:
[self showPopover:NO];
I've built a custom UITabBarController with Storyboards/Segues and UIViewController containment. Here is a link to it: https://github.com/mhaddl/MHCustomTabBarController
The UIViewControllers which will be presented by the Container are stored in a NSMutableDictionary (keys are the segues' identifiers). Everything is working fine until the point is reached where I come back to a earlier presented ViewController. At this moment "dealloc" gets called on this ViewController before it is presented.
How can I prevent "dealloc" from getting called so it can be used to unsubscribe from Notifications, and nil delegates.
MHCustomTabBarController:
#implementation MHCustomTabBarController {
NSMutableDictionary *_viewControllersByIdentifier;
}
- (void)viewDidLoad {
[super viewDidLoad];
_viewControllersByIdentifier = [NSMutableDictionary dictionary];
}
-(void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (self.childViewControllers.count < 1) {
[self performSegueWithIdentifier:#"viewController1" sender:[self.buttons objectAtIndex:0]];
}
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
self.destinationViewController.view.frame = self.container.bounds;
}
#pragma mark - Segue
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if (![segue isKindOfClass:[MHTabBarSegue class]]) {
[super prepareForSegue:segue sender:sender];
return;
}
self.oldViewController = self.destinationViewController;
//if view controller isn't already contained in the viewControllers-Dictionary
if (![_viewControllersByIdentifier objectForKey:segue.identifier]) {
[_viewControllersByIdentifier setObject:segue.destinationViewController forKey:segue.identifier];
}
for (UIButton *aButton in self.buttons) {
[aButton setSelected:NO];
}
UIButton *button = (UIButton *)sender;
[button setSelected:YES];
self.destinationIdentifier = segue.identifier;
self.destinationViewController = [_viewControllersByIdentifier objectForKey:self.destinationIdentifier];
}
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
if ([self.destinationIdentifier isEqual:identifier]) {
//Dont perform segue, if visible ViewController is already the destination ViewController
return NO;
}
return YES;
}
#pragma mark - Memory Warning
- (void)didReceiveMemoryWarning {
[[_viewControllersByIdentifier allKeys] enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop) {
if (![self.destinationIdentifier isEqualToString:key]) {
[_viewControllersByIdentifier removeObjectForKey:key];
}
}];
}
#end
MHTabBarSegue:
#implementation MHTabBarSegue
- (void) perform {
MHCustomTabBarController *tabBarViewController = (MHCustomTabBarController *)self.sourceViewController;
UIViewController *destinationViewController = (UIViewController *) tabBarViewController.destinationViewController;
//remove old viewController
if (tabBarViewController.oldViewController) {
[tabBarViewController.oldViewController willMoveToParentViewController:nil];
[tabBarViewController.oldViewController.view removeFromSuperview];
[tabBarViewController.oldViewController removeFromParentViewController];
}
destinationViewController.view.frame = tabBarViewController.container.bounds;
[tabBarViewController addChildViewController:destinationViewController];
[tabBarViewController.container addSubview:destinationViewController.view];
[destinationViewController didMoveToParentViewController:tabBarViewController];
}
#end
"At this moment "dealloc" gets called on this ViewController before it is presented." -- no, not really. Dealloc is being called on a controller that never gets on screen, not the one you came from initially or are going back to. The way your segue is set up, and the fact that you keep a reference to your controllers in the dictionary, means that they never get deallocated. Segues (other than unwinds) ALWAYS instantiate new view controllers, so what's happening is that a new instance of, say VC1 is created when you click on the first tab (and a segue is triggered), but you never do anything with that controller (which would be self.destinationViewController in the custom segue class) so it's deallocated as soon as the perform method exits.
Depending on where you setup any delegates or notification observers, this might not be a problem -- this controller that's created, and then immediately deallocated never has its viewDidLoad method called, so if you do those things in viewDidLoad, they won't ever happen for this transient view controller.
If you don't want this to happen, then you need to make your transitions in code without using segues.