I'm new to iOS development and I have an assignment where I need to implement a a UITextfield which upon a tap, brings a country selector UIPickerView.
I went through some online tutorials and got it working somehow. But it shows some strange behaviour which I can't seem to figure out.
Some strange black bars are appearing, with the picker content visibly duplicated each time I scroll.
I believe I've made a mistake in my code, forgive my lack of knowledge but can't seem to figure out what is wrong in the code.
Could you please tell me what has gone wrong?
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if ([textField isEqual:self.countryTextField]) {
countryPicker = [[UIPickerView alloc] initWithFrame:CGRectZero];
countryPicker.showsSelectionIndicator = YES;
self.countryPicker.delegate = self;
self.countryPicker.dataSource = self;
// [self.countryPicker reloadAllComponents];
countryPicker.showsSelectionIndicator = YES;
// [countryPicker init:self];
textField.inputView = countryPicker;
}
return YES;
}
- (UIView * ) pickerView: (UIPickerView * ) pickerView viewForRow: (NSInteger) row forComponent: (NSInteger) component reusingView: (UIView * ) view {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, pickerView.frame.size.width, 44)];
label.text = [NSString stringWithFormat:#"%#", [[self.countries objectAtIndex:row] objectForKey:#"name"]];
[label setTextAlignment:UITextAlignmentLeft];
[label setBackgroundColor:[UIColor clearColor]];
[label setFont:[UIFont boldSystemFontOfSize:15]];
return label;
}
Might be initialising every time , instead of initialising at every time , Check whether the UIPicker is already initialised
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if ([textField isEqual:self.countryTextField]) {
if(! countryPicker){
countryPicker = [[UIPickerView alloc] initWithFrame:CGRectZero];
countryPicker.showsSelectionIndicator = YES;
self.countryPicker.delegate = self;
self.countryPicker.dataSource = self;
countryPicker.showsSelectionIndicator = YES;
}
textField.inputView = countryPicker;
}
return YES;
}
It seems there are few things need to be changed in your code
1.Don't allocate memory to UIPickerView every time your text field get edited -textFieldShouldBeginEditing
if(self.countryPicker == nil)
{
self.countryPicker = [[UIPickerView alloc] initWithFrame:CGRectZero];
self.countryPicker.showsSelectionIndicator = YES;
self.countryPicker.delegate = self;
self.countryPicker.dataSource = self;
self.countryPicker.showsSelectionIndicator = YES;
}
2.Either use self.countrypicker -> class property or countrypicker don't use them interchangeably.
Well I finally found the issue. It was a silly mistake of defining a wrong number of components in numberOfComponentsInPickerView
Related
When I bring up a UIImagePickerController and then close it, it duplicates the content in my modal window. Below are the before and after pictures:
Here's the code that shows the image picker:
-(void) choosePhotos
{
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
[imagePicker setDelegate:self];
[imagePicker setAllowsEditing:YES];
[imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
[self presentViewController:imagePicker animated:YES completion:nil];
}
Here's the rest of my code (if needed):
-(id) init
{
self = [super init];
if (self)
{
[self.navigationItem setTitle:#"Deposit"];
UIBarButtonItem *closeButton = [[UIBarButtonItem alloc] initWithTitle:#"Cancel" style:UIBarButtonItemStyleDone target:self action:#selector(cancel)];
[self.navigationItem setLeftBarButtonItem:closeButton];
toItems = #[#"Account...5544", #"Account...5567"];
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(hideKeyboard)];
[self.view addGestureRecognizer:recognizer];
}
return self;
}
-(void) hideKeyboard
{
for (UITextField *field in [scrollView subviews])
{
[field resignFirstResponder];
}
}
-(void) cancel
{
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return [toItems count];
}
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return [toItems objectAtIndex:row];
}
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
[self.view setBackgroundColor:[UIColor whiteColor]];
UILabel *toLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 0, 50, 100)];
[toLabel setText:#"To:"];
toPicker = [[UIPickerView alloc] initWithFrame:CGRectMake(130, -30, 220, 100)];
[toPicker setDataSource:self];
[toPicker setDelegate:self];
UILabel *amountLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 100, 70, 100)];
amountLabel.lineBreakMode = NSLineBreakByWordWrapping;
amountLabel.numberOfLines = 0;
[amountLabel setText:#"Check Amount:"];
UITextField *amountField = [[UITextField alloc] initWithFrame:CGRectMake(130, 100, 270, 100)];
[amountField setPlaceholder:#"Enter Amount"];
[amountField setReturnKeyType:UIReturnKeyDone];
[amountField setKeyboardType:UIKeyboardTypeDecimalPad];
UILabel *imagesLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 200, 70, 100)];
imagesLabel.lineBreakMode = NSLineBreakByWordWrapping;
imagesLabel.numberOfLines = 0;
[imagesLabel setText:#"Check Images:"];
UIButton *imagesButton = [[UIButton alloc] initWithFrame:CGRectMake(120, 200, 244, 99)];
[imagesButton setBackgroundImage:[UIImage imageNamed:#"photos.png"] forState:UIControlStateNormal];
[imagesButton addTarget:self action:#selector(choosePhotos) forControlEvents:UIControlEventTouchUpInside];
CGRect bounds = [[UIScreen mainScreen] bounds];
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, bounds.size.width, bounds.size.height)];
[scrollView setAlwaysBounceVertical:YES];
[scrollView setShowsVerticalScrollIndicator:YES];
[scrollView addSubview:toLabel];
[scrollView addSubview:toPicker];
[scrollView addSubview:amountLabel];
[scrollView addSubview:amountField];
[scrollView addSubview:imagesLabel];
[scrollView addSubview:imagesButton];
[self.view addSubview:scrollView];
}
I recommend you use viewDidLoad as the place to create and add your views:
- (void)viewDidLoad {
[super viewDidLoad];
//init and add your views here
//example view
self.someLabel = [[UILabel alloc] init];
self.someLabel.text = #"someExampleText";
[self.view addSubview:self.someLabel];
}
And either viewWillAppear or viewDidLayoutSubviews as the place to configure their sizes (i prefer viewDidLayoutSubviews so i'll use it as an example):
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.someLabel.frame = CGRectMake(kMargin,kMargin,kLabelWidth,kLabelHeight);
}
Of course, in order to do this you need to have a reference to all the views you wish to configure this way by creating a property to them in the interface:
#interface YourViewController ()
#property (nonatomic, strong) UILabel *someLabel;
#end;
static CGFloat const kMargin = 20.0f;
static CGFloat const kLabelHeight = 30.0f;
static CGFloat const kLabelWidth = 100.0f;
Also, it is recommended you avoid using hard coded values for their sizes (doing it like CGRectMake(20,20,100,70) but this it not completely wrong.
Not using hard coded values does not mean setting them yourself, it just means to make their values more readable (and on most cases, dynamic).
In my example, i created kMargin, kLabelHeight and kLabelWidth, meaning that anyone who looks at this code will understand what they mean, they will know what to change if needed, and these values can be used in other places.
For example, you could have 4 labels, and in order to keep them all following the same layout rules, all of them will use the kMargin value on the origin.x.
You could also, instead of using a static value for the width, you can implement a dynamic value, like this:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
CGFloat labelWidth = self.view.bounds.size.width - (kMargin * 2);
self.someLabel.frame = CGRectMake(kMargin,kMargin,labelWidth,kLabelHeight);
}
What i did here is to make my label to have the same width as my super view, but i made it account for the left and the right margins (by taking the total view width and reducing twice the margin value).
Since we are doing this on the viewDidLayoutSubviews method, which gets called whenever the superview changes its size (for example, orientation change) this will ensure your UILabel can be shown on any size of view and orientation without extra code to handle 'specific cases'.
Your UI elements are being added to your view every time viewWillAppear is called. This is called when your image picker dismisses and returns to your view, so they're being duplicated. Either check to see whether your UI elements already exist before creating them again, or do your UI setup in the viewDidLoad method which will only be run once. You could try this perhaps, using a BOOL property to keep track:
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
if (!self.alreadyAppeared) {
self.alreadyAppeared = YES;
// Create labels and buttons
}
}
I'm having problems with the action of a button ... I do not understand why things are not working and wanted to ask you if you could help me understand the error.
In my viewController I have a button in the selected mode adds a UIView inside another UIView but when the button is brought in was not selected should eliminate the view previously entered, it remains there without doing anything ... I tried in this way, but I do not understand where I'm wrong
- (IBAction)shareActive:(id)sender {
UIView *checkActive = [[UIView alloc]init];
checkActive.frame =CGRectMake(2, 2, 11, 11);
checkActive.layer.masksToBounds = YES;
checkActive.layer.cornerRadius = 5.5f;
checkActive.backgroundColor = [UIColor greenColor];
if (!self.condividiButton.selected) {
self.condividiButton.selected = YES;
[self.checkCondividi addSubview:checkActive];
NSLog(#"attivo");
}else {
self.condividiButton.selected = NO;
[checkActive removeFromSuperview];
NSLog(#"disattivo");
}
}
here is one of the many possible solutions.
I'm sure the others will give you different ideas about how such problem can be also solved.
- (IBAction)buttonShareTouchedUpInside:(UIButton *)sender {
if (!self.condividiButton.selected) {
UIView *checkActive = [[UIView alloc]init];
checkActive.tag = 121212;
checkActive.frame =CGRectMake(2, 2, 11, 11);
checkActive.layer.masksToBounds = YES;
checkActive.layer.cornerRadius = 5.5f;
checkActive.backgroundColor = [UIColor greenColor];
self.condividiButton.selected = YES;
[self.checkCondividi addSubview:checkActive];
} else {
self.condividiButton.selected = NO;
[self.checkCondividi.subviews enumerateObjectsUsingBlock:^(UIView * obj, NSUInteger idx, BOOL *stop) {
if (obj.tag == 121212) {
[obj removeFromSuperview];
}
}];
}
}
NOTE: the original problem can be resolved via many other and probably more elegant ways, but I'm not concerning about those here.
I have a UITableView which has some custom styling. This table view appears in two places in the app, one of which is inside a UIPopoverController. However when the tableview is inside the popover it takes on the default tableview styling as stated in the UI Transition Guide under "Popover".
The problem I have is that there appears to be nowhere to change this behaviour. Regardless of where I try and modify properties of the tableview the view inside the popover doesn't change.
Anyone dealt with this issue before or have any ideas?
Here is the init method of LibraryProductView where I create the table view:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.sectionOrdering = [NSArray arrayWithObjects:
[NSNumber numberWithInt:LIBRARY_PRODUCT_SECTION_DESCRIPTION],
[NSNumber numberWithInt:LIBRARY_PRODUCT_SECTION_DOCUMENTS],
[NSNumber numberWithInt:LIBRARY_PRODUCT_SECTION_ACTIVE_INGREDIENTS],
[NSNumber numberWithInt:LIBRARY_PRODUCT_SECTION_RELATED_PRODUCTS],
[NSNumber numberWithInt:LIBRARY_PRODUCT_SECTION_RELATED_DOCUMENTS], nil];
self.backgroundColor = [UIColor whiteColor];
self.tableView = [[UITableView alloc] initWithFrame:CGRectInset(self.bounds, 10, 0) style:UITableViewStyleGrouped];
self.tableView.backgroundColor = [UIColor whiteColor];
self.tableView.dataSource = self;
self.tableView.delegate = self;
self.tableView.separatorColor = [UIColor clearColor];
self.tableView.showsVerticalScrollIndicator = NO;
[self addSubview:self.tableView];
}
return self;
}
Here is where the containing view (LibraryProductView) is added to the popover:
- (IBAction)didTouchInformationButton:(id)sender
{
if (_infoPopover != nil && _infoPopover.isPopoverVisible)
{
[_infoPopover dismissPopoverAnimated:YES];
return;
}
CGSize preferredSize = CGSizeMake(600.0f, 500.0f);
LibraryProductViewController* productController = [[[LibraryProductViewController alloc] initWithPreferredSize:preferredSize] autorelease];
productController.filterByMyCompany = NO;
productController.product = _activityInput.product;
UINavigationController* nav = [[[UINavigationController alloc] initWithRootViewController:productController] autorelease];
nav.title = _activityInput.product.name;
RELEASE(_infoPopover);
_infoPopover = [[UIPopoverController alloc] initWithContentViewController:nav];
_infoPopover.popoverContentSize = CGSizeMake(preferredSize.width, preferredSize.height + 46);
[_infoPopover presentPopoverFromRect:_infoButton.frame inView:_infoButton permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
}
The LibraryProductView is created within viewDidLoad method of LibraryProductViewController.
- (void)viewDidLoad
{
[super viewDidLoad];
self.libraryProductView = [[LibraryProductView alloc] initWithFrame:(usingPreferredSize ? CGRectMake(0.0, 0.0, preferredSize.width, preferredSize.height) : self.view.bounds)];
self.libraryProductView.dataSource = self;
self.libraryProductView.delegate = self;
[self.view addSubview:self.libraryProductView];
}
To set properties for the TableView you might do so in
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
[tableView setBackgroundColor:[UIColor redcolor]];
[tableView setSeparatorColor: [UIColor blueColor]];
return 1;
}
This, of course, assumes you have set UITableViewDataSource in your .h file
I have two buttons for adding and deleting the textfields. Adding works fine but when I click on delete it deletes only the last added textfield. Here are my two methods:
-(void)addTextField {
keyTextField = [[UITextField alloc] initWithFrame:CGRectMake(10, yAxisDistance, 150, 30)];
keyTextField.borderStyle = UITextBorderStyleRoundedRect;
keyTextField.placeholder = #"Key Value";
keyTextField.delegate = self;
[self.view addSubview:keyTextField];
valueTextField = [[UITextField alloc] initWithFrame:CGRectMake(165, yAxisDistance, 150, 30)];
valueTextField.borderStyle = UITextBorderStyleRoundedRect;
valueTextField.placeholder = #"Value";
valueTextField.delegate = self;
[self.view addSubview:valueTextField];
yAxisDistance = yAxisDistance+35;
}
-(void)deleteTextField {
[keyTextField removeFromSuperview];
[valueTextField removeFromSuperview];
yAxisDistance = yAxisDistance-35;
}
I know it's an small issue but I am very new to this field so kindly help.
Use this code for remove specific textfield from UIView. But First you have to set tag of every UITextField in view when you create or add it in view.
for ( UITextField* textField in view.subviews )
{
if(textField.tag== 1)
{
[textField removeFromSuperview];
}
}
I think the problem lies with the outlet. Can you check the following:
Open the outlets that are connected to the textifeld in the IB. There should be gray dots inside circles on the left side of the editor. Are they seem correct for both text fields?
Setup a breakpoint inside deleteTextField method and check the two textfields. Verify that both properties are not nil.
PS: You don't need to add tags to your view, using properties is perfectly fine and even better in my opinion. The reason for your problem is something else. Also, you do not need to removeFromSuperview, you can also setHidden:YES.
Sorry that time I was not understand your problem...
I done with this:
Declare one
NSMutableArray *allTextfieldArray;
and initialise in
viewdidload
method..
now do:
-(void)addTextField {
keyTextField = [[UITextField alloc] initWithFrame:CGRectMake(10, yAxisDistance, 150, 30)];
keyTextField.borderStyle = UITextBorderStyleRoundedRect;
keyTextField.placeholder = #"Key Value";
keyTextField.delegate = self;
[self.view addSubview:keyTextField];
valueTextField = [[UITextField alloc] initWithFrame:CGRectMake(165, yAxisDistance, 150, 30)];
valueTextField.borderStyle = UITextBorderStyleRoundedRect;
valueTextField.placeholder = #"Value";
valueTextField.delegate = self;
[self.view addSubview:valueTextField];
yAxisDistance = yAxisDistance+35;
[allTextfieldArray addObject:keyTextField];
[allTextfieldArray addObject:valueTextField];
}
if ([allTextfieldArray count]>0) {
UITextField *txtField = [allTextfieldArray lastObject];
[allTextfieldArray removeLastObject];
[txtField removeFromSuperview];
txtField = nil;
UITextField *txtField2 = [allTextfieldArray lastObject];
[allTextfieldArray removeLastObject];
[txtField2 removeFromSuperview];
txtField2 = nil;
yAxisDistance = yAxisDistance-35;
}
you store the last textField in your variables keyTextField and valueTextField. So when you call your deleteTextField the last both will be deleted. you must track which textFileds you want exactly to delete.
for example you could give all your textFields a tag number when you create them:
first create an int as counter:
#implementation YourClass {
int tagcounter;
}
in init method set your counter:
tagcounter = 0;
in your addTextField:
keyTextField.tag = tagcounter++;
valueTextField.tag = tagcounter++;
when the delete button is tapped, you must know the textfield tags and pass them to your deleteTextField method. There you could do something like:
-(void)deleteTextFieldWithTag:(int)tagnumber {
for (UIView *view in [self.view subviews])
{
if ([view isKindOfClass:[UITextField class]])
{
if (view.tag == tagnumber || view.tag == tagnumber+1) {
[view removeFromSuperview];
}
}
}
I am trying to show UIPickerView with UIToolBar but getting some error.
Here is my code -
CGRect toolbarTargetFrame = CGRectMake(0, self.view.bounds.size.height-216-44, 320, 44);
CGRect datePickerTargetFrame = CGRectMake(0, self.view.bounds.size.height-216, 320, 216);
UIView *darkView = [[UIView alloc] initWithFrame:self.view.bounds];
darkView.alpha = 0;
darkView.backgroundColor = [UIColor blackColor];
darkView.tag = 9;
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissDatePicker:)];
[darkView addGestureRecognizer:tapGesture];
[self.view addSubview:darkView];
UIDatePicker *picker = [[UIDatePicker alloc] init];
picker.autoresizingMask = UIViewAutoresizingFlexibleWidth;
picker.datePickerMode = UIDatePickerModeDate;
[picker addTarget:self action:#selector(dueDateChanged:) forControlEvents:UIControlEventValueChanged];
[picker setFrame:CGRectMake(0,235,320,120)];
picker.backgroundColor = [UIColor blackColor];
[self.view addSubview:picker];
UIToolbar *toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, self.view.bounds.size.height, 320, 44)];
toolBar.tag = 11;
toolBar.barStyle = UIBarStyleBlackTranslucent;
UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil] ;
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(dismissDatePicker:)];
[toolBar setItems:#[spacer, doneButton]];
[self.view addSubview:toolBar];
[UIView beginAnimations:#"MoveIn" context:nil];
toolBar.frame = toolbarTargetFrame;
picker.frame = datePickerTargetFrame;
darkView.alpha = 0.5;
[UIView commitAnimations];
Getting error on this line -
picker.frame = datePickerTargetFrame;
This is Error -
*** Assertion failure in -[UIPickerTableView _createPreparedCellForGlobalRow:withIndexPath:], /SourceCache/UIKit_Sim/UIKit-2903.2/UITableView.m:7768
2013-10-03 13:43:12.688 Mistoh Beta 1[7228:a0b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource is not set'
libc++abi.dylib: terminating with uncaught exception of type NSException
Please Help me.Thank you in advance.
I had the same problem, it's some crash that appeared starting at iOS7.03.
It can be solved by moving
[self.view addSubview:picker]; at the end of your routine, basically after setting picker's frame. i.e.
picker.frame = datePickerTargetFrame;
[self.view addSubview:picker]; must be added after all pickers manipulations
I am using UIDatePicker as inputView so the accepted answer from Tao-Nhan didn't work for me. I've been struggling with this bug for a long time, but today I finally found an elegant work-around!
After much investigation, I found out that the crash occurs just after didMoveToSuperview is called on the input view. The trick is to use a 'wrapper' view with UIDatePicker as a subview as the inputView, and to remove the picker just as the inputView is being removed from superview, and to re-add it on the next run on runloop after it's moved to a new superview. If that sounds too confusing, just use the code below as your input view and you'll be fine.
TL;DR Using UIDatePicker as inputView? Here is the workaround that I found:
GSDatePickerInputView.h:
#import <UIKit/UIKit.h>
#interface GSDatePickerInputView : UIView
#property (nonatomic, readonly) UIDatePicker *datePicker;
#property (nonatomic) BOOL useWorkaroundToAvoidCrash;
#end
GSDatePickerInputView.m:
#import "GSDatePickerInputView.h"
#interface GSDatePickerInputView ()
#property (nonatomic, strong, readwrite) UIDatePicker *datePicker;
#end
#implementation GSDatePickerInputView
- (instancetype)init {
if (self = [super initWithFrame:CGRectMake(0, 0, 320, 166)]) {
self.translatesAutoresizingMaskIntoConstraints = NO;
self.backgroundColor = [UIColor whiteColor];
UIDatePicker *datePicker = [[UIDatePicker alloc] init];
datePicker.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierISO8601];
datePicker.backgroundColor = [UIColor whiteColor];
[self addSubview:datePicker];
self.datePicker = datePicker;
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
self.datePicker.frame = self.bounds;
}
- (void)willMoveToSuperview:(UIView *)newSuperview {
if (self.useWorkaroundToAvoidCrash == YES) {
if (newSuperview == nil) {
[self.datePicker removeFromSuperview];
}
}
}
- (void)didMoveToSuperview {
if (self.useWorkaroundToAvoidCrash == YES) {
if (self.superview != nil) {
dispatch_async(dispatch_get_main_queue(), ^{
[self addSubview:self.datePicker];
self.datePicker.frame = self.bounds;
});
}
}
}
#end
The key pieces are the methods willMoveToSuperview: and didMoveToSuperview. The dispatch_async GCD function is used to put the datePicker back after the crash would've occurred.
You can then use an instance of this inputView like this:
GSDatePickerInputView *dateInputView = [[GSDatePickerInputView alloc] init];
dateInputView.useWorkaroundToAvoidCrash = YES;
[dateInputView.datePicker addTarget:self action:#selector(datePickerChanged:) forControlEvents:UIControlEventValueChanged];
yourView.inputView = dateInputView;
And you can access the datePicker itself later using this code:
((GSDatePickerInputView *)yourView.inputView).datePicker
One last note - the property useWorkaroundToAvoidCrash is there for cases when in one place it was crashing but in another place it wasn't (which happened to me). It's obviously better to avoid such hackery whenever possible, so only set this property to YES in places where it's actually crashing.
UIDatePicker manages a UIPicker internally. So, the message contains UIPicker in it.
Now to the actual error message:
Do you have enough room when you are trying to show the DatePicker?
One of the reason it will throw this error is if could not find enough real estate to display the entire view.
I've had a similar problem where I had to change the maximumDate and minimumDate on UIDatePicker that was a subview of an inputView on one of many UITextFields in my UITableView, after a lot of tracking it appeared that the problem was setting both dates at the same time. The only way I was able to get this working is by removing the UIDatePicker from my custom input view entirely and creating and adding it back in and setting the new min and max date values. This is the ugliest thing I was forced to do in quite some time.
Have the same problem with UIPickerView in a custom UITableViewCell. I have moved all logic that had dealt with placing of the Picker view on the parent view plus settings it's constraints to - (void)layoutSubviews
After updates it looked like the next way:
- (void)layoutSubviews
{
[super layoutSubviews];
[self addSubview:YOUR_PICKER_VIEW]; //'self' in my case was UITableViewCell
[self addConstraints:PICKER_VIEW_CONSTRAINTS];
}
I had similar crash. I put my code in dispatch_after and crash resolved.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (textField == _txtFieldEndDate)
{
_datePicker.maximumDate = [NSDate dateWithDaysFromNow:100 * 365];
[_datePicker setDate:[NSDate date]];
}
else if (textField == _txtFieldStrtDate)
{
_datePicker.maximumDate = [NSDate date];
}
});