I have a textfield in my form sheet. When the textfield is typed on, I want a popover to appear with a pickerView inside. I've used popOverController before, but in this case I don't have a clue on how to place a pickerView and set it's delegate and datasource to the form sheet view controller, because actually the popover needs an independent view controller.
i tried the following (the app is universal), the popover isn't appearing:
- (IBAction)gradeTextfieldPressed:(UITextField *)sender
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
[self.nameTextField resignFirstResponder];
UIViewController *pickerController = [[UIViewController alloc] init];
UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(self.gradeTextField.center.x, self.gradeTextField.center.y, 320, 320)];
pickerView.delegate = self;
pickerView.dataSource = self;
[pickerController.view addSubview:pickerView];
UIPopoverController *pickerPopover = [[UIPopoverController alloc] initWithContentViewController:pickerController];
[pickerPopover presentPopoverFromRect:CGRectMake(self.gradeTextField.center.x, self.gradeTextField.center.y, 320, 320) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
[self.gradeTextField setInputView:pickerView];
if ([self.gradeTextField.text isEqualToString:#""]) {
[self pickerView:pickerView didSelectRow:0 inComponent:0];
}
} else if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
[self.picker setHidden:NO];
//[self pickerView:self.picker didSelectRow:0 inComponent:0];
if ([self.gradeTextField.text isEqualToString:#""]) {
[self pickerView:self.picker didSelectRow:0 inComponent:0];
}
[self.gradeTextField setInputView:self.picker];
[self.nameTextField resignFirstResponder];
[self.creditstextField resignFirstResponder];
[self.chaptersTextField resignFirstResponder];
}
}
One way to do this that I found simple Create a new controller with just the PickerView in it (in this case done with a .xib), and have a simple delegate protocol to let your form sheet controller know when something has been picked.
#protocol MyPickerDelegate <NSObject>
- (void)valuePicked:(NSString*)value
#end
#interface MyPickerController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource>
{
__weak IBOutlet UIPickerView *_pickerView;
}
#property (nonatomic, weak) id<MyPickerDelegate> delegate;
You can then implement the data source and delegate methods in this controller. Here would be the code for when the item was picked:
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
[_delegate valuePicked:[_myStrings objectAtIndex:row]];
}
And finally, in the calling class (your form sheet controller):
- (void)displayPickerFromRect:(CGRect)rect inView:(UIView*)view
{
if (!_pickerController)
_pickerController = [[MyPickerController alloc] initWithNibName:nil bundle:nil];
if (_pickerController)
{
_speedPickerController.delegate = self;
if (!_pickerPopover)
{
_pickerPopover = [[UIPopoverController alloc] initWithContentViewController:_pickerController];
_pickerPopover.popoverContentSize = _pickerController.view.frame.size;
_pickerPopover.delegate = self;
}
[_pickerPopover presentPopoverFromRect:rect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
}
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
if (_pickerController)
{
_pickerController = nil;
_pickerPopover = nil;
}
}
- (void)valuePicked:(NSString*)value
{
// do something with the picked value
// dismiss the popover if you want it to go away as soon as a value is picked
}
Related
I have a UIPickerView that is being "pushed" to UINavigationController like this:
[self.navigationController pushViewController:vc animated:YES];
I would like to set the selected row.
I added in ViewDidAppear:
for (int i = 0; i < [countryCodes count]; i++)
{
if ([[countryCodes objectAtIndex:i] isEqualToString:selectedCountryCode]){
[_countryPicker selectRow:i inComponent:0 animated:YES];
countrySelectedRow = i;
break;
}
}
[_countryPicker reloadAllComponents];
where i is dynamic (being changed based on data that is changing in that view controller)
It works only if I restart the app.
If I go back and forth in the navigation it doesn't work
How can I make the UIPickerView choose the the correct row?
I can see in debug mode that the lines in viewDidAppear are called. Maybe the component is being created and I can't change it?
This is how I create the UIPickerView:
- (void)viewDidLoad
{
_countryPicker = [[UIPickerView alloc] init];
[self initPicker:_countryPicker textField:_countryText];
}
- (void)initPicker:(UIPickerView*)pickerView textField:(UITextField*) textField
{
CGRect pickerFrame = CGRectMake(0, 0, 200, 216);
pickerView.frame = pickerFrame;
pickerView.userInteractionEnabled = YES;
pickerView.dataSource = self;
pickerView.hidden = YES;
pickerView.delegate = self;
pickerView.showsSelectionIndicator = YES;
[self.view addSubview:pickerView];
[textField setInputView:pickerView];
textField.delegate = self;
[pickerView removeFromSuperview];
}
You wrote: "where i is dynamic (being changed based on data that is changing in that view controller)""
In your code i is a local variable. Did you mean selectedCountryCode here?
for (int i = 0; i < [countryCodes count]; i++)
{
if ([[countryCodes objectAtIndex:i] isEqualToString:selectedCountryCode]){
[_countryPicker selectRow:i inComponent:0 animated:YES];
countrySelectedRow = i;
break;
}
}
[_countryPicker reloadAllComponents];
I am pretty sure selectedCountryCode is not updated correctly. Add NSLog(selectedCountryCode); to check it.
UPDATE:
It seems that problem is somewhere inside a code you did not post in the question. To check your code I created and share a project. Please find it here https://github.com/Avtolic/SOHelper If you will check it you will find that everything works ok.
After you set the selected row you then call this...
[_countryPicker reloadAllComponents];
Thats going to wipe out your selection? I would remove that line
If you make the selectedCountryCode variable part of a singleton class (for example AppDelegate or preferebly some other), and then equate the value, this is surely going to work. Here I don't understand how the selectedCountryCode is expected to be retained even after the view is popped.
I tried with making the string a part of AppDelegate (which is of course not a good practice. One should put it in another singleton class).
#import "CViewController.h"
#import "AppDelegate.h"
#interface CViewController ()<UITextFieldDelegate, UIPickerViewDelegate, UIPickerViewDataSource>
#property(nonatomic, strong) UIPickerView *countryPicker;
#property (nonatomic, weak) IBOutlet UITextField *countryText;
#property (nonatomic, strong) NSArray *countryCodes;
#property (nonatomic, assign) int countrySelectedRow;
#property (nonatomic,strong) AppDelegate *delegate;
#end
#implementation CViewController
- (void)viewDidLoad
{
self.delegate = [[UIApplication sharedApplication] delegate];
_countryPicker = [[UIPickerView alloc] init];
[self initPicker:_countryPicker textField:_countryText];
self.countryCodes = #[#"A", #"B", #"C", #"D", #"E"];
}
- (void)initPicker:(UIPickerView*)pickerView textField:(UITextField*) textField
{
CGRect pickerFrame = CGRectMake(0, 0, 200, 216);
pickerView.frame = pickerFrame;
pickerView.userInteractionEnabled = YES;
pickerView.dataSource = self;
pickerView.hidden = YES;
pickerView.delegate = self;
pickerView.showsSelectionIndicator = YES;
[self.view addSubview:pickerView];
[textField setInputView:pickerView];
textField.delegate = self;
[pickerView removeFromSuperview];
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return [self.countryCodes objectAtIndex:row];
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
// returns the # of rows in each component..
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return [self.countryCodes count];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
self.delegate.selectedCountryCode = [self.countryCodes objectAtIndex:row];
NSLog(#"picker was(is): %d",[_countryPicker selectedRowInComponent:0]);
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
for (int i = 0; i < [self.countryCodes count]; i++)
{
if ([[self.countryCodes objectAtIndex:i] isEqualToString:self.delegate.selectedCountryCode]){
[_countryPicker selectRow:i inComponent:0 animated:YES];
self.countrySelectedRow = i;
break;
}
}
[_countryPicker reloadAllComponents];
}
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
self.countryPicker.hidden = NO;
}
I have a custom class (FFFuelQuantityPickerVC) Storyboard View Controller that contains a UIPickerView and a UIButton. The UIButton is wired to an IBAction called fullButtonPressed in FFFuelQuantityPickerVC. When this View Controller is presented using a storyboard popover segue, the fullButtonPressed IBAction is fired when the UIButton is "touched up inside."
However, when I programmatically init and present FFFuelQuantityPickerVC in a popup, pressing the UIButton does not fire the IBAction. Why would that be? Here is the code that does the programmatic presentation when a button in a UITableViewCell is pressed. (self.poc is a reusable popover controller):
-(void)thisHelperPressed:(UIButton *)thisHelper inCell:(UITableViewCell *)thisCell{
if ([thisHelper.titleLabel.text isEqualToString:#"FuelPicker"]){
//init the fuel quantity picker VC
FFFuelQuantityPickerVC *fuelQuantityPickerVC;
fuelQuantityPickerVC =[[UIStoryboard storyboardWithName:#"MainStoryboard"
bundle:nil]
instantiateViewControllerWithIdentifier:#"FuelQuantityPickerVC"];
fuelQuantityPickerVC.delegate = self;
[self.poc setContentViewController:fuelQuantityPickerVC];
} else if...
}
self.poc.delegate = self;
//present it
[self.poc presentPopoverFromRect:thisHelper.frame inView:thisCell permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
.
.
.
Here is FFFuelQuantityPickerVC:
// FFFuelQuantityPickerVC.h
#import <UIKit/UIKit.h>
#protocol fuelPickerDelegate <NSObject>
-(void) fuelQuantityChangedL:(NSInteger) quantityL R:(NSInteger)quantityR;
#end
#interface FFFuelQuantityPickerVC : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate>
#property (weak, nonatomic) IBOutlet UIPickerView *thisPicker;
#property (nonatomic) NSString *fuelQuantityL;
#property (nonatomic) NSString *fuelQuantityR;
#property (nonatomic) id delegate;
- (IBAction)fullButtonPressed; //this is wired to the button
#end
//
// FFFuelQuantityPickerVC.m
#import "FFFuelQuantityPickerVC.h"
#define FUEL_MIN 0
#define FUEL_MAX 146
#define LEFT_COMPONENT 0
#define RIGHT_COMPONENT 1
#interface FFFuelQuantityPickerVC ()
#end
#implementation FFFuelQuantityPickerVC
- (void)viewDidLoad
{
[super viewDidLoad];
if (!self.fuelQuantityL){
self.fuelQuantityL = [NSString stringWithFormat:#"%i", FUEL_MAX];
}
if (!self.fuelQuantityR){
self.fuelQuantityR = [NSString stringWithFormat:#"%i", FUEL_MAX];
}
}
//set selected row to current values, if any
- (void) viewDidAppear:(BOOL)animated {
[self.thisPicker selectRow:FUEL_MAX - [self.fuelQuantityL intValue] inComponent:LEFT_COMPONENT animated:YES];
[self.thisPicker selectRow:FUEL_MAX - [self.fuelQuantityR intValue] inComponent:RIGHT_COMPONENT animated:YES];
}
//this method does not get called when the button is pressed (except when the VC is presented via storyboard popover segue)
- (IBAction)fullButtonPressed {
self.fuelQuantityL = [NSString stringWithFormat:#"%i", FUEL_MAX];
self.fuelQuantityR = [NSString stringWithFormat:#"%i", FUEL_MAX];
[self.thisPicker selectRow:0 inComponent:0 animated:YES];
[self.thisPicker selectRow:0 inComponent:1 animated:YES];
[self.delegate fuelQuantityChangedL:[self.fuelQuantityL integerValue]
R:[self.fuelQuantityR integerValue]];
}
#pragma mark - PickerViewDataSource delegate methods
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
return 2;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return (FUEL_MAX-FUEL_MIN + 1);
}
#pragma mark - PickerView delegate methods
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component{
float myWidth = self.view.frame.size.width;
if (component == 0) return myWidth / 3;
return (myWidth * 2 / 3);
}
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component {
//TODO
return 28;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [NSString stringWithFormat:#"%d", (FUEL_MAX)-row];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
if (component == LEFT_COMPONENT){
self.fuelQuantityL = [NSString stringWithFormat:#"%i", FUEL_MAX - row];
} else {
self.fuelQuantityR = [NSString stringWithFormat:#"%i", FUEL_MAX - row];
}
[self.delegate fuelQuantityChangedL:[self.fuelQuantityL integerValue]
R:[self.fuelQuantityR integerValue]];
}
#end
Here is my code. I m using this code for display the UIPopoverController when I click the cell and pick the value from UIPickerView to display the value in UILabel in my UITableviewCell
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0)
{
if (indexPath.row == 1)
{
//PopoverView controller.........................................................................
UIViewController *popoverViewController = [[UIViewController alloc] init];
//PopoverView....................................................................................
UIView *popoverView = [[UIView alloc]init];
[popoverView setBackgroundColor:[UIColor blackColor]];
//Navigation bar and Barbutton items..............................................................
UINavigationBar *navBar = [[UINavigationBar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];
navBar.barStyle = UIBarStyleBlackTranslucent;
UIBarButtonItem *btnDone = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(doDone)];
UIBarButtonItem *btnCancel = [[UIBarButtonItem alloc]initWithTitle:#"Cancel" style:UIBarButtonItemStylePlain target:self action:#selector(doCancel)];
UINavigationItem *navItem = [[UINavigationItem alloc]init];
navItem.rightBarButtonItem = btnDone;
navItem.leftBarButtonItem = btnCancel;
navBar.items = [[NSArray alloc]initWithObjects:navItem, nil];
[popoverView addSubview:navBar];
//UIPickerView.....................................................................................
UIPickerView *sortPickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 50, 320, 180)];
popoverViewController.contentSizeForViewInPopover = CGSizeMake(320, 230);
sortPickerView.delegate = self;
sortPickerView.dataSource = self;
sortPickerView.showsSelectionIndicator = YES;
[popoverView addSubview:sortPickerView];
NSUserDefaults *ud1 = [NSUserDefaults standardUserDefaults];
if ([ud1 objectForKey:#"languages"])
{
NSUInteger row1 = [languages indexOfObject:[ud1 objectForKey:#"languages"]];
if (row1)
{
[sortPickerView selectRow:row1 inComponent:0 animated:YES];
}
}
else
{
[sortPickerView selectRow:0 inComponent:0 animated:YES];
}
CGRect popFrame = lbl_language.frame;
popFrame.origin.y = popFrame.origin.y + popFrame.size.height + 70;
popFrame.origin.x = popFrame.origin.x + 100;
popoverViewController.view = popoverView;
self.SortPopover = [[UIPopoverController alloc] initWithContentViewController:popoverViewController];
[self.SortPopover presentPopoverFromRect:popFrame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
}
For reasons that are unclear to me, the UI Button was not receiving the push - it never highlighted. It was not overlaid by another view that I could see (the only other view was the picker). Anyway, I added a UIToolbar and changed the button to a bar button item and it works fine.
In a ViewController call by push, I try to programmatically display a ComboBox. This combobox implement UIPickerView delegate protocol and add a .xib file.
When i run the app, i can see my combobox on the screen, but when i click on it, nothing append. Normally the pickerview will be displayed.
What i don't understand, is in another viewcontroller call modal it works fine
//
// ComboBox.h
//
#import <UIKit/UIKit.h>
#interface ComboBox : UIViewController<UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate>
{
UIPickerView* pickerView;
IBOutlet UITextField* textField;
NSMutableArray *dataArray;
}
-(void) setComboData:(NSMutableArray*) data; //set the picker view items
-(void) setPlaceholder:(NSString*) label;
#property (retain, nonatomic) NSString* selectedText; //the UITextField text
#property (retain, nonatomic) IBOutlet UITextField* textField; //the UITextField
#end
//
// ComboBox.m
//
#import "ComboBox.h"
#implementation ComboBox
#synthesize selectedText;
#synthesize textField;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
return [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
//-- UIPickerViewDelegate, UIPickerViewDataSource
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView;
{
return 1;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
textField.text = [dataArray objectAtIndex:row];
selectedText = textField.text;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;
{
return [dataArray count];
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;
{
return [dataArray objectAtIndex:row];
}
//-- ComboBox
-(void) setComboData:(NSMutableArray*) data
{
dataArray = data;
}
-(void) setPlaceholder:(NSString *)label
{
textField.placeholder = label;
}
-(void)doneClicked:(id) sender
{
[textField resignFirstResponder]; //hides the pickerView
}
- (IBAction)showPicker:(id)sender {
pickerView = [[UIPickerView alloc] init];
pickerView.showsSelectionIndicator = YES;
pickerView.dataSource = self;
pickerView.delegate = self;
UIToolbar* toolbar = [[UIToolbar alloc] init];
toolbar.barStyle = UIBarStyleBlackTranslucent;
[toolbar sizeToFit];
//to make the done button aligned to the right
UIBarButtonItem *flexibleSpaceLeft = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem* doneButton = [[UIBarButtonItem alloc] initWithTitle:#"Done"
style:UIBarButtonItemStyleDone target:self
action:#selector(doneClicked:)];
[toolbar setItems:[NSArray arrayWithObjects:flexibleSpaceLeft, doneButton, nil]];
//custom input view
textField.inputView = pickerView;
textField.inputAccessoryView = toolbar;
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)aTextField
{
[self showPicker:aTextField];
return YES;
}
#end
the viewdidload of my viewcontroller
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray* ServeurArray = [[NSMutableArray alloc] init];
[ServeurArray addObject:#"1"];
[ServeurArray addObject:#"2"];
[ServeurArray addObject:#"3"];
comboServeur = [[ComboBox alloc] init];
[comboServeur setComboData:ServeurArray]; //Assign the array to ComboBox
comboServeur.view.frame = CGRectMake(95, 220, 130, 31); //ComboBox location and size (x,y,width,height)
[self.view addSubview:comboServeur.view];
}
thx for your answers
I assume that you are targeting iOS 5.0 and above. Since you are adding a view of a viewController to another viewController you can use the childViewController introduced in iOS 5.0.
Modify your viewDidLoad method
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
ComboBox *comboServeur = [[ComboBox alloc]initWithNibName:#"ComboBoxController" bundle:nil];
[comboServeur setComboData:#[#"1",#"2",#"3"]];
comboServeur.view.frame = CGRectMake(50.0f, 200.0f, 220.0f, 31.0f);
[self.view addSubview:comboServeur.view];
[self addChildViewController:comboServeur];
[comboServeur didMoveToParentViewController:self];
}
Few steps to check
Make the view of the ComboBox viewController freeform with maskType UIViewAutoresizingNone.
Check the textField and delegate of textField is connected
Demo project
I forget the specifics but I remember having the same problem but the thing for me was that I needed to link it to delegate or datasource or something? I'm not 100% sure since it's been quite a while but make sure when you have it on your view you link it to your picker reference + the other thing that you need.
Your ComboBox class isn't set as a delegate for the UITextField, so textFieldShouldBeginEditing: will never be called.
i try to use this combo class in my viewcontroller, i try all the solution you give to me, but nothing work, so the solution is to implement all the combo class code directly in my viewcontroller, and now it works, but it's a little bit uggly...
I am using Apple's MuiltipleDetailViewController sample app and get the message "UIViewController may not respond to showRootPopoverButtonItem"
This worked in XCode 3.X, but I get the message with 4.2
The app itself functions 100%, the popover is recognized in every nib, as is the table on the left when in landscape mode. But I can't submit with this warning. What do I need to change??
RootViewController.h
#import <UIKit/UIKit.h>
/*
SubstitutableDetailViewController defines the protocol that detail view controllers must adopt. The protocol specifies methods to hide and show the bar button item controlling the popover.
*/
#protocol SubstitutableDetailViewController <NSObject>
- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
- (void)invalidateRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
#end
#interface RootViewController : UITableViewController <UISplitViewControllerDelegate> {
UISplitViewController *splitViewController;
UIPopoverController *popoverController;
UIBarButtonItem *rootPopoverButtonItem;
//UINavigationBar *navigationBar;
}
#property (nonatomic, assign) IBOutlet UISplitViewController *splitViewController;
#property (nonatomic, retain) UIPopoverController *popoverController;
#property (nonatomic, retain) UIBarButtonItem *rootPopoverButtonItem;
//#property (nonatomic, retain) IBOutlet UINavigationBar *navigationBar;
#end
RootViewController.m:
#import "RootViewController.h"
#import "WebViewController.h"
#import "Twitter.h"
//#import "SubstitutableDetailViewController.h"
#implementation RootViewController
#synthesize splitViewController, popoverController, rootPopoverButtonItem;//, navigationBar;
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
// Set the content size for the popover: there are just two rows in the table view, so set to rowHeight*2.
self.contentSizeForViewInPopover = CGSizeMake(310.0, self.tableView.rowHeight*2.0);
//self.navigationController.navigationBar.tintColor = [UIColor colorWithRed:255/255 green:104/255 blue:1/255 alpha:1];
}
/*
-(void)customizeAppearance {
//create resizable images
UIImage *bluImage = [UIImage imageNamed:#"blu.jpg"];// resizableImageWithCapInsets:(0, 0, 0, 0)];
//set the bg for *all* UINavBars
[[UINavigationBar appearance] setBackgroundImage:bluImage forBarMetrics:UIBarMetricsDefault];
}
*/
-(void) viewDidUnload {
[super viewDidUnload];
self.splitViewController = nil;
self.rootPopoverButtonItem = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
- (void)splitViewController:(UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem
forPopoverController:(UIPopoverController*)pc {
// Keep references to the popover controller and the popover button, and tell the detail view controller to show the button.
barButtonItem.title = #"Index";
self.popoverController = pc;
self.rootPopoverButtonItem = barButtonItem;
UIViewController <SubstitutableDetailViewController> *detailViewController = [splitViewController.viewControllers objectAtIndex:1];
[detailViewController showRootPopoverButtonItem:rootPopoverButtonItem];
}
- (void)splitViewController:(UISplitViewController*)svc willShowViewController:(UIViewController *)aViewController
invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
// Nil out references to the popover controller and the popover button, and tell the detail view controller to hide the button.
UIViewController <SubstitutableDetailViewController> *detailViewController = [splitViewController.viewControllers objectAtIndex:1];
[detailViewController invalidateRootPopoverButtonItem:rootPopoverButtonItem];
self.popoverController = nil;
self.rootPopoverButtonItem = nil;
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section {
// Two sections, one for each detail view controller.
return 2;
}
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"RootViewControllerCellIdentifier";
// Dequeue or create a cell of the appropriate type.
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
//cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Set appropriate labels for the cells.
if (indexPath.row == 0) {
cell.textLabel.text = #"Twitter";
}
else if (indexPath.row == 1) {
cell.textLabel.text = #"Contact Us";
}
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor blackColor];
cell.contentView.backgroundColor = [UIColor blackColor];
cell.detailTextLabel.backgroundColor = [UIColor blackColor];
return cell;
}
#pragma mark -
#pragma mark Table view selection
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
/*
Create and configure a new detail view controller appropriate for the selection.
*/
NSUInteger row = indexPath.row;
UIViewController *detailViewController = nil;
if (row == 0) {
Twitter *newDetailViewController = [[Twitter alloc]
initWithNibName:#"Twitter"
bundle:nil];
detailViewController = newDetailViewController;
}
if (row == 1) {
WebViewController *newDetailViewController = [[WebViewController alloc]
initWithNibName:#"WebViewController"
bundle:nil];
newDetailViewController.detailURL=
[[NSURL alloc] initWithString:#"http://www.chipmunkmobile.com/contact.html"];
detailViewController = newDetailViewController;
}
// Update the split view controller's view controllers array.
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
splitViewController.viewControllers = viewControllers;
[viewControllers release];
// Dismiss the popover if it's present.
if (popoverController != nil) {
[popoverController dismissPopoverAnimated:YES];
}
// Configure the new view controller's popover button (after the view has been displayed and its toolbar/navigation bar has been created).
if (rootPopoverButtonItem != nil) {
[detailViewController showRootPopoverButtonItem:self.rootPopoverButtonItem];
}
[detailViewController release];
}
#pragma mark -
#pragma mark Managing the popover
/*
- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem {
// Add the popover button to the left navigation item.
[navigationBar.topItem setLeftBarButtonItem:barButtonItem animated:NO];
}
- (void)invalidateRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem {
// Remove the popover button.
[navigationBar.topItem setLeftBarButtonItem:nil animated:NO];
}
*/
#pragma mark -
#pragma mark Memory management
- (void)dealloc {
[popoverController release];
[rootPopoverButtonItem release];
[super dealloc];
}
#end
Here is an image of the exact line where I get the warning
The reason you getting this warning is because of this UIViewController *detailViewController UIViewController does not have a method called "showRootPopoverButtonItem". If you want to get rid of the warning just do this instead:
[(WebViewController*)detailViewController showRootPopoverButtonItem:self.rootPopoverButtonItem];
or
[(Twitter*)detailViewController showRootPopoverButtonItem:self.rootPopoverButtonItem];
You just need to let it know its not really just a viewController, its a subclassed viewController you created. So what ever class showRootPopoverButtonItem: is in you just need to type cast it.
If you want to leave your code exactly the same but get rid of the warning you can do this.
if (rootPopoverButtonItem != nil) {
[detailViewController performSelector:#selector(showRootPopoverButtonItem:) withObject:self.rootPopoverButtonItem];
}
If you want to be more careful you should use this.
if (rootPopoverButtonItem != nil && [detailViewController respondsToSelector:#selector(showRootPopoverButtonItem:)]) {
[detailViewController performSelector:#selector(showRootPopoverButtonItem:) withObject:self.rootPopoverButtonItem];
}
Update
After reading through your code you could just specify the delegate on the detailViewController like you did in the other functions.
UIViewController<SubstitutableDetailViewController> *detailViewController = nil;
if (row == 0) {
//...
(1)Specify the Type for the detailedViewController: [(TYPE *)OBJECTNAME...
(2) Then Specify method call [(TYPE *)OBJECTNAME METHODCALL];
(*) You get the warning because the compiler does not know what type of object you are using. If you subclass a UIViewController then you have to specify type when accessing methods.Make sure the method is in .h so that you can access it.
I am trying to build a small app. It's a tabbed app with 3 tabs: photos, videos, documents
Each tab displays a tableview to select wich gallery, video, document is to be shown; Videos work fine.
I'm having trouble with photo galleries. I use Fgallery which is working fine from the sample: Fgallery git
.h
#import <UIKit/UIKit.h>
#import "FGalleryViewController.h"
#interface FirstViewController : UIViewController <FGalleryViewControllerDelegate, UITableViewDelegate, UITableViewDataSource> {
NSArray *localCaptions;
NSArray *localImages;
NSArray *networkCaptions;
NSArray *networkImages;
FGalleryViewController *localGallery;
FGalleryViewController *networkGallery;
}
#property (nonatomic, strong) UITableView *myTableView;
#end
.m
#import "FirstViewController.h"
#implementation FirstViewController
#synthesize myTableView;
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect tableViewRect = self.view.bounds;
UITableView *tableView = [[UITableView alloc]
initWithFrame:tableViewRect
style:UITableViewStylePlain];
self.myTableView = tableView;
self.myTableView.autoresizingMask =
UIViewAutoresizingFlexibleHeight |
UIViewAutoresizingFlexibleWidth;
[self.view addSubview:self.myTableView];
self.myTableView.dataSource = self;
self.myTableView.delegate = self;
}
and
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog( #"Choix Table");
if( indexPath.row == 0 ) {
NSLog( #"selection 1");
localGallery = [[FGalleryViewController alloc] initWithPhotoSource:self];
[self.navigationController pushViewController:localGallery animated:YES];
}
else if( indexPath.row == 1 ) {
networkGallery = [[FGalleryViewController alloc] initWithPhotoSource:self];
[self.navigationController pushViewController:networkGallery animated:YES];
...
}
I really don't know how to display the gallery. The didSelectRowAtIndexPath is the one from fgallery, I tried to modify it to show the viewm but I'm new to Objective-C and I'm stuck.
Any help or guideline will be appreciated.
Thanks
I added
if( indexPath.row == 0 ) {
NSLog( #"selection 1");
localGallery = [[FGalleryViewController alloc] initWithPhotoSource:self];
// Create the navigation controller and present it modally.
UINavigationController *navigationController = [[UINavigationController alloc]
initWithRootViewController:localGallery];
[self presentModalViewController:navigationController animated:YES];
View shows ok now but I am missing the back button
In FGalleryViewController.m, I added btn2 to the navigation controller
- (void)setUseThumbnailView:(BOOL)useThumbnailView
{
_useThumbnailView = useThumbnailView;
if( self.navigationController ) {
if (_useThumbnailView) {
UIBarButtonItem *btn = [[UIBarButtonItem alloc] initWithTitle:#"See All" style:UIBarButtonItemStylePlain target:self action:#selector(handleSeeAllTouch:)] ;
[self.navigationItem setRightBarButtonItem:btn animated:YES];
UIBarButtonItem *btn2 = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:self action:#selector(dismissModalViewControllerAnimated:)] ;
[self.navigationItem setLeftBarButtonItem:btn2 animated:YES];
}
else {
[self.navigationItem setRightBarButtonItem:nil animated:NO];
}
}
}
And voilà