In my app on button click i have add pickerview to the windows below is the code show that
- (IBAction)btnMake:(id)sender
{
pickerViewMake = [[UIPickerView alloc] initWithFrame:pickerFrame];
pickerViewMake.showsSelectionIndicator = YES;
pickerViewMake.dataSource = self;
pickerViewMake.delegate = self;
[pickerViewMake setBackgroundColor:[UIColor clearColor]];
[viewPicker addSubview:pickerViewMake];
[self.view.window addSubview:pickerViewMake];
}
-(void)removeAllPicker
{
[pickerViewMake removeFromSuperview];
[pickerViewModel removeFromSuperview];
[pickerViewYear removeFromSuperview];
[pickerViewTrim removeFromSuperview];
}
remove all picker is the method used for removing the picker from superview
it works
The problem is that on multiple clicking btnMake number of the picker view cones up then
removeallPicker method call than also pickerview does not remove from superview.
Do one Thing create one BOOL variable and set in viewdidload yes and check in function if it is yes then picker come and also make it no in btnmake method.
Try in the following way
if (<instance>)
{
[<instance> removeFromSuperview],<instance> = nil;
}
After this create your picker then it won't create multiple times, it will create only once.
Related
I have CalenderVC which consist of Container View named PickerController.
PickerController consist of one toolbar,datepicker.Everytime i want to add date i use PickerController but
my problem is on somecondition i also want to set minimum date.I also passed minimumdate using customdelegate but still datepicker not set minimum date.
//CalendarVC added PickerController
- (void)displayContentView
{
UIStoryboard *story=[UIStoryboard storyboardWithName:#"Pagebar" bundle:nil];
objContent=[story instantiateViewControllerWithIdentifier:#"pickerVCID"];
objContent.datePicker.hidden=false;
self.dtDelegate=objContent;
objContent.view.frame=CGRectMake(0,0, self.view.frame.size.width, 280);
if(isFromDate==false)
{
// delegate method that set minimum date of picker
[self.dtDelegate setMinDate:minimumDate];
}
_pickerContainerVw.hidden=false;
[self addChildViewController:objContent];
[self.view addSubview:_pickerContainerVw];
[objContent didMoveToParentViewController:self];
}
-(void)removeContentView
{
_pickerContainerVw.hidden=true;
[objContent willMoveToParentViewController:nil];
[objContent.view removeFromSuperview];
[objContent removeFromParentViewController];
objContent.view.hidden=true;
}
// In pickercontroller
-(void)setMinDate:(NSDate *)minDate
{
[self.datePicker setMinimumDate:minDate];
[self.view addSubview:self.datePicker];
NSLog(#"minimum date %#",minDate);
}
There are several potential problems with your code.
First make sure you have connected your outlets in pickerVCID, especially datePicker.
Then I wonder why you add the picker to the view pickercontroller in setMinDate:? Since you seem to have designed it as a storyboard view controller you already have it as a child in the correct view. In that case you can just hide/show it.
Also, where do you set _pickerContainerVw? Is it the same as objContent.view? You are adding the objContentas a child view controller, but _pickerContainervW as sub-view. Probably you want to add the objContent.view as a sub-view instead.
With the risk of introducing side-effects with my changes, since I haven't seen all of your code, I have fixed some of the above.
//CalendarVC added PickerController
- (void)displayContentView
{
// Instantiate picker
UIStoryboard *story=[UIStoryboard storyboardWithName:#"Pagebar" bundle:nil];
objContent=[story instantiateViewControllerWithIdentifier:#"pickerVCID"];
self.dtDelegate=objContent;
objContent.view.frame=CGRectMake(0,0, self.view.frame.size.width, 280);
// Add it as a child VC
[self addChildViewController:objContent];
[self.view addSubview:objContent.view];
[objContent didMoveToParentViewController:self];
// Start with hidden date picker, show if needed
objContent.datePicker.hidden = YES;
if(isFromDate==false)
{
// delegate method that set minimum date of picker
objContent.datePicker.hidden = NO;
[self.dtDelegate setMinDate:minimumDate];
}
}
-(void)removeContentView
{
[objContent willMoveToParentViewController:nil];
[objContent.view removeFromSuperview];
[objContent removeFromParentViewController];
}
// In pickercontroller
-(void)setMinDate:(NSDate *)minDate
{
[self.datePicker setMinimumDate:minDate];
NSLog(#"minimum date %#",minDate);
}
I am adding the UISwitch programmatically in a scroll view.
UIVIew -> UIScrollView -> UISwitch
UISwitch *toggleSwitch = [[UISwitch alloc] initWithFrame: CGRectZero];
[toggleSwitch addTarget:self action:#selector(flipMode:) forControlEvents:UIControlEventValueChanged];
toggleSwitch.on = YES;
toggleSwitch.userInteractionEnabled = YES;
[scrollView addSubview: toggleSwitch];
Action method:
- (IBAction)flipMode:(id)sender{
if([sender isOn])
{
// On Toggle ON
} else {
//On Toggle OFF
}
}
When we toggle the switch multiple times or on dragging or moving the switch slowly from ON to OFF state or vice versa at some point of time the action is not getting called. In next moment on value change it will trigger the event.
Occurrence of this issue is 2 out of 15-20 trials. Unable to find the root cause for it.
Help appreciated
set your delaysContentTouches property of scroll view to NO
yourScrollView.delaysContentTouches = NO;
This will cause your switch to "get" the touches immediately, rather
than have them go to the UIScrollView first.
Check this answer.
your flipMethod: should look like below code
-(void)flipMode:(id)sender
{
if([sender isOn])
[toggleSwitch setOn:YES animated:YES];
else
[toggleSwitch setOn:NO animated:YES];
}
I want to check if my view has already been added to the view, so that the user cannot repeatedly add the new UIViewController onto the view.
if (!self.fmovc)
{
self.fmovc = [[FMOVC alloc] initWithNibName: #"FMOVC" bundle:nil];
}
BOOL viewAlreadyDisplayed = NO;
for (UIView * b in self.view.subviews)
{
if ([b isKindOfClass:[FMOVC class]])
{
viewAlreadyDisplayed = YES;
}
}
if (!viewAlreadyDisplayed)
{
[self.view addSubview:self.fmovc.view];
}
This is not working because it never triggers
viewAlreadyDisplayed = YES;
What is the correct way to go about finding if your view is already being displayed?
Thanks,
-Code
Before adding just removeItFromSuperView...It may solve your prob
[self.fmovc.view removeFromSuperview];
[self.view addSubview:self.fmovc.view];
Make the UIView member variable say thatView;
if(!thatView) {
thatView = [[UIView alloc] init];
[self.view addSubView:thatView];
}
Once you release the superview, release thatView & make thatView to nil.
OR
always check & remove thatView if present from superview before allocating thatView.
Hope this Helps !!!
Instead of showing the keyboard I want to display a popover view when a textField is selected (my code is at the bottom). If the keyboard isn't showing then everything works great. However, if the keyboard is showing and then the textfield is selected the keyboard doesn't get dismissed, somewhere the firstResponders must be getting lost but I don't know where. Does anyone have a solution to this?
My textfield:
self.startDateTextField = [[UITextField alloc] initWithFrame:CGRectMake(79, 148, 138, 27)];
[self.startDateTextField setBorderStyle:UITextBorderStyleRoundedRect];
[self.startDateTextField setDelegate:delegate];
[self.startDateTextField addTarget:delegate action:#selector(editStartDate:) forControlEvents:UIControlEventEditingDidBegin];
[popoverWrapper addSubview:self.startDateTextField];
and in editStartDate: I have:
-(void)editStartDate:(UITextField *)textField {
[textField resignFirstResponder];
DatePickerVC *datePickerVC = [[DatePickerVC alloc] init];
datePickerVC.delegate = self;
self.popoverController = [[UIPopoverController alloc] initWithContentViewController:datePickerVC];
[self.popoverController setDelegate:self];
[self.popoverController presentPopoverFromRect:CGRectMake(0, 0, 5, 5) inView:textField permittedArrowDirections:UIPopoverArrowDirectionRight animated:YES];
}
This is very easy to do, use your UITextFieldDelegate methods specifically UITextFieldShouldBeginEditing and return NO and execute the code to show the popover instead. This way the keyboard is never shown to begin with.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
[self.view endEditing:YES]; // added this in for case when keyboard was already on screen
[self editStartDate:textField];
return NO;
}
for it to work make sure you set the delegate of the textField to self (the view controller) and in your editStartDate method remove the resignFirstResponder call.
Try like this in your editStartDate: method
[self.startDateTextField resignFirstResponder];
EDIT:
But instead of doing resign the keyboard when you click in textfield, you can make something like setInputView for Textfield to bring out the popViewController.
DatePickerVC *datePickerVC = [[DatePickerVC alloc] init];
datePickerVC.delegate = self;
self.popoverController = [[UIPopoverController alloc] initWithContentViewController:datePickerVC];
[self.popoverController setDelegate:self];
[self.popoverController presentPopoverFromRect:CGRectMake(0, 0, 5, 5) inView:textField permittedArrowDirections:UIPopoverArrowDirectionRight animated:YES];
self.startDateTextField = [[UITextField alloc] initWithFrame:CGRectMake(79, 148, 138, 27)];
[self.startDateTextField setBorderStyle:UITextBorderStyleRoundedRect];
[self.startDateTextField setDelegate:delegate];
self.startDateTextField.inputView = self.popoverController;
You appear to be resigning the first responder of the text field; however, this isn't necessarily the first responder, which may explain why calling it has no effect.
Instead, you should use the endEditing category to recurse through all children of your view to resign the first responder from whichever view it is attached to:
[self.view endEditing:YES];
In any case, as you never want to show the keyboard, you can simply implement UITextFieldDelegate to override the default behaviour.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
// Your popover code.
return NO;
}
UITextFieldDelegate Protocol Reference.
So you're trying to hide the keyboard immediately after the text field is selected and display something else?
There's two things I can think of:
Give the text field some time to get it together before resigning the first responder:
[textField performSelector:#selector(resignFirstResponder) withObject:nil afterDelay:0.5];
Set the inputView property of the text field to nil or a UIView with a clear background color.
If inputView on the text field doesn't get you what you want, you can also simply put an invisible button on top of the UITextField and just show the popover from the button's action. To the user it will appear as if the text field brought up the popover. If at that point the keyboard is still there, call resignFirstResponder on all possible first responders (text fields etc.).
I know this is really basic stuff but i need to understand whether my understanding of this is correct.
So what i want to do is this. I want an view with a label on which when double tapped flips and loads another view. On the second view i want a UIPickerView and above i have a button saying back. Both views will be of same size as an UIPickerView which is 320px x 216px.
What i am thinking of to do is create two UIViewclasses named labelView and pickerView. I would then create a viewController which on loadView loads labelView then when user double taps the labelView i get an event in labelView class which is sent to my viewController that then can unload loadView and load the pickerView.
Does this sound as the best way to do this ? Is there a simpler way ? I am also unsure how i route the event from the labelView class to the viewControllerclass.
I dont exactly know the most efficient way to do it(as i am also now to this language),but it is for sure that i have solved ur problem. I made a simple program for that.Three classes involved here in my eg are BaseViewController (which will show two views),LabelView and PickerView (according to ur requirement).
In LabelView.h
#protocol LabelViewDelegate
-(void)didTapTwiceLabelView;
#end
#interface LabelView : UIView {
id <LabelViewDelegate> delegate;
}
#property(nonatomic,retain)id <LabelViewDelegate> delegate;
-(void)didTouch;
#end
In LabelView.m
#synthesize delegate;
-(id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self)
{
UILabel* labl = [[UILabel alloc] initWithFrame:CGRectMake(10, 5, frame.size.width-20,20)];
labl.text = #"Some Text";
[self addSubview:labl];
[labl release]; labl = nil;
self.backgroundColor = [UIColor grayColor];
UITapGestureRecognizer* ges = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(didTouch)] autorelease];
ges.numberOfTapsRequired = 2;
[self addGestureRecognizer:ges];
}
return self;
}
-(void)didTouch
{
[delegate didTapTwiceLabelView];
}
//=============================================================
In Pickerview.h
#protocol PickerViewDelegate
-(void)didTapBackButton;
#end
#interface PickerView : UIView <UIPickerViewDelegate,UIPickerViewDataSource>{
id <PickerViewDelegate> delegate;
}
#property(nonatomic,retain)id <PickerViewDelegate> delegate;
#end
In Pickerview.m
#implementation PickerView
#synthesize delegate;
-(id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self)
{
UIPickerView* picker = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 30, 320, 216)];
picker.delegate = self;
picker.dataSource = self;
[self addSubview:picker];
[picker release]; picker = nil;
self.frame = CGRectMake(frame.origin.x, frame.origin.y, 320, 250);
UIButton* btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setFrame:CGRectMake(10, 1, 50, 27)];
[btn setTitle:#"Back" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(backButton) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:btn];
}
return self;
}
-(void)backButton
{
[delegate didTapBackButton];
}
//====================================================================
in BaseViewController.h
#import "LabelView.h"
#import "PickerView.h"
#interface VarticalLabel : UIViewController<UITextFieldDelegate,PickerViewDelegate,LabelViewDelegate> {
PickerView* myPickerView;
LabelView* myLabelView;
}
#end
In BaseViewController.m
-(void)viewDidLoad
{
[super viewDidLoad];
myPickerView= [[PickerView alloc] initWithFrame:CGRectMake(0, 50, 320, 250)];
[self.view addSubview:myPickerView];
myPickerView.delegate = self;
myLabelView= [[LabelView alloc] initWithFrame:CGRectMake(0, 50, 320, 250)];
[self.view addSubview:myLabelView];
myLabelView.delegate = self;
myPickerView.hidden = YES;
}
#pragma mark PickerViewDelgate
-(void)didTapBackButton
{
myPickerView.hidden = YES;
myLabelView.hidden = NO;
}
#pragma mark LabelViewDelegate
-(void)didTapTwiceLabelView
{
myPickerView.hidden = NO;
myLabelView.hidden = YES;
}
To get events from a button to the view controller, just hook up the button's event, e.g. touch up inside, to a method in the view controller, using interface builder. (Double tapping is probably more complicated though.)
When you say 'flips', do you mean it actually shows an animation of flipping over a view to show a 'reverse' side? Like in the weather app when you hit the 'i' button? I'm assuming this is what you mean.
Perhaps check TheElements sample example on the iPhone Reference Library, it has an example of flip animation.
Btw, it's not strictly necessary to unload the loadView that is being 'hidden' when you flip -- it saves you having to construct it again when you flip back -- but it may be pertinent if you have memory use concerns, and/or the system warns you about memory being low.
Also, what do you mean by "create a UIView"? Do you mean subclass UIView, or just instantiate a UIVIew and add children view objects to it? The latter is the usual strategy. Don't subclass UIView just because you want to add some things to a UIView.
If you've got one screen of information that gives way to another screen of information, you'd normally make them separate view controllers. So in your case you'd have one view controller with the label and upon receiving the input you want, you'd switch to the view controller composed of the UIPickerView and the button.
Supposing you use Interface Builder, you would probably have a top level XIB (which the normal project templates will have provided) that defines the app delegate and contains a reference to the initial view controller in a separate XIB (also supplied). In the separate XIB you'd probably want to add another view controller by reference (so, put it in, give it the class name but indicate that its description is contained in another file) and in that view controller put in the picker view and the button.
The point of loadView, as separate from the normal class init, is to facilitate naming and linking to an instance in one XIB while having the layout defined in another. View controllers are alloced and inited when something that has a reference to them is alloced and inited. But the view is only loaded when it is going to be presented, and may be unloaded and reloaded while the app is running (though not while it is showing). Generally speaking, views will be loaded when needed and unnecessary views will be unloaded upon a low memory warning. That's all automatic, even if you don't put anything in the XIBs and just create a view programmatically within loadView or as a result of viewDidLoad.
I've made that all sound more complicated than your solution, but it's actually simpler because of the amount you can do in Interface Builder, once you're past the curve of learning it. It may actually be worth jumping straight to the Xcode 4 beta, as it shakes things up quite a lot in this area and sites have reported that a gold master was seeded at one point, so is likely to become the official thing very soon.
With respect to catching the double tap, the easiest thing is a UITapGestureRecognizer (see here). You'd do something like:
// create a tap gesture recogniser, tell it to send events to this instance
// of this class, and to send them via the 'handleGesture:' message, which
// we'll implement below...
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(handleGesture:)];
// we want double taps
tapGestureRecognizer.numberOfTapsRequired = 2;
// attach the gesture recogniser to the view we want to catch taps on
[labelView addGestureRecognizer:tapGestureRecognizer];
// we have an owning reference to the recogniser but have now given it to
// the label. We don't intend to talk to it again without being prompted,
// so should relinquish ownership
[tapGestureRecognizer release];
/* ... elsewhere ... */
// the method we've nominated to receive gesture events
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer
{
// could check 'gestureRecognizer' against tapGestureRecognizer above if
// we set the same message for multiple recognisers
// just make sure we're getting this because the gesture occurred
if(gestureRecognizer.state == UIGestureRecognizerStateRecognized)
{
// do something to present the other view
}
}
Gesture recognisers are available as of iOS 3.2 (which was for iPad only; so iOS 4.0 on iPhone and iPod Touch).