Pass variable from a ViewController to a UIPopoverControllerView iOS - ios

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...
}
}

Related

Find the base view controller name

I searched for this on SO and other sites but didn't find anything useful
What I have is..
One base class say TOPViewController.h/.m
In this class I have created my controls and I am using this class on all my other views, by creating object of this class.
Say,
ViewController1, ViewController2, ViewController3 are my other views and I am using the TOPViewController on all these views.
Now My current view is ViewController2 which is visible. I jumped from ViewController1 to ViewController2.
now in my TOPViewController how I will come to know which is my current viewcontroller visible.
All the view controllers are adding TOPViewController object as [self.view addSubview:topViewObj];
Here is code of adding my TOPViewController in all views,
topBarViewObj = [[TopBarViewController alloc]init];
topBarViewObj.view.backgroundColor = [UIColor whiteColor];
topBarViewObj.view.frame = CGRectMake(0, 0, 320, 50);
topBarViewObj.titleLable.text = #"TEST";
[self.view sendSubviewToBack:topBarViewObj.view];
[self.view addSubview:topBarViewObj.view];
Please guide me for the same.
Thanks in advance..
If you want to know which is the top most UIViewController visible according to your UINavigationController (so the last UIViewController that has been pushed on your UINavigationController stack):
self.navigationController.topViewController;
if you are using UINavigationControoler
you can get baseViewController
baseViewControoer = [self.navigationController.viewControllers firstObject]
But if you did not use the following line
[self.navigationController pushViewController: animated:];
you will not get above result
as you are adding TopBarViewController's view with addSubView to your view so you just try to get the parent class by calling
`id parentClass = [self.view parentViewController]; `
and then try with
`if([parentClass isKindOfClass[ViewController1 Class]]){
// view 1
}
else if ([parentClass isKindOfClass[ViewController2 Class]])
{
// view 2
}
else if ([parentClass isKindOfClass[ViewController3 Class]])
{
// view 3
}
`
It might work for you. Let me know.

App crashes when UITableView clicked second time

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
}

UILabel is always nil

I have the following problem.
This is my Code:
GTSearchViewController* vc = [[GTSearchViewController alloc] initWithNibName:#"GTSearchViewController"
bundle:nil];
vc.headlineLabel.text = [[self.categorieArray objectAtIndex:indexPath.row] valueForKey:#"categoryName"];
[AppDelegate().centerViewController pushViewController:vc
animated:YES];
As you can see, I try to push a New ViewController with a xib File and want to set a String in my headlineLabel from my Array self.categorieArray. But when the SearchController gets pushed, everything works perfect, but my headlineLabel is always nil.
I don't understand why, I thought I don´t need to call "alloc-init" in the SearchController because everything is build with Interface Builder?
Your problem is changing UI before it actually is loaded.
You should set label's text in ViewDidLoad of your view controller (it is called after the view is loaded).
Make NSString property in your SearchViewController class and set it right after initialization.
vc.headlineText = [[self.categorieArray objectAtIndex:indexPath.row] valueForKey:#"categoryName"];
Then in SearchViewController you should override viewDidLoad method:
- (void) viewDidLoad{
[super viewDidLoad];
self.headlineLabel.text = self.headlineText;
}
P.S. Of course I assume that you've set headlineLabel outlet correctly (from Interface Builder).

UISwitch not reaction

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;
}];

How do you switch to a split view. If you don't start with one

I'm looking to find out how to switch to a UISplitView from another view. The user will click on a button and the Split View should open. I'm having no luck at all.
I start with a normal view and when the user clicks on the button i try to switch to the split view by removing the current view and initing the split view controller. I would just use a nib to load it but split views don't have nib files.
Is there anyone that can get me the simplest way to do this.
You have to create the UISplitViewController programatically. You have to give it an array of two UIViewController objects (these can be from nib files). Then when you want to load the split view you send the message [window addSubView:splitViewController.view]
i have practically done something like this.
i declared a SplitViewController in viewDidLoad at one of my viewcontroller (FrameViewController)
Then i added the splitViewController that i have just declared into AppDelegate's window variable. (i have tried declaring another UIWindow variable and add SplitViewController's view to it, it will throw wait_fences: failed to receive reply: 10004003 when u change orientation)
then, set your viewController's view to hidden so that the SplitViewController will be displayed correctly..
Voila~
- (void)viewDidLoad {
[super viewDidLoad];
appDelegate = (iPadProject2AppDelegate *)[[UIApplication sharedApplication] delegate];
ContentViewController* secondVC = [[ContentViewController alloc]
initWithNibName:#"ContentView" bundle:nil];
MenuViewController* firstVC = [[MenuViewController alloc]
initWithNibName:#"MenuView"
bundle:nil
withContentViewController:secondVC];
UISplitViewController* splitVC = [[UISplitViewController alloc] init];
splitVC.viewControllers = [NSArray arrayWithObjects:firstVC, secondVC, nil];
[appDelegate.window addSubview:splitVC.view];
[self.view setHidden:YES];}
BTW,
you should add these code into Yit Ming's code:
[[self view] removeFromSuperview];
Or the Split View will not work while you change the orientation.

Resources