I implemented a simple UIPickerView in my app and I keep getting warnings that I can't explain about incomplete implementation and "method in protocol not completed". I went through a bunch of examples and could not figure out what am I missing.
Here is my code:
.h
#interface ViewTestViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UIPageViewControllerDataSource, UIPageViewControllerDataSource> {
UIPickerView *pickerView;
NSMutableArray *pickerList;
....
}
#property (nonatomic, retain) IBOutlet UIPickerView *pickerView;
#property (nonatomic, retain) NSMutableArray *pickerList;
#end
.m
- (void)viewDidLoad
{
[super viewDidLoad];
…
//PICKER AREA
pickerList = [[NSMutableArray alloc] init];
[pickerList addObject:#"aaa"];
[pickerList addObject:#"bbb"];
CGRect pickerFrame = CGRectMake(0, 200, 0, 0);
pickerView = [[UIPickerView alloc] initWithFrame:pickerFrame];
pickerView.showsSelectionIndicator = YES;
}
-(IBAction)showPicker:(id)sender {
[self.view addSubview:pickerView];
}
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView
{
return 1;
}
-(NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)component
{
return [pickerList count];
}
-(NSString *)pickerView:(UIPickerView *)thePickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return [pickerList objectAtIndex:row];
}
-(void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
NSLog(#"Selected item: %# index of selected item: %i", [pickerList objectAtIndex:row], row);
}
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component
{
return 200;
}
You need to conform to the UIPickerViewDelegate and UIPickerViewDataSource in your .h like you do for UITableViewDelegate, UITableViewDataSource etc (you're currently not)
#interface ViewTestViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate, UITableViewDelegate, UITableViewDataSource, UIPageViewControllerDataSource, UIPageViewControllerDataSource> {
Also, make sure you are setting self as the picker view delegate and data source when you create it:
//PICKER AREA
pickerList = [[NSMutableArray alloc] init];
[pickerList addObject:#"aaa"];
[pickerList addObject:#"bbb"];
CGRect pickerFrame = CGRectMake(0, 200, 0, 0);
pickerView = [[UIPickerView alloc] initWithFrame:pickerFrame];
pickerView.showsSelectionIndicator = YES;
pickerView.dataSource = self;
pickerView.delegate = self;
In your .h file you declare yourself as conforming to these protocols:
<UITableViewDelegate, UITableViewDataSource, UIPageViewControllerDataSource, UIPageViewControllerDataSource>
Each of those protocols involves some methods you have to implement (see the documentation on each one for the details). If you don't implement all the required methods, you will get this warning.
Related
I have created a custom picker view with xib which loads a data from the array and displays it properly. Now my problem is, this picker view does not get scrolled. Actually this picker view is loaded on to another view. So when i click into the picker view, the click appears to be on the base view on which this has been loaded.
Below is the code. Can any one please tell how do i correct this problem. Thanks
#import <UIKit/UIKit.h>
#class PickerView;
#protocol PickerViewDelegate <NSObject>
-(void) didSelectValueAtIndex;
#end
#interface PickerView : UIView <UIPickerViewDataSource, UIPickerViewDelegate>
#property (strong, nonatomic) IBOutlet UIPickerView *pickerView;
#property (nonatomic,weak) id<PickerViewDelegate> PickerViewDelegate;
-(id) showPickerView : (UIButton *) senderButton dataArray: (NSArray *) dataArray viewframe: (CGRect) viewFrame;
-(void) hidePickerView : (UIButton *) senderButton;
#end
#import "PickerView.h"
#interface PickerView ()
#property (nonatomic,retain) NSArray * pickerData;
#property (nonatomic,retain) UIButton *button;
#end
#implementation PickerView
#synthesize pickerView;
#synthesize PickerViewDelegate;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
-(id) showPickerView : (UIButton *) senderButton dataArray: (NSArray *) dataArray viewframe:(CGRect)viewFrame{
self.button = senderButton;
self.pickerView = (UIPickerView *)[super init];
if (self) {
//inorder to load xib
NSArray *theView = [[NSBundle mainBundle] loadNibNamed:#"PickerView" owner:self options:nil];
UIView *pickerviewLoadedFromXib = [theView objectAtIndex:0];
CGRect btn = senderButton.frame;
self.pickerData = dataArray;
pickerviewLoadedFromXib.frame = CGRectMake(btn.origin.x , btn.origin.y+ viewFrame.size.height, pickerviewLoadedFromXib.frame.size.width, pickerviewLoadedFromXib.frame.size.height);
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
pickerviewLoadedFromXib.frame = CGRectMake(btn.origin.x, btn.origin.y+btn.size.height, btn.size.width, 200);
[UIView commitAnimations];
[senderButton.superview addSubview:self];
[self addSubview:pickerviewLoadedFromXib];
}
return self;
}
-(void) hidePickerView : (UIButton *) senderButton{
NSLog(#"hide picker view");
}
-(NSInteger) numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
-(NSInteger) pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return self.pickerData.count;
}
-(NSString *) pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return [self.pickerData objectAtIndex:row];
}
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
NSLog(#"selectd value %#", [self.pickerData objectAtIndex:row]);
}
#end
pickerviewLoadedFromXib.delegate = self;
pickerviewLoadedFromXib.dataSource = self;
Pop these two in after you get the pickerviewloadedfromxib variable...
I have this code in the .h file :
#import <UIKit/UIKit.h>
#interface NFModalPickerView : NSObject
#end
#protocol NFModalPickerViewDelegate<NSObject>
#optional
- (void)titleSelected:(NFModalPickerView *) modalPickerView title:(NSString *) title;
#required
- (void)done:(NFModalPickerView *) modalPickerView;
#end
#interface NFModalPickerView()
{
id <NFModalPickerViewDelegate> delegate;
}
#property (nonatomic, strong) NSMutableArray * objectArray;
#property (nonatomic, strong) id <NFModalPickerViewDelegate> delegate;
- (void) show;
#end
and this code in the .m file :
#import "NFModalPickerView.h"
#interface NFModalPickerView()<UIPickerViewDelegate,UIPickerViewDataSource>
#end
#implementation NFModalPickerView
#synthesize objectArray;
#synthesize delegate;
UIActionSheet *actionSheet;
UIPickerView *pickerView ;
UISegmentedControl *closeButton;
- (void) show{
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil
delegate:nil
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
[actionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
CGRect pickerFrame = CGRectMake(0, 40, 0, 0);
pickerView = [[UIPickerView alloc] initWithFrame:pickerFrame];
pickerView.showsSelectionIndicator = YES;
pickerView.dataSource = self;
pickerView.delegate = self;
[actionSheet addSubview:pickerView];
pickerView = nil;
closeButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:#"Done"]];
closeButton.momentary = YES;
closeButton.frame = CGRectMake(260, 7.0f, 50.0f, 30.0f);
closeButton.segmentedControlStyle = UISegmentedControlStyleBar;
closeButton.tintColor = [UIColor blackColor];
[closeButton addTarget:self action:#selector(dismissActionSheet:) forControlEvents:UIControlEventValueChanged];
[actionSheet addSubview:closeButton];
closeButton = nil;
[actionSheet showInView:[[UIApplication sharedApplication] keyWindow]];
[actionSheet setBounds:CGRectMake(0, 0, 320, 485)];
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
return [objectArray count];
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
return [objectArray objectAtIndex:row];
}
-(void) dismissActionSheet:(id)sender {
UIActionSheet *actionSheet = (UIActionSheet *)[(UIView *)sender superview];
[actionSheet dismissWithClickedButtonIndex:0 animated:YES];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
[[self delegate] titleSelected:self title:[objectArray objectAtIndex:row]];
}
#end
and finally this code in my ViewController
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
pickerView = [[NFModalPickerView alloc] init];
pickerView.objectArray = [[NSMutableArray alloc] init];
[pickerView.objectArray addObject:#"Don personnel"];
[pickerView.objectArray addObject:#"Don d'entreprise"];
[pickerView setDelegate:self];
[pickerView show];
return NO;
}
I'm always getting a bad access error when using NFModalPickerView as the delegate of the pickerview. If i put all the code in the view controller using the view controller as the delegate of the picker view it works fine. I need to have a separate class to reuse the modalpickerview and not always put all the code in each of my view controllers. Anyone can help me with this?
If you are using ARC, UIPickerView 's delegate might be auto-released. Either use the UIViewController as the dataSource and the delegate for the UIPickerView, or if you are using a separate object to manage the UIPickerView, keep it as a property so that it is not released.
The default scroll setting for a UIPickerView is set to vertical. Is it possible to implement a UIPickerView horizontally?
If so, could you please show me a sample or direct me where to helpful documentation?
you can use CPPickerView .. A custom, configurable, horizontal version of UIPickerView (based on the spinning-wheel or slot-machine metaphor), with an included table cell implementation. Originally intended for condensing the space/rows needed for a multi-option setting.
IN .h File
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UIPickerViewDelegate> {
IBOutlet UIPickerView *pickerView;
NSMutableArray *itemArray;
IBOutlet UILabel *myLabel;
}
#property (nonatomic, retain) UIPickerView *pickerView;
#property (nonatomic, retain) UILabel *myLabel;
#end
IN .XIB File
drag and drop UIPickerView And One UILable
Also connect BOTH the “delegate” and “Referencing Outlet” to the FileOwner.
IN .M File
#import "ViewController.h"
#implementation ViewController
#synthesize pickerView, myLabel;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.pickerView.delegate = self;
self.pickerView.showsSelectionIndicator =YES;
self.pickerView.backgroundColor = [UIColor blackColor];
CGAffineTransform rotate = CGAffineTransformMakeRotation(M_PI_2);
rotate = CGAffineTransformScale(rotate, 0.1, 0.8);
[self.pickerView setTransform:rotate];
self.pickerView.center = CGPointMake(160,75);
UILabel *theview[20];
CGAffineTransform rotateItem = CGAffineTransformMakeRotation(-M_PI_2);
rotateItem = CGAffineTransformScale(rotateItem, 1, 10);
for (int i=0;i<20;i++) {
theview[i] = [[UILabel alloc] init];
theview[i].text = [NSString stringWithFormat:#"%d",i];
theview[i].textColor = [UIColor blackColor];
theview[i].frame = CGRectMake(0,0, 100, 100);
theview[i].backgroundColor = [UIColor clearColor];
theview[i].textAlignment = NSTextAlignmentCenter; //UITextAlignmentCenter is deprecated.
theview[i].shadowColor = [UIColor whiteColor];
theview[i].shadowOffset = CGSizeMake(-1,-1);
theview[i].adjustsFontSizeToFitWidth = YES;
UIFont *myFont = [UIFont fontWithName:#"Georgia" size:15];
[theview[i] setFont:myFont];
theview[i].transform = rotateItem;
}
itemArray = [[NSMutableArray alloc] init];
for (int j=0;j<20;j++) {
[itemArray addObject:theview[j]];
}
}
#pragma mark -
#pragma mark Picker View Methods
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView {
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)component {
return [itemArray count];
}
- (UIView *)pickerView:(UIPickerView *)thePickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
return [itemArray objectAtIndex:row];
}
- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
myLabel.text = [NSString stringWithFormat:#"SELECTED: %d", row+1];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
Here is my .h file
When I run this code and select a text field, a pickerview pop's with question marks in it
but when I select question mark I get correct values in text field
#import <UIKit/UIKit.h>
#import "ScrollableViewController.h"
#import "MIBackgroundTapDelegate.h"
//#interface Activapc1 : UIViewController {
#interface Activapc1 : ScrollableViewController <MIBackgroundTapDelegate, UIPickerViewDelegate, UIPickerViewDataSource>{
UITextField *amplitude1;
UITextField *rate1;
UITextField *pulse_width1;
UITextField *impedance1;
IBOutlet UITextField *configuration;
NSArray *mode;
}
#property (nonatomic, retain) IBOutlet UITextField *amplitude1;
#property (nonatomic, retain) IBOutlet UITextField *rate1;
#property (nonatomic, retain) IBOutlet UITextField *pulse_width1;
#property (nonatomic, retain) IBOutlet UITextField *impedance1;
-(IBAction)next;
-(IBAction)skip;
-(IBAction)home;
-(IBAction)select;
-(IBAction)textFieldDoneEditing:(id) sender;
#end
Here is .m file
I am not able to understand why I am getting question mark please help me
#import "Activapc1.h"
#import "dbsViewController.h"
#import "Activapc2.h"
#import "APCoption.h"
#implementation Activapc1
#synthesize amplitude1;
#synthesize rate1;
#synthesize pulse_width1;
#synthesize impedance1;
const int MyModePicker = 3002;
-(void)viewDidLoad {
self.svScrollViewM.contentSize = CGSizeMake(320, 416);
[self registerForEditingEvents:amplitude1];
[self registerForEditingEvents:rate1];
[self registerForEditingEvents:pulse_width1];
[self registerForEditingEvents:impedance1];
UIPickerView *modePicker = [[UIPickerView alloc] initWithFrame:CGRectZero];
modePicker.tag = MyModePicker;
modePicker.delegate = self;
modePicker.dataSource = self;
[modePicker setShowsSelectionIndicator:YES];
configuration.inputView = modePicker;
[modePicker release];
[super viewDidLoad];
//Prepare data for pickers
mode = [NSArray arrayWithObjects:#"Voltage",#"Current",nil];
[mode retain];
//mode = [[NSMutableArray alloc] init];
//[mode addObject]
}
//********picker view code**************
#pragma mark -
#pragma mark UIPickerViewDelegate
-(NSString *)pickerView:(UIPickerView *)pickerView titileForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
if(pickerView.tag == MyModePicker)
{
return [mode objectAtIndex:row];
}
return #"Unknown title";
}
-(void) pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
if(pickerView.tag == MyModePicker)
{
configuration.text = (NSString *)[mode objectAtIndex:row];
}
}
#pragma mark -
#pragma mark UIPickerViewDataSource
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if(pickerView.tag == MyModePicker)
{
return mode.count;
}
return 1;
}
#pragma mark -
//**********picker view code end************
-(IBAction) backgroundTap:(id) sender{
[self.amplitude1 resignFirstResponder];
[self.rate1 resignFirstResponder];
[self.pulse_width1 resignFirstResponder];
[self.impedance1 resignFirstResponder];
}
-(IBAction) textFieldDoneEditing:(id)sender{
[sender resignFirstResponder];
}
-(IBAction)home {
dbsViewController *dbs = [[dbsViewController alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:dbs animated:YES];
}
-(IBAction)skip {
Activapc2 *activapc2 = [[Activapc2 alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:activapc2 animated:YES];
}
-(IBAction)next {
Activapc2 *activapc2 = [[Activapc2 alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:activapc2 animated:YES];
}
-(IBAction)select {
APCoption *apcoption = [[APCoption alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:apcoption animated:YES];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[mode release];
[super dealloc];
}
#end
The pickerview needs a title not a titile. Also the delegate method that returns the string does not have a reusingView: parameter. Since you don't properly implement the delegate method the picker simply displays question marks.
-(NSString *)pickerView:(UIPickerView *)pickerView titileForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view;
I believe it should be:
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;
Issue with subviews but it may be related to the AppDelegate with respect to placing a UIPickerView in myView as apposed to self.view?
Thanks
[self.view addSubview:pickerView]; <-- works ok
//[myView addSubview:pickerView];<-- fails, can't get dial movement or response
AppDelegate.h
#import <UIKit/UIKit.h>
#class PickerViewController;
#interface PickerViewAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
PickerViewController *pvController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#end
AppDelegate.m
#import "PickerViewAppDelegate.h"
#import "PickerViewController.h"
#implementation PickerViewAppDelegate
#synthesize window;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
pvController = [[PickerViewController alloc] initWithNibName:#"PickerView" bundle:[NSBundle mainBundle]];
[window addSubview:pvController.view];
// Override point for customization after application launch
[window makeKeyAndVisible];
}
- (void)dealloc {
[pvController release];
[window release];
[super dealloc];
}
#end
Controller.h
#import <UIKit/UIKit.h>
#interface PickerViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate> {
IBOutlet UIPickerView *pickerView;
NSMutableArray *arrayColors;
}
#end
Controller.m
#import "PickerViewController.h"
#implementation PickerViewController
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 100, 100, 100)];
[myView setBackgroundColor:[UIColor blueColor]];
[self.view addSubview:myView];
UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 100.0)];
pickerView.delegate = self;
pickerView.showsSelectionIndicator = YES;
arrayColors = [[NSMutableArray alloc] init];
for (int i=0; i<60; i++) {
[arrayColors addObject:[NSString stringWithFormat:#"%d", i]];
}
//[self.view addSubview:pickerView]; // <-- works
[myView addSubview:pickerView]; // <-- this fails.. this is what I need for multiple views
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
- (void)dealloc {
[arrayColors release];
[super dealloc];
}
#pragma mark -
#pragma mark Picker View Methods
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView {
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)component {
return [arrayColors count];
}
- (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [arrayColors objectAtIndex:row];
}
- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
NSLog(#"Selected Color: %#. Index of selected color: %i", [arrayColors objectAtIndex:row], row);
}
#end
If you comment
[myView addSubview:pickerView];
you will understand, that myView frame is too small. You will be able to interact with the picker only touching that parent view frame. If you want to make the pickers behave normally, you must set the parent view frame to contain the picker frame - make it equal or larger.
Please remember iOs Human Interface Guidelines,
The overall size of a picker, including its background, is fixed at the same size as the keyboard on iPhone.
Make sure that myView has userInteractionEnabled set to YES?