This is probably simple. My UISwitch from my xib is connected to an IBOutlet "switch".
however when i create the viewController, i want to check if a variable is YES/NO, and the switch should be the correct value.
ViewController *vc = [[ViewController alloc] init];
if(variable ==YES){
[vc.switch setOn:YES];
}else{
[vc.switch setOn:NO];
}
however its always unchecked. What could i be doing wrong? i´ve double checked the connection to the IBOutlet
You aren't calling the correct method; UISwitch doesnt' have a setOn method. it has an on property and a senOn:animated: method.
either:
ViewController *vc = [[ViewController alloc] init];
vc.switch.on = variable
or:
ViewController *vc = [[ViewController alloc] init];
[vc.switch setOn:variable animated:YES];
Note, you are already checking against a BOOL, I've shown how to do it without the needless check.
This is the most common problem new developers have. Actually i had the same problem once. at that time i don't know the reason of happening this. i think now i am clear about such problems.
Let me give you some tips.
You should never access any UIView controls before presenting or pushing viewcontroller. you can access the UIView controls after presenting/pushing.
You can achieve this by setting the boolean value also. Create deafultSwitchStatus boolean property because its a boolean type this value will remain memory before viewDidLoad. and you can assign this status to your UISwitch object in viewDidLoad.
In short. UIView controls are not created/loaded before viewDidLoad method and viewDidLoad is called after preseting/pushing any controller. it means your controls are nil if you are accessing before presenting/pushing. those controls will not have any effect of your code because it will be overwritten.
Hope i explained right :)
You have created ViewController, but not presented it. So loadView was never called and yours .switch is nil.
try this:
ViewController *vc = [[[ViewController alloc] init] autorelease];
[self presentViewController:vc
animated:YES
completion:^(){
vc.switch.on = variable;
}];
Related
I've recently been updating an application to replace instances of the deprecated UIPopoverController with UIViewControllers presented modally, and when I create one, it takes about 250% as long to appear. Also, setting animated:NO in the presentViewController method also seems to have no effect.
Does anyone know why this might be?
Here's some of the relevant code I've written (it's in an IBAction from a UIButton being pressed):
UIViewController *popover = [[MyViewControllerForPopover alloc] initWithNibName:nibName bundle:nil];
popover.modalPresentationStyle = UIModalPresentationPopover;
popover.preferredContentSize = popover.view.frame.size;
popover.popoverPresentationController.sourceView = parentView;
popover.popoverPresentationController.sourceRect = location;
popover.popoverPresentationController.permittedArrowDirections = arrows;
[parentViewController presentViewController:popover animated:NO completion:nil];
I tried setting modalTransitionStyle, but it didn't seem to have any effect on the style or duration of animation. What I see is a delay, followed by the animation, so it looks like there's an extended amount of time spent setting up the view controller.
This is the same view controller that used to be put inside the UIPopover, via the initWithContentViewController init method, so I can't understand why this is slower.
Thanks
MyVC* bottle = [[MyVC alloc] initWithDelegate:self];
bottle.title = #"bottle";
if ( water == nil )
water = [[UIPopoverController alloc] initWithContentViewController:bottle];
else
water.contentViewController = bottle;
This code runs once....when I click again on UITableViewCell my app crashes..
I am unable to figure it Out Why??
ERROR
-[UIPopoverController setContentViewController:animated:] can only be called after the popover has been presented.'
NOTE When Change my code this to following it works:
MyVC* bottle = [[MyVC alloc] initWithDelegate:self];
bottle.title = #"bottle";
if ( water == nil )
water = [[UIPopoverController alloc] initWithContentViewController:bottle];
else
water = [[UIPopoverController alloc] initWithContentViewController:bottle];
But i uses memory as double allocation is present.How can I resolve this
You are making a confusion between initialisation, presentation, and content modification of your UIPopoverController.
It is OK to store your popover on an instance variable, to avoid recreating it every time. It doesn't cause any trouble either to set the contentViewController to a new instance of "Bottle" if that "water" exists already.
But your error messages says it all: -[UIPopoverController setContentViewController:animated:] : you are trying to change the content of your popover with an animation. It means, your popover must already be presented (i.e. visible). For doing so, use one of the two methods starting with presentPopoverFrom... before changing its content.
In other words, only once your popover is presented, you can animate a change of content. Note also that it makes no sense to animate a change when your popover is not yet presented / visible. Use the setter .contentViewController = for that (or the non-animated method).
A note on your edit/note: Writing the same allocation in the two branches of the if/else clause is pointless. And it doesn't cause the system to use twice memory. Because when the compiler sees the second line ("else"...), it first releases the existing instance of the popovercontroller before allocating the new one and making the "water" instance variable point to it.
If you want to push then try this
MyVC *Newpage = [[MyVC alloc] initWithNibName:#"MyVC" bundle:nil];
[self.navigationController pushViewController:Newpage animated:YES];
If you want too go back from this page i.e pop then use this
You are using wrong code.
[self.navigationController popViewControllerAnimated:YES];
There is problem in hiding the popover view. Check if presented correctly.
if (popover == nil) {
popover = [[UIPopoverController alloc] initWithContentViewController: MYVC];
popover.delegate = self;
[self.tablesPopoverController presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
Use delegate methods to check if popover is visible or not.
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
// do something now that it's been dismissed
}
Object: change the label's text in ViewControllerB
(In the ViewControllerA.m)
- (IBAction)ReturnToMenu
{
ViewControllerB *ViewControllerB =
[self.storyboard instantiateViewControllerWithIdentifier:#"ViewControllerB"];
ViewControllerB.scorelabel.text=#"WHY IS IT NOT WORKING";
[self presentViewController:GameOverViewController animated:YES completion:nil];
}
Well, this isn't working. I've exhausted all my options. This is such an elementary question, but please help me out.
P.S. #"Why is it not working" is just a temporary thing, a variable from ViewControllerA is supposed to take its place.
P.P.S. I tried out Passing Data between View Controllers, but it didn't work. I'm not sure what I'm doing wrong here
You should not try to manipulate another view controller's views directly. It's bad design, and in many cases (like yours) it doesn't work.
Instead of setting a label's text, add a string property "score". Set that after instantiating the VC.
Then, in "ViewController8"s viewWillAppear method, install the score property into the label.
Problem solved.
Here I present a modal view controller from my main view controller to show locations which I previously got from foursquare api.
LocationPickerVC *vc = (LocationPickerVC*)[self.storyboard instantiateViewControllerWithIdentifier:#"modal"];
if([vc respondsToSelector:#selector(setLocations:) ])
vc.locations = items;
[self.formSheetController presentViewController:vc animated:YES completion:nil];
[EDIT]
Make sure you set storyboard id in your storyboard (for the code below it is "modal"). Also my LocationPickerVC has this interface.
#interface LocationPickerVC : UIViewController<UITableViewDataSource, UITableViewDelegate>
#property(strong, nonatomic) NSMutableArray *locations;
#end
OK, try this:
In your ViewController1.h that the property score is declared, add this:
+ (ViewController1 *) sharedController;
In your ViewController1.m add this method:
+ (ViewController1 *)sharedController
{
static ViewController1* staticVar = nil;
if (staticVar == nil)
staticVar = [[ViewController1 alloc] init];
return staticVar;
}
Now, where ever in other ViewControllers you need something from ViewController1, import the header, and then get the property like this:
[[ViewController1 sharedController] score]
I am having problems passing a variable from a view controller to a UIPopoverViewcontroller
is the logic not the same as passing data between two usual viewControllers?
i.e setting a variable in view1 & view2 and synthesising then presenting the PopoverView pass the variable from view1 to view2?
I am really struggling with this I have read a little about protocols but seems overkill if it would work like a usual view controller?
An example
self.optionsPopover.delegate = self;
popOverViewController = [[PopOverViewController alloc]initWithNibName:#"PopOverViewController" bundle:nil];
self.optionsPopover = [[UIPopoverController alloc]initWithContentViewController:popOverViewController];
//dictionary to pass from view1 to view2 which is a popover
self.popOverViewController.statsDict = self.statsDict;
[self.optionsPopover setPopoverContentSize:CGSizeMake(320, 480)];
[self.optionsPopover presentPopoverFromBarButtonItem:optionsButton permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
There is nothing wrong in your code except you are setting delegate of popOver before creating popover. I have changed the order. And check your dictionary is nil or not
self.popOverViewController = [[PopOverViewController alloc]initWithNibName:#"PopOverViewController" bundle:nil];
//dictionary to pass from view1 to view2 which is a popover
//self.popOverViewController.statsDict = self.statsDict;
self.popOverViewController.testString = #"testing"; // This is for testing only
self.optionsPopover = [[UIPopoverController alloc]initWithContentViewController:popOverViewController];
self.optionsPopover.delegate = self;
[self.optionsPopover setPopoverContentSize:CGSizeMake(320, 480)];
[self.optionsPopover presentPopoverFromBarButtonItem:optionsButton permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
The UIPopOverViewController will allow you to show your own UIViewController (act as a container). Like a UINavigationController that receives a UIViewController. What exactly do you want to do in your UIPopoverViewController?
After initWithContentViewController, your popOverViewController's viewDidLoad method is already called (and that time the statsDict property is nil).
So either set the property before the initializer is called or write a custom setter like:
- (void)seStatsDict(NSDictionary *)statsDict
{
_statsDict = statsDict;
if (self.view) {
// Set UILabel texts, etc...
}
}
-(void)showsearch:(id)sender
{
SearchViewController *searchview =[[SearchViewController alloc] initWithNibName:#"SearchViewController" bundle:nil];
settingpopoverController = [[[UIPopoverController alloc]
initWithContentViewController:searchview] autorelease];
[searchview release];
[settingpopoverController presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
When I click on button, the app is crash and I got [UIPopoverController dealloc] reached while popover is still visible. message.
There are some good discussions on this topic here:
Retain/release pattern for UIPopoverController, UIActionSheet, and modal view controllers?
UIPopoverController and memory management
The gist of it is you need to:
assign your autoreleased popover to a retain property
set the property to nil in your view's dealloc
as well as setting it to nil in the popoverControllerDidDismissPopover.
think autorelease is incorrect, here is a tutorial
http://www.jannisnikoy.nl/index.php/2010/04/ipad-tutorial-creating-a-popoverviewcontroller
Problem is you're setting
settingpopoverController =
when you mean to do
self.settingpopoverController =
for which the autorelease would be correct. The second one uses the property accessors, the first just uses the iVar.