I have a UITableView cell with several UITextFields in it. When a user clicks into one of the textFields, a popover appears with some information. At first, they then had to click outside of either the textField or the popover to clear the popover before then clicking into the next textField. I therefore then added the cell's contentView to the popover controller's passThroughViews property so they can click through the different textFields in that cell at will without having to dismiss the popover controller first. However, it keeps the original popover open (which) is fine, and then opens another identical popover as well.
Is there a way I can tell if a popover is already open before sending the command to open another? I can't think of how to detect this?
If each cell controls the logic of the popover, you need to say to your custom cell to implement UIPopoverControllerDelegate protocol, set the delegate for the popover as self (the cell) and override popoverControllerDidDismissPopover like the following:
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
[self.pop dismissPopoverAnimated:YES]; // hide the popover
self.pop = nil; // release the popover, this forces to create a fresh popover each time
}
If you want you can also remove the line self.pop = nil; but remember to release it in dealloc (I suppose you are not using ARC code since you are using retainCount). As bbum suggested you should't use retainCount to check objects existence.
In addition, each UIPopoverController instance has a property called popoverVisible if you want to see if a popover is already visible or not.
OK, I did it. For others who find this question. In addition to the other answers, this is how I did it.
I made my view controller a UIPopoverControllerDelegate.
I then created an BOOL called myPopoverControllerOpen.
When I created my popover I set the BOOL to yes. Using the delegate method popoverDidDismissPopover I then set the BOOL back to NO.
I then check on the state of this BOOL before presenting the popover.
Related
I have two views and i used two view controllers. From the main view i want to initialize the button in the second view with a certain text.
If I press the button in the second view, then i can store that button reference to a global UIButton, and change the text then onwards.
But the very first time, how can I initialize the button text in the second view from my main view with a particular text ?
You should not do that: every controller should be responsible for its own view. Full stop.
You can always set some poperty on the second controller and use it when the second view appears on the screen to change whatever you like.
you use delegates & #protocol to access other class example,
refer ex, ex1, link
Not sure how you did this. But if you post some code, it will be helpful. If you already have the above code working, then you need to have the following in order for what you are expecting to work.
Say you have ViewControllerA, ViewControllerB as the two view controllers. You can definitely initialize the text in the button when you create the XIB file.
But I am assuming that you want to do this programatically. If you want to access a button in another view controller, you need
a. Access to the other view controller.
b. Once you have access to the other view controller, access to the UIButton variable in that view controller.
So you can do the following in the ViewControllerA code,
-(void)changeButtonTextOfVCB{
viewControllerB.button setTitle:#"MyTitle" forControlState...
}
and you can have a button in viewControllerA, which will trigger the above method.
Having said this, I am not sure whether you have the whole thing working, where you can even switch between the view controllers
If you make a button in FirstViewController and want to change button properties like title..etc from the second view, then you should make properties in SecondViewController
#property (nonatomic,assign) UIButton *button;
when you navigate firstViewController to secondViewController just pass the button Object like
obj = [SecondViewController alloc]...]
obj.button = button;//(FirstViewController button object)
I have an app that has two viewcontrollers Viewcontroller and OptionsViewController. Viewcontroller is the initial viewcontroller then if I click a button I have a modal segue to optionsviewcontroller.
There in optionsviewcontroller I have I UISegmented viewcontroller created from the storyboard which is linked to an outlet (UnitsSegmentedControl) and I want to be able to tell the segmented control which segment should be selected by default when OptionsViewController loads.
In my Viewcontroller I wrote a method:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
OptionsViewController *ovc=[segue destinationViewController];
ovc.delegate=self;
[ovc.UnitsSegmentedControl setSelectedSegmentIndex:1];
}
the thing is when OptionsViewController loads the view the selected index is 0 as by default. I don't get any error message or something.
I'm using Xcode 4.2. I think It might be some option I can change in storyboard to make the UISegmentedControl to be able to set default selected index. I don't know what else could be causing that.
EDIT:
I figured out that if I write :
[ovc.UnitsSegmentedControl setSelectedSegmentIndex:1];
inside OptionsViewController method viewdidload everything works fine. Why am I not able to do it from the prepare for segue method?
The segmented control does not exist until the OptionsViewController is loaded which is why you cannot set the selected segment in the prepareForSegue method of you ViewController. Review the UISegmentedControl Class Reference reveals that there is no way to set a default state:
"The default value is UISegmentedControlNoSegment (no segment selected) until the user touches a segment. Set this property to -1 to turn off the current selection. UISegmentedControl ignores this property when the control is in momentary mode. When the user touches a segment to change the selection, the control event UIControlEventValueChanged is generated; if the segmented control is set up to respond to this control event, it sends a action message to its target."
Setting the selectedSegmentIndex in the viewDidLoad method of your OptionsViewController is the correct way to set a default value the view controller.
Just use this code if you want to do it programmatically
segmentControl.selectedSegmentIndex=-1;
If you want to set it from nib then in interface builder just uncheck selected property of index
I have a a UIViewController that is pushed to by two different views in my app.
One time it is a modal view, so I have the right navbar button set to Done and it dismisses the view.
At another time in my app, this same view is pushed to, but not modally, thus I don't want this button to show. I tried adding this when pushing it, but no luck.
self.navigationItem.rightBarButtonItem.enabled = NO;
You can check the parent view controller for whether it has the modalViewController property set
if (self.parentViewController.modalViewController == self)
{
// add button
}
Simple and effective -
self.navigationItem.rightBarButtonItem = nil;
Edit:
How can you add this when you are pushing this ? Add it in the viewWillAppear or viewDidLoad of the viewController you want to see this is in.
You can check for a certain condition.
If it is pushed from view 1, you can make it nil.
If it is shown modally from view 2, you can make it appear.
For this, you will have to make the viewControllers communicate with each other. For that, you will need to use NSUserDefaults and set an integer for a key.
You can assign two different integers logically and use them as the condition for showing/not showing the rightBarButtonItem.
Good Luck.
I am strugling on the following task.
I am trying to control my subview from another viewController class.
What I did and does not work is this.
I inserted an object and changed it class to my second viewController class.
Then I connected its UIButton outlet to a button I have on my subview.
I then connected the buttons action to the outlet of my second view controller.
What I get when I run is this.
It all shows up well but when I try to touch the button that resides in my subview app crashes. I am only left with a worringing: "Action unavailable: The "Touch Up Inside" event of "Rounded Rect Button".
It's probably my logic that is incorrect. Thanks for help.
Well after a long research I got an answer to my problem.
As it appears I was doing everything right.
The problem is that after the initial XIB file is initialized it autoreleases all views and subviews. So to prevent from gettig your second view controller from being released implement this method
- (void)awakeFromNib {
[self retain];
}
in your view controller .m file.
This method will retain your second view controller alive and allow it to recive and respond to UI actions.
Edit:Ok, this is weird... After doing extensive debugging, I have discovered that whilst the text fields are resigning first responder status (I can see that there is no longer a blinking bar in any), the keyboard is NOT GOING DOWN! Maybe this deserves a different question.
I have several text fields in a custom uiviewcontroller subclass, which is displayed within a popover. The popover is displayed form a bar button. I want the keyboard to go down when the popover is dismissed (either by the user tapping the bar button again, or tapping outside the popover. From the view controller that displays the popover, when the popover is dismissed, in either of the 2 fashions, I call
[optionsController dismissFirstResponder];
Optionscontroller is the uiviewcontroller subclass in the popover. Dismissfirstresponder is a method I defined:
-(void)dsimissFirstResponder {
[nameField resignFirstResponder];
[descriptionField resignFirstResponder];
[helpField resignFirstResponder];
}
Those are three IBoutlets which I connected in the xib to the text fields.
That doesn't work. Any help with this would be greatly appreciated.
The code is called as such:
[optionsController dismissFirstResponder];
[poppoverController dismissPopoverAnimated];
I set a breakpoint in dismissFirstResponder and it is called when I expected it to be. I also checked, and all three IBOutlets are non-nil during that function call. These are the only text fields in the whole app, so I'm not sure how else to put the keyboard down.
What you need is to receive the delegate method callbacks for a popover. Have you looked at the docs for the UIPopoverControllerDelegate? The following methods are defined:
-popoverControllerShouldDismissPopover:
-popoverControllerDidDismissPopover:
These should get called when your user does any gesture to dismiss the popover (tapping outside, etc.) assuming you've set a delegate for your popover and you've implemented this formal protocol in that delegate. When – popoverControllerDidDismissPopover: gets called, you can just call -resignFirstResponder on your controls at that point.
// In your popover delegate
- (void)popoverControllerDidDismissPopover:
(UIPopoverController *)popoverController
{
[nameField resignFirstResponder];
[descriptionField resignFirstResponder];
[helpField resignFirstResponder];
}