Really simple question i think.
i have a main view and a popover view.
i am trying to make a custom delegate which will enable me to close the popover view at certain times. My code is posted below. The real simple issue i am having is my code dosnt appear to be entering the delegate code. Any ideas as to why? It builds and runs but nothing appears to happen, i have put NSLog statments, the popover nslog appears but the function in
mainview dismissPopover does nothing.
Mainview.h
#interface MainScreen : UIViewController<DismissPopoverDelegate>
Mainview.m
- (void) dismissPopover:(NSNumber *)dataa
{ /* Dismiss you popover here and process data */
[popoverController dismissPopoverAnimated:YES];
NSLog(#"OLOLO");
}
Popover.h
#protocol DismissPopoverDelegate
- (void) dismissPopover:(NSNumber *)yourDataToTransfer;
#end
#interface SelectAgePopOver : UIViewController<UITableViewDataSource,
UITableViewDelegate,UIPopoverControllerDelegate>{
NSArray *items;
id<DismissPopoverDelegate> delegate;
}
#property (nonatomic, assign) id<DismissPopoverDelegate> delegate;
Popover.m
[self.delegate dismissPopover:selrow];
where i want the delegate called.
Thanks
the popover view is called by the following method in main view.m
controller = [[SelectAgePopOver alloc] initWithNibName:#"SelectAgePopOver" bundle:nil];
popoverController = [[UIPopoverController alloc] initWithContentViewController:controller];
[popoverController setDelegate:self];
popoverController.popoverContentSize = CGSizeMake(250, 294);
if ([popoverController isPopoverVisible]) {
[popoverController dismissPopoverAnimated:YES];
} else {
CGRect popRect = CGRectMake((self.AgeRangeTextField.frame.origin.x+50),
(self.AgeRangeTextField.frame.origin.y+50),
(self.AgeRangeTextField.frame.size.width),
(self.AgeRangeTextField.frame.size.height));
[popoverController presentPopoverFromRect:popRect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
}
On where you instantiate the instance of the SelectAgePopOver, you need to set the delegate of the SelectAgePopOver instance to the MainScreen (self) in the Mainview.m, for example:
controller = [[SelectAgePopOver alloc] initWithNibName:#"SelectAgePopOver" bundle:nil];
;
controller.delegate = self;
Please try to set the controller delegate as shown above.
In the SelectAgePopOver.h class file, you do not need to set UIPopOverControllerDelegate though.
Related
I have two class, PresentViewController and ModalViewController, In PresentViewController I call the ModalViewController in this format:
ModalViewController *targetController = [[ModalViewController alloc] init];
targetController.modalPresentationStyle = UIModalPresentationFormSheet;
targetController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:targetController animated:YES completion:nil];
// it is important to do this after presentModalViewController:animated:
targetController.view.superview.bounds = CGRectMake(0, 0, 400, 218);
In ModalViewController, I have a button who send a parameter to the class PresentViewController:
-(IBAction)apply{
PresentViewController *infoViewController = [[PresentViewController alloc] init];
[infoViewController setDiscount:[campoDesconto.text intValue]];
[self dismissViewControllerAnimated:YES completion:nil];
}
In PresentViewController the method setDiscount is as follows:
-(void)setDiscount:(int)value{
NSLog(#"Method is called!");
totalPrice.text = value;
}
This method is being called because I get a console message, but unfortunately this UILabel not updating your value, why this is happening and how can I solve?
When you call apply method, you haven't setup the view of infoViewController yet.
So you probably haven't created the totalPrice label yet, if you do NSLog(#"totalPrice: %#", totalPrice); in setDiscount:, it will probably output (null). You should save the discount value as a property, and set it in viewDidLoad as well as when setDiscount: method is called.
You're also setting an int to a NSString, this isn't correct.
PresentViewController.h
#interface PresentViewController : UIViewController
#property (nonatomic, assign) int discount;
#end
PresentViewController.m
#implementation PresentViewController
-(void)viewDidLoad
{
[super viewDidLoad];
// Setup detailLabel
detailLabel.text = [#(self.discount) stringValue];
}
-(void)setDiscount:(int)discount
{
_discount = discount;
detailLabel.text = [#(_discount) stringValue];
}
#end
That's because totalPrice is not probably instantiated before setDiscount: is called. Call setDiscount: after your view is loaded and totalPrice is instantiated to have the label text updated.
I'm currently building an iPad app in which I need to implement a pop over view.
I have set up a view controller like I always do:
Create UIViewController wit xib file
set the xib up and do the necessary programming in it's .h & .m files
now in the view controller I'm loading it from (from a UIBarButtonItem), I have this code:
- (void) action
{
ItemContent *newItem = [[ItemContent alloc] initWithNibName:#"ItemContent" bundle:nil];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:newItem];
_popover = [[UIPopoverController alloc] initWithContentViewController:nav];
[_popover setPopoverContentSize:CGSizeMake(557, 700) animated:YES];
_popover.delegate = self;
[_popover presentPopoverFromBarButtonItem:self.navigationItem.rightBarButtonItem permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
This properly displays my view- and UINavigationController in a UIPopOverController. So far so good!
In the newItem view controller, I have made a bar button in my navigation bar that says "Done". When that button is pushed, I want the UIPopOverController to disappear. How do I do this:
Set a method for when te button is pushed. In this method I want to call a function on the view controller that loaded the Popover to dismiss it again.. but how do I do this?
Put things shortly
How do I make my UIPopOverController call a method on the view controller that loaded the UIPopOverController?
I have been searching SO for a while but none of the solutions and answers solve my problem. If I missed something please inform me ;)
Thank you so much in advance!
You can do this by delegate...
In NewItem.h declare a protocol
#protocol NewItemDelegate
-(void)onTapDoneButton;
#end
Now create a delegate property like this
#property (nonatomic, assign) id<NewItemDelegate>delegate;
In NewItem.m in doneButtonPuhsed method call this
[self.delegate onTapDoneButton];
Change this method a bit
- (void) action
{
ItemContent *newItem = [[ItemContent alloc] initWithNibName:#"ItemContent" bundle:nil];
newItem.delegate =self;
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:newItem];
_popover = [[UIPopoverController alloc] initWithContentViewController:nav];
[_popover setPopoverContentSize:CGSizeMake(557, 700) animated:YES];
_popover.delegate = self;
[_popover presentPopoverFromBarButtonItem:self.navigationItem.rightBarButtonItem permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
Now implement NewItemDelegate method below this action method.
-(void)onTapDoneButton{
//dismiss popover here
}
I had this problem too and solved it using notifications.
In your parent controller, in viewDidLoad method, you have to add an observer:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(closePopover)
name:#"closePopoverName"
object:nil];
Then, in your viewDidUnload method you remove the observer like this:
[[NSNotificationCenter defaultCenter] removeObserver:self];
Of course, you have to create the function which actually dismisses the popover:
- (void) closePopover
{
[_popover dismissPopoverAnimated:YES];
}
Then, in your ItemContent controller, you just post a notification when you want to close the popover:
[[NSNotificationCenter defaultCenter] postNotificationName:#"closePopoverName" object:self userInfo:nil];
You could define a protocol on ItemContent and use it on your CallerViewController. If you want to close your Popover, just call your delegate method, which you will implement on your CallerViewController
In my application I have a presentViewController, and inside it I have a button that opens a popover. In this popover I have a barButtonItem to save de data of this popover. I would like that when the user taps outside of the popover, the data could be saved too.
I've tried to use the popoverControllerDidDismissPopover method in the presentViewController view. I have the delegate but when I tap outside of the popover this method is not called.
What can I do?
Thanks!!
Add this line of code while adding popOver:
popover.delegate = self;
Also register popOverDelegate in .h file where u present your popOver COntroller
#interface yourViewController : UIViewController<UIPopoverControllerDelegate>
Please, pay attention to docs!
"Called on the delegate when the user has taken action to dismiss the popover.
This is not called when the popover is dismissed programmatically."
It was my case because my popover was closing on button tap with this method:
dismiss(animated: true, completion: nil)
You probably already solved it, but I just faced the same problem. I'm holding a instance of UIPopoverController in my Viewcontroller and had it this way:
self.popover.delegate = self;
self.popover = [[UIPopoverController alloc] initWithContentViewController:wgtvc];
of course this doesn't work because I'm initializing the UIPopoverController AFTER setting the delegate, which overrides the delegate setting. So the correct way is to FIRST initialize the UIPopovercontroller and THEN setting the delegate
self.popover = [[UIPopoverController alloc] initWithContentViewController:wgtvc];
self.popover.delegate = self;
Maybe you are reinitializing your UIPopoverController somewhere - just set the delegate again after reinitializing.
I had the same problem and I solved it by handling it different for iOS8.
Presentation code
UIViewController *searchViewController = [[UIViewController alloc] init];
[[searchViewController view] addSubview:_searchOptions];
[searchViewController setModalPresentationStyle:UIModalPresentationPopover];
[searchViewController setPreferredContentSize:CGSizeMake(500, 400)];
[_searchOptions setHidden:NO];
[_searchOptions setFrame:[[searchViewController view] bounds]];
[_searchOptions setAutoresizingMask:UIViewAutoresizingFlexibleWidthAndHeight];
if (CRIdiomToolsIsIOS8OrHigher())
{
UIPopoverPresentationController *popOverPresentationController = [searchViewController popoverPresentationController];
[popOverPresentationController setDelegate:self];
[popOverPresentationController setSourceView:[_searchOptionsButton disclosureView]];
[popOverPresentationController setSourceRect:[[_searchOptionsButton disclosureView] bounds]];
[self presentViewController:searchViewController animated:YES completion:nil];
}
else
{
UIPopoverController *popOverControler = [[UIPopoverController alloc] initWithContentViewController:searchViewController];
[popOverControler setDelegate:self];
[popOverControler setPopoverContentSize:CGSizeMake(500, 400)];
[popOverControler presentPopoverFromRect:[[_searchOptionsButton disclosureView] bounds] inView:[_searchOptionsButton disclosureView] permittedArrowDirections:UIPopoverArrowDirectionUp|UIPopoverArrowDirectionLeft animated:YES];
}
Delegate calls
#pragma mark Delegate Methods: UIPopoverControllerDelegate
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
[self showSearchOptions:NO animated:YES];
}
#pragma mark Delegate Methods: UIPopoverPresentationControllerDelegate
- (void)popoverPresentationControllerDidDismissPopover:(UIPopoverPresentationController *)popoverPresentationController
{
[self showSearchOptions:NO animated:YES];
}
I had the same issue. You will need to retain the popover object, that way the delegate method gets called. Its strange but it works.
#property (nonatomic, retain) UIPopoverController *popupObject;
UIPopoverController *popup = [[UIPopoverController alloc] initWithContentViewController:viewController];
popup.delegate = self;
[popup presentPopoverFromRect:presentationRect inView:self permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
self.popupObject = popup; //Retained
-(void) popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
//Do whatever operation you need to perform
self.popupObject = nil;
}
I know this questions is old but hopefully it helps someone out there...
The issue is in the initialization of your popover controller. If you have established the popover segue in the storyboard you need to have a reference to this popover in order for the delegate to be called when it is dismissed.
In your prepare for segue method:
Instead of:
self.popoverController = [[UIPopoverController alloc]initWithContentViewController:segue.destinationViewController];
self.popoverController.delegate = self;
You need:
self.popoverController = [(UIStoryboardPopoverSegue *)segue popoverController];
self.popoverController.delegate = self;
Then make sure to correctly handle if the when the popover should appear in
(BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
I have a navigation based application.On click of a button on the navigation bar in the first screen , I am able to push another view controller as follows :
-(void) buttonClicked:(id)sender
{
UIViewController* mv = [[SecondViewController alloc] init];
[[self navigationController] pushViewController:mv animated:YES];
}
Now i have a UIView(separate .h and .m files) as part of the first screen. On click of a button in the UIView, i want to push the SecondViewController.
I have tried the following :
UIViewController* mv = [[SecondViewController alloc] init];
UIViewController * home=[[FirstViewController alloc]init];
[[home navigationController] pushViewController:mv animated:YES];
It doesnt work!! Kindly help
UIViewController* mv = [[SecondViewController alloc] init];
UIViewController * home=[[FirstViewController alloc]init];
[[home navigationController] pushViewController:mv animated:YES];
The problem here is that home isn't part of the navigation stack, so [home navigationController] is surely nil. I'm not quite clear on what you're trying to do here, but just creating a view controller doesn't mean that it's actually part of the view controller graph.
Why would it work? Randomly creating view controllers whose view is not even visible, is not the solution. You can either keep a reference to the VC in the view like this:
#imlementation ViewController
- (id) init
{
// ...
aView = [[CustomView alloc] init];
aView.viewController = self;
// ...
}
#end
#interface CustomView
#property (assign) ViewController *viewController;
#end
Or you can search the responder chain at runtime:
UIResponder *next = [view nextResponder];
while (next)
{
if ([next isKindOfClass:[ViewController class]])
{
break;
}
next = [next nextResponder];
}
And now "next" will contain the view controller (or nil if it can't be found).
Try using the same navigationController to push view, this keeps the same stack of ViewControllers.
UIViewController* mv = [[SecondViewController alloc] init];
[[self navigationController] pushViewController:mv animated:YES];
[mv release];
I see your problem now! You need to #import your FirstViewController, then #class it. Then do your push.
So:
//.h
#import "FirstViewContoller.h"
#class FirstViewController;
#interface...
//.m
-(void)return {
FirstViewController *firstview = [[FirstViewController alloc]init(withnibname:)];
[firstView.navigationController pushViewController: firstView.navigationController.topViewController animated: TRUE];
}
If I am not wrong, your UIView though is in separate files, is still added to the screen from a UIViewController class.
Simply, post a notification from UIView to your FirstViewController class where you have access to the navigation controller. Then push the SecondViewController from there.
You Can use this. It Works very well for me:-
Firstly Create Object of AppDelegate in UIView Class and initialize it. Then create Navigationcontroller object in Appdelegate.h :-
#property(strong,nonatomic) UINavigationController *navControl;
In your UIView Class implement this code where you want to push :-
ViewController *objview = [[ViewController alloc]init]; [appDelegate.navControl pushViewController:objview animated:YES];
I have two views setup ( inside a TabBar). The DetailView with a button that calls a PopOver with a NavigationController+UITableView (RootView) loading data from CoreData. I have a problem passing data from the UITableView to the DetailView. I have a protocol declared in RootView and used in the DetailView.
Here is the code I use to create the PopOver from the button because I think I have some delegate issues. Any help will be amazing,
- (IBAction)zoneListButtonController
{
if (self.controladorPopOver == nil) {
ipadrootviewController = [[iPadRootViewController alloc] initWithNibName:#"iPadRootView" bundle:[NSBundle mainBundle]];
UINavigationController *ipadnavController = [[UINavigationController alloc]
initWithRootViewController:ipadrootviewController];
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:ipadnavController];
self.controladorPopOver = popover;
popover.delegate = self;
self.title = #"Countries";
popover.popoverContentSize = CGSizeMake(320, 300);
[self.controladorPopOver presentPopoverFromRect:CGRectMake(112, 20, 86, 27) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
[ipadnavController release];
[controladorPopOver release];
}
}
An instance of the SubZone1iPadController doesn't exist when you create the popover in DetailView so you can't set its delegate property directly from the DetailView.
One option is to also add the delegate property to the iPadRootViewController which you can set in the zoneListButtonController method. Then, when ipadrootviewController creates the SubZone1iPadController, pass along the delegate.
So in both ipadrootviewController and SubZone1iPadController, add a delegate property:
#property (nonatomic,assign) id <SubZone1Tap> delegate;
Then, in the zoneListButtonController method, set the delegate property on iPadRootViewController:
ipadrootviewController = [[iPadRootViewController alloc] init...
ipadrootviewController.delegate = self;
Then, where ipadrootviewController creates SubZone1iPadController:
SubZone1iPadController *sz1 = [[SubZone1iPadController alloc] init...
sz1.delegate = self.delegate;
[self.navigationController pushViewController:...
[sz1 release];
Finally, in the DetailView, make sure the delegate method is implemented. For example:
-(void)SubZone1Tap:(NSString *)name
{
NSLog(#"SubZone1Tap, name = %#", name);
//dismiss the popover if that's what you need to do...
[controladorPopOver dismissPopoverAnimated:YES];
}