I am trying to use a PickerView with ARC turned off, it has become a nightnmare, will be extremely grateful if someone could please have a quick look kindly suggest how to solve...thnx in advance
the issue is that the rest of my app is non-arc and so i want to add the pickerview as a class that can operate as a viewcontroller in the project...
I had multiple pickers working beautifully 4 days ago with arc but when i turned arc off it became a nightmare...to identify the precise issue i have removed all the frills and am just working with a bare structure now....there are no errors but the data from the array is not displaying...i am listing the header and omplementation files below...the reason i had linked the folder was to make the interface file available....so that the connections can be checked too...but we can look at that after the basic code is first checked....thanks so much for your kind attention and time...
.h
#import <UIKit/UIKit.h>
#interface HomeViewController : UIViewController UIPickerViewDataSource,UIPickerViewDelegate>
{NSArray *categoryTypes;
}
#property (retain, nonatomic) IBOutlet UIPickerView *categoryTypePicker;
#property (retain, nonatomic) IBOutlet UIButton *categoryTypeBtn;
#end
.m
#import "HomeViewController.h"
#interface HomeViewController ()
#define kPICKER1COLUMN 1
#define kCATEGORYTYPEPICKERTAG 21
#define kCATEGORYTYPEBTN 31
#end
#implementation HomeViewController
#synthesize categoryTypeBtn;
#synthesize categoryTypePicker;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
categoryTypes = [[NSArray alloc] initWithObjects:#"Appetizers",#"Breakfast",#"Dessert",#"Drinks",
#"Main Dish/Entree", #"Salad", #"Side Dish", #"Soup", #"Snack",
#"Baby Food", #"Pet Food", nil];
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
categoryTypePicker.tag = kCATEGORYTYPEPICKERTAG;
categoryTypePicker.showsSelectionIndicator = TRUE;
categoryTypePicker.dataSource = self;
categoryTypePicker.delegate = self;
self.categoryTypePicker.dataSource = self;
self.categoryTypePicker.delegate = self;
[self.categoryTypePicker reloadAllComponents];
categoryTypePicker.hidden = YES;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (int)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
if (pickerView.tag == kCATEGORYTYPEPICKERTAG)
return kPICKER1COLUMN;
else { return 0; }
}
- (int)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if (pickerView.tag == kCATEGORYTYPEPICKERTAG)
return [categoryTypes count];
else { return 0; }
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
if (pickerView.tag == kCATEGORYTYPEPICKERTAG)
return [categoryTypes objectAtIndex:row];
else { return 0; }
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
if (pickerView.tag == kCATEGORYTYPEPICKERTAG)
{
NSString *categoryType = [categoryTypes objectAtIndex:[categoryTypePicker selectedRowInComponent:0]];
[categoryTypeBtn setTitle:categoryType forState:UIControlStateNormal];
NSLog(#"%#", categoryType);
}
pickerView.hidden=YES;
}
-(IBAction) showCategoryTypePicker{
{
[self.view addSubview:categoryTypePicker];
categoryTypePicker.hidden = NO;
}
}
- (void)viewDidUnload {
[super viewDidUnload];
}
- (void)dealloc {
[categoryTypes release];
[categoryTypePicker release];
[super dealloc];
}
#end
i will await your reply...
linktocode
[dont have access to comments so am responding here] thanks rdelmar i commented out the init-bundle and the subview of the button but now the build is giving the error bad access...i have a rough idea of what is going on but don't know how to address it...the issue is basically that the array is not retained for the objectAtIndex call...need some way of retaining it...thnx
Related
So I've followed everything this post Default Picker Value iphone says, but I can't seem to get my picker to work.
Here's my .m snippet:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.arrPercent = #[#"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9",#"10",#"11",#"12",#"13",#"14",#"15",#"16",#"17",#"18",#"19",#"20",#"21",#"22",#"23",#"24",#"25",#"26",#"27",#"28",#"29",#"30",#"31",#"32",#"33",#"34",#"35",#"36",#"37",#"38",#"39",#"40",#"41",#"42",#"43",#"44",#"45",#"46",#"47",#"48",#"49",#"50"];
self.arrPeople = #[#"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9",#"10",#"11",#"12",#"13",#"14",#"15",#"16",#"17",#"18",#"19",#"20"];
self.percent = [NSNumber numberWithInt:15];
self.people = [NSNumber numberWithInt:5];
self.strSubTotal = #"";
self.myPicker.dataSource = self;
self.myPicker.delegate = self;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
//[self.myPicker selectRow:self.percent.integerValue inComponent:0 animated:YES];
[self.myPicker selectRow:5 inComponent:0 animated:YES];
[self.myPicker selectRow:5 inComponent:1 animated:YES];
[self.myPicker reloadAllComponents]; // tried commenting out this line with no luck
}
Here's my .h snippet:
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#interface ViewController : UIViewController <UIPickerViewDataSource,UIPickerViewDelegate>
#property (nonatomic,strong) NSArray *arrPercent;
#property (nonatomic,strong) NSArray *arrPeople;
#property (strong, nonatomic) IBOutlet UIPickerView *myPicker;
#property (strong, nonatomic) NSString *strSubTotal;
#property (strong, nonatomic) NSNumber *percent;
#property (strong, nonatomic) NSNumber *people;
#end
Here's the delegate stuff, I think...
// returns the number of 'columns' to display.
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 2;
}
// returns the # of rows in each component..
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent: (NSInteger)component
{
if(component== 0)
{
return [self.arrPercent count];
}
else
{
return [self.arrPeople count];
}
}
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
if(component == 0)
{
return [NSString stringWithFormat:#"%#%#", [self.arrPercent objectAtIndex:row], #"%"];
}
else
{
return [self.arrPeople objectAtIndex:row];
}
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
if(component == 0)
{
self.percent = [self.arrPercent objectAtIndex:row];
}
else
{
self.people = [self.arrPeople objectAtIndex:row];
}
[self updateSubTotal:-3];
}
When I start the emulator, the picker doesn't animate to the position I tell it to. Am I doing anything wrong? Please help!
As it turns out, the error was that for some reason, the connection between the picker in the UI was disconnected with the code. I had to hold the Control key while dragging the picker from the UI to the .h file.
I saw this because I noticed a little "empty button icon" next to the method declaration in the .h file. Once Xcode understood that the picker is controlled by the piece of code, everything works as expected.
Thank you so much!
I get the exc_bad_access error when running my project and trying to change the picker.
The error is occurring on
- (NSString*)pickerView:(UIPickerView *)pickerView
titleForRow:(NSInteger)row
forComponent:(NSInteger)component
Below is my code. From reading the other SO articles I realize I am probably not retaining my variable. I'm new and learning and appreciate the help.
#import <UIKit/UIKit.h>
#import "RootViewController.h"
#class RootViewController;
#interface AddConditionViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate> {
IBOutlet UITextField *txtConditionDetail;
IBOutlet UITextField *txtConditionArea;
IBOutlet UIPickerView *conditionNamesPicker;
NSMutableArray *names;
NSMutableArray *conditionDefs;
RootViewController *rvc;
NSString *conditionName;
}
#property (retain, nonatomic) IBOutlet UIPickerView *conditionNamesPicker;
#property (nonatomic,assign) RootViewController *rvc;
#property (nonatomic, retain) NSString *conditionName;
#property (nonatomic,assign) NSMutableArray *names;
#property (nonatomic,assign) NSMutableArray *conditionDefs;
#end
#import "AddConditionViewController.h"
#import "ConditionsAppDelegate.h"
#import "Condition.h"
#import "ConditionDef.h"
#import "Formula.h"
#implementation AddConditionViewController
#synthesize rvc, conditionNamesPicker, names, conditionDefs, conditionName;
/*
// Implement loadView to create a view hierarchy programmatically.
- (void)loadView {
}
*/
// Implement viewDidLoad to do additional setup after loading the view.
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"Add Condition";
self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
target:self action:#selector(cancel_Clicked:)] autorelease];
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemSave
target:self action:#selector(save_Clicked:)] autorelease];
self.view.backgroundColor = [UIColor groupTableViewBackgroundColor];
ConditionsAppDelegate *appDelegate = (ConditionsAppDelegate *)[[UIApplication sharedApplication] delegate];
conditionDefs = appDelegate.getConditionDefs;
self.names = [NSMutableArray arrayWithCapacity:[conditionDefs count]];
for (ConditionDef *def in conditionDefs) {
NSString *condition_name = def.condition_name;
if (!condition_name) {
condition_name = #"<Unknown Account>";
}
[names addObject:condition_name];
}
self.conditionNamesPicker.dataSource = self;
self.conditionNamesPicker.delegate = self;
NSLog(#"LINE 48");
}
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
//Set the textboxes to empty string.
txtConditionArea.text = #"";
txtConditionDetail.text = #"";
//Make the Category name textfield to be the first responder.
[txtConditionArea becomeFirstResponder];
NSLog(#"LINE 63");
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
// The number of columns of data
- (int)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
// The number of rows of data
- (int)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
NSLog(#" LINE 87 - COUNT OF CONDITION DEFS TO SHOW = %i", names.count);
[conditionNamesPicker setDataSource:self];
return [names count];
}
// The data to return for the row and component (column) that's being passed in
- (NSString*)pickerView:(UIPickerView *)pickerView
titleForRow:(NSInteger)row
forComponent:(NSInteger)component
{
// NSLog(#"LINE 94 - here is the bug: conditionDefs[row] %#", names[row]);
return names[row];
}
// Catpure the picker view selection
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
// This method is triggered whenever the user makes a change to the picker selection.
// The parameter named row and component represents what was selected.
conditionName = names[row];
}
- (void) save_Clicked:(id)sender {
ConditionsAppDelegate *appDelegate = (ConditionsAppDelegate *)[[UIApplication sharedApplication] delegate];
//Create a Condition Object.
Condition *c = [[Condition alloc] init];
NSInteger newId = c.getNextConditionId;
Condition *cond = [[Condition alloc] initWithPrimaryKey:newId];
cond.condition_area = txtConditionArea.text;
cond.condition_detail = txtConditionDetail.text;
cond.condition_name = conditionName;
//Add the object
// [appDelegate addCondition:cond];
[appDelegate populateFromDatabase];
// ADD TO THE ARRAY:
// [cvc.categories addObject:cond];
// [cvc.Conditions addObject:cond];
rvc.Conditions = [appDelegate activeConditions];
// UPDATE THE TABLEVIEW
[rvc.tableView reloadData];
// release
[cond release];
[c release];
//Dismiss the controller.
[self.navigationController dismissViewControllerAnimated:YES completion: nil];
}
- (void) cancel_Clicked:(id)sender {
//Dismiss the controller.
[self.navigationController dismissViewControllerAnimated:YES completion: nil];
}
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
NSLog(#"LINE 159");
[theTextField resignFirstResponder];
return YES;
}
- (void)dealloc {
[txtConditionArea release];
[txtConditionDetail release];
[conditionNamesPicker release];
[super dealloc];
}
#end
Please change the property assign toretain for names property. And other array or those object inheriting fromNSObject. It is an object and you are keeping it as assign property. Use assign only for primitive data type. Try this and let me know.
You are setting the data source of PickerView in one the DataSource methods. This is not valid. Remove the below line
[conditionNamesPicker setDataSource:self];
from function:
numberOfRowsInComponent:
You are setting it again.
I'm trying to bring up a picker view instead of a keyboard to put in a textfield, but my picker view doesn't show.
#import "SettingsViewController.h"
#import "FindClasses.h"
#interface SettingsViewController ()
#property (weak, nonatomic) IBOutlet UIBarButtonItem *saveButton;
#property (weak, nonatomic) IBOutlet UITextField *classTextField;
#property (strong, nonatomic) UIPickerView *picker;
#property (nonatomic, strong) FindClasses *finder;
#property (nonatomic, strong) NSArray *itemsArray;
#end
#implementation SettingsViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *itemsArray = [self.finder findClassesInTimetable];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)presentPicker {
CGRect frame = CGRectMake(0, 40, 0, 0);
UIPickerView *picker = [[UIPickerView alloc] initWithFrame:frame];
picker.delegate = self;
picker.dataSource = self;
// TODO: animate this on screen
[self.view addSubview:picker];
}
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[self presentPicker];
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return [self.itemsArray count]; //where items is your array of items
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row inComponent:(NSInteger)component {
return [self.itemsArray objectAtIndex:row];
}
Can someone tell me what I'm doing wrong? I took the example from another Stackoverflow post:
This is how I use UIPickerViews, with sample code:
UIPickerView* genderPicker = [[UIPickerView alloc] init];
genderPicker.delegate = self;
genderPicker.dataSource = self;
After initializing your UITextField (registrationGenderField in my case):
registrationGenderField.inputView = genderPicker;
And then the delegates and dataSources:
- (NSString *) pickerView:(UIPickerView *)pickerView
titleForRow:(NSInteger)row
forComponent:(NSInteger)component {
switch (row) {
case 0:
return #"Gender";
break;
case 1:
return #"Male";
break;
case 2:
return #"Female";
break;
default:
return #"Gender";
break;
}
}
- (void) pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
switch (row) {
case 0:
registrationGenderField.text = #"";
break;
case 1:
registrationGenderField.text = #"Male";
break;
case 2:
registrationGenderField.text = #"Female";
break;
default:
registrationGenderField.text = #"";
break;
}
}
- (NSInteger) numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
- (NSInteger) pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return 3;
}
Hope it helps you
- (void)presentPicker {
UIPickerView *picker = [[UIPickerView alloc] init];
picker.delegate = self;
picker.dataSource = self;
// TODO: animate this on screen
classTextField .delegate = self;
classTextField.inputView = picker;
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
[textField becomeFirstResponder];
return YES;
}
you just have to alloc init your pickerview;
and set its delegate to self and also add uipickerviewdelegate and datasource in .h file
than in textfieldbegin editing add [textField setInputView:picker];
also implement textfieldshouldreturn
I have been working on a multi-component picker and I wanted to set the defaults for the various components. The code looks like the following.
#import "MathTablesSelectVC.h"
#interface MathTablesSelectVC ()
#property (weak, nonatomic) IBOutlet UIPickerView *problemDifficultyTypeTable;
#property NSArray *problemDifficulties;
#property NSArray *problemTypes;
#property NSArray *problemTables;
#end
#implementation MathTablesSelectVC
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
NSLog(#"0");
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
NSLog(#"1");
[super viewDidLoad];
_problemDifficulties = #[#"Practice", #"Slow", #"Normal", #"Fast"];
_problemTypes = #[#"Addition", #"Subtraction", #"Multiplication", #"Division", #"Remainders"];
_problemTables = #[#" 0's", #" 1's", #" 2's", #" 3's", #" 4's", #" 5's", #" 6's", #" 7's", #" 8's", #" 9's", #"10's", #"11's", #"12's", #"All"];
}
-(void)viewWillAppear:(BOOL)animated {
NSLog(#"2");
[super viewWillAppear:animated];
[_problemDifficultyTypeTable selectRow:1 inComponent:0 animated:NO];
[_problemDifficultyTypeTable selectRow:0 inComponent:1 animated:NO];
[_problemDifficultyTypeTable selectRow:1 inComponent:2 animated:NO];
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
NSLog(#"3");
return 3;
}
-(CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
NSLog(#"4");
if(component == 0) {
return 150.0;
} else if(component == 1) {
return 300.0;
} else {
return 75.0;
}
}
-(CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component {
NSLog(#"5");
return 60.0;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
NSLog(#"6");
if(component == 0) {
return [_problemDifficulties count];
} else if(component == 1) {
return [_problemTypes count];
} else {
return [_problemTables count];
}
}
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
NSLog(#"7");
if(component == 0) {
return [_problemDifficulties objectAtIndex:row];
} else if(component == 1) {
return [_problemTypes objectAtIndex:row];
} else {
return [_problemTables objectAtIndex:row];
}
}
-(void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
NSLog(#"8");
}
-(void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
NSLog(#"9");
}
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(#"10");
}
#end
Now this all worked nicely for a while and then it stopped working :(
I then spent the next several hours working out what I'd done wrong.
The answer I stuffed things up when I did some refactoring. I managed to kill the connection between the storyboard and the IBOutlet. Now the nice small, very small, little circle was still there next to the #property it just no longer had a dot in it. As soon as I re-established the connection things started behaving again.
You'll also note a whole bunch of NSLog's and this seems to be the order things are first called in. We get several repeats of some of the numbers as we cycle through the components.
The other thing I broke although I picked that up pretty much straight away were the delegation connections.
I have found a lot of sample code from internet, but also doesn't work.... anyone can tell me what's wrong of my coding below? thanks a lot. SOS
//My storeboard screen
http://imageupload.org/en/file/209300/03.jpg.html
//This is PickerViewTest.h
#interface InputRound : UIViewController<UITextFieldDelegate>
{
UIPickerView *pvPickerTest;
NSMutableArray *aryMaster;
}
#property (nonatomic, retain) IBOutlet UIPickerView *pvPickerTest;
#property (nonatomic, retain) NSMutableArray *aryMaster;
#end
//This is PickerViewTest.m
#interface InputRound ()
#end
#implementation PickerViewTest
#synthesize pvPickerTest, aryMaster;
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
aryMaster = [[NSMutableArray alloc] init];
[aryMaster addObject:#"User01"];
[aryMaster addObject:#"User02"];
[aryMaster addObject:#"User03"];
}
-(NSInteger)numberOfComponentsInPickerView:(NSInteger)component
{
return 1;
}
-(NSInteger)pickerView:(UIPickerView *)picker numberOfRowsInComponent:(NSInteger)component
{
return [aryMaster count];
}
-(NSString *) pickerView:(UIPickerView *)picker titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return [aryMaster objectAtIndex:row];
}
-(void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
// Show UIPickerView
pvPickerTest.frame = CGRectMake(0, 500, pvPickerTest.frame.size.width, pvPickerTest.frame.size.height);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.50];
[UIView setAnimationDelegate:self];
pvPickerTest.frame = CGRectMake(0, 200, pvPickerTest.frame.size.width, pvPickerTest.frame.size.height);
[self.view addSubview:pvPickerTest];
[UIView commitAnimations];
return NO;
}
#end
Don't try and reinvent the wheel by rolling your own appearance animation to mimic the built in one. Set the picker view as the input view for your text field, and the system will do the animation for you:
textField.inputView = pickerView;
When you begin editing the text field, the picker is animated on screen for you. See my answer here for more details, including adding a toolbar on top with a "Done" button.