Best Pattern for multiple Popovers in Storyboard - ios7

I am writing an iPad application which will have several buttons that when clicked open a popover to a tableview. The user will choose a value, and the popover will be dismissed and the button't title will change.
I got this working with one Popover, and then wanted to add another. I want to write some good, clean reusable code.
My big hangup is with delegates. How many should there be? Should each popover have its own.
Root View Controller Header
#import <UIKit/UIKit.h>
#import "PopViewController1.h"
#import "PopViewController2.h"
#interface RootViewController : UIViewController <PopViewControllerDelegate,UIPopoverControllerDelegate>
// Properties for accessing the popover and its viewcontroller (1)
#property (strong, nonatomic) IBOutlet UIButton *btnOpenPopover1;
#property (strong, nonatomic) UIStoryboardPopoverSegue *pvcSegue1;
#property (strong, nonatomic) PopViewController1 *pvc1;
// Properties for accessing the popover and its viewcontroller (2)
#property (strong, nonatomic) IBOutlet UIButton *btnOpenPopover2;
#property (strong, nonatomic) UIStoryboardPopoverSegue *pvcSegue2;
#property (strong, nonatomic) PopViewController2 *pvc2;
#end
Root View Controller Method
#import "RootViewController.h"
#interface RootViewController ()
#end
#implementation RootViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[self setBtnOpenPopover1:nil];
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"segPop1"]) {
_pvcSegue1 = (UIStoryboardPopoverSegue *)segue;
_pvc1 = [segue destinationViewController];
[_pvc1 setDelegate:self];
} else ([[segue identifier] isEqualToString:#"segPop2"]); {
_pvcSegue2 = (UIStoryboardPopoverSegue *)segue;
_pvc2 = [segue destinationViewController];
//[_pvc2 setDelegate:self];
}
}
// PopViewControllerDelegate callback function
- (void)dismissPop:(NSString *)value {
[_btnOpenPopover1 setTitle:value forState:UIControlStateNormal];
[[_pvcSegue1 popoverController] dismissPopoverAnimated: YES]; // dismiss the popover
}
#end
PopViewController1.h
#import <UIKit/UIKit.h>
#protocol PopViewControllerDelegate;
#interface PopViewController1 : UITableViewController
#property (weak) id <PopViewControllerDelegate> delegate;
#property (strong, nonatomic) NSString *strPassedValue;
#property (nonatomic, strong) NSMutableArray *importantChoices;
#end
#protocol PopViewControllerDelegate <NSObject>
#required
- (void)dismissPop:(NSString *)value;
#end
PopViewController1 Method
#import "PopViewController1.h"
#interface PopViewController1 ()
#end
#implementation PopViewController1
- (id)initWithCoder:(NSCoder *)aDecoder
{
//Popover Choices
_importantChoices = [NSMutableArray array];
[_importantChoices addObject:#"Extremely Important"];
[_importantChoices addObject:#"Very Important"];
[_importantChoices addObject:#"Somewhat Important"];
[_importantChoices addObject:#"Not Very Important"];
[_importantChoices addObject:#"Not At All Important"];
self.clearsSelectionOnViewWillAppear = NO;
NSInteger rowsCount = [_importantChoices count];
NSInteger singleRowHeight = [self.tableView.delegate tableView:self.tableView
heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
NSInteger totalRowsHeight = rowsCount * singleRowHeight;
//Calculate how wide the view should be by finding how
//wide each string is expected to be
CGFloat largestLabelWidth = 0;
for (NSString *colorName in _importantChoices) {
//Checks size of text using the default font for UITableViewCell's textLabel.
CGSize labelSize = [colorName sizeWithFont:[UIFont boldSystemFontOfSize:20.0f]];
if (labelSize.width > largestLabelWidth) {
largestLabelWidth = labelSize.width;
}
}
//Add a little padding to the width
CGFloat popoverWidth = largestLabelWidth + 100;
//Set the property to tell the popover container how big this view will be.
self.contentSizeForViewInPopover = CGSizeMake(popoverWidth, totalRowsHeight);
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Uncomment the following line to preserve selection between presentations.
//self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (void)viewWillAppear: (BOOL)animated
{
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [_importantChoices count];}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [_importantChoices objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
_strPassedValue = [_importantChoices objectAtIndex:indexPath.row];
[_delegate dismissPop:_strPassedValue];
}
#end
PopViewController2 Header
#import <UIKit/UIKit.h>
#protocol PopViewControllerDelegate;
#interface PopViewController2 : UITableViewController
#property (weak) id <PopViewControllerDelegate> delegate;
#property (strong, nonatomic) NSString *strPassedValue2;
#property (nonatomic, strong) NSMutableArray *importantChoices2;
#end
#protocol PopViewControllerDelegate <NSObject>
#required
- (void)dismissPop2:(NSString *)value;
#end
PopViewController2 Method
import "PopViewController2.h"
#interface PopViewController2 ()
#end
#implementation PopViewController2
- (id)initWithCoder:(NSCoder *)aDecoder
{
//Popover Choices
_importantChoices = [NSMutableArray array];
[_importantChoices addObject:#"Extremely Important"];
[_importantChoices addObject:#"Very Important"];
[_importantChoices addObject:#"Somewhat Important"];
[_importantChoices addObject:#"Not Very Important"];
[_importantChoices addObject:#"Not At All Important"];
self.clearsSelectionOnViewWillAppear = NO;
NSInteger rowsCount = [_importantChoices count];
NSInteger singleRowHeight = [self.tableView.delegate tableView:self.tableView
heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
NSInteger totalRowsHeight = rowsCount * singleRowHeight;
//Calculate how wide the view should be by finding how
//wide each string is expected to be
CGFloat largestLabelWidth = 0;
for (NSString *colorName in _importantChoices) {
//Checks size of text using the default font for UITableViewCell's textLabel.
CGSize labelSize = [colorName sizeWithFont:[UIFont boldSystemFontOfSize:20.0f]];
if (labelSize.width > largestLabelWidth) {
largestLabelWidth = labelSize.width;
}
}
//Add a little padding to the width
CGFloat popoverWidth = largestLabelWidth + 100;
//Set the property to tell the popover container how big this view will be.
self.contentSizeForViewInPopover = CGSizeMake(popoverWidth, totalRowsHeight);
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Uncomment the following line to preserve selection between presentations.
//self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (void)viewWillAppear: (BOOL)animated
{
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [_importantChoices count];}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [_importantChoices objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
_strPassedValue = [_importantChoices objectAtIndex:indexPath.row];
[_delegate dismissPop:_strPassedValue];
}
#end
Any help or suggestions would be greatly appreciated!!!
Bryan

For reusable code, you only want one version of PopViewController. Your two versions look identical, so get rid of one. In InterfaceBuilder, set your buttons to all segue to a single PopViewController. Root View Controller, then, looks like this:
#property (strong, nonatomic) IBOutlet UIButton *btnOpenPopover1;
#property (strong, nonatomic) IBOutlet UIButton *btnOpenPopover2;
In prepareForSegue:, rather than segue to one version or another of PopViewController, just segue to your single version. Add a property to Root View Controller, to keep track of it (this replaces pvc1 and pvc2):
#property (strong, nonatomic) PopViewController* currentPopoverController;
You also need to keep track of which button is being edited, so add a property to your Root View Controller for that (note the weak reference):
#property (weak, nonatomic) IBOutlet UIButton* currentButton;
Set both of these in prepareForSegue:, so it looks like this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
currentPopoverController = [segue destinationViewController];
[currentPopoverController setDelegate:self];
currentButton = (UIButton*) sender;
}
Now, you only need one delegate that looks like this:
- (void)dismissPop:(NSString *)value {
[currentButton setTitle:value forState:UIControlStateNormal];
[currentPopoverController dismissPopoverAnimated:YES];
}

I figured this out.
I needed to put in my segue in the h file, set that to the segue title, and then I added the segue property to the prepareForSegue method:
_segPopViewController = (UIStoryboardPopoverSegue *)segue;
Finally in the delegate I was able to put in this line:
[[_segPopViewController popoverController] dismissPopoverAnimated: YES];
And success!
Kudos to the original poster - you helped me a ton! I wish I could up vote you more than one!!!
Bryan

Related

Detail View from TableView, Parsing

Can someone please help me, I looked everywhere to figure this out and nothing worked so far. I need to pass some data from table view to detail view and stick it into labels and Uiimage.
Data tableview is pulling comes from Parse database I created and seems to get pulled fine into the Tableview but I would like to use the same array that tableview is using for its data to fill out the detail view.
I am using 2 columns from parse to fill out this tableview Title and sub, and another tow columns to fill out the label and image. Here is my code so far. There is a bunch of variables that i was using in this code in DetailView
.h
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#interface BooksTableViewController : UITableViewController <UITableViewDelegate,NSObject >
{
NSArray * Booksarray;
}
#property (strong, nonatomic) IBOutlet UITableView *bookstableview;
#end
.m
#import "BooksTableViewController.h"
#import "BookDetailViewController.h"
#interface BooksTableViewController ()
#end
#implementation BooksTableViewController
#synthesize bookstableview;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self performSelector:#selector(RetrieveDatafromParse)];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
-(void) RetrieveDatafromParse {
PFQuery * getbooks = [PFQuery queryWithClassName:#"BooksTableView"];
[getbooks findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if(!error) {
Booksarray =[[NSArray alloc] initWithArray: objects];
}
[bookstableview reloadData];
NSLog(#"%#",objects);
}];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return Booksarray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * CellIdentifier = #"Cell";
UITableViewCell * cell = [bookstableview dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell ==nil) {
cell = [[ UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Cell"];
}
PFObject * tempObject = [Booksarray objectAtIndex:indexPath.row];
cell.textLabel.text = [tempObject objectForKey:#"Books"];
cell.detailTextLabel.text= [tempObject objectForKey:#"Code"];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
BookDetailViewController * detailVC=[[BookDetailViewController alloc] initWithNibName:#"BookDetailViewController" bundle:nil];
detailVC.BookImage.image=[Booksarray objectAtIndex:indexPath.row];
detailVC.bookDesc.text=[Booksarray objectAtIndex:indexPath.row];
detailVC.bookTitle.text=[Booksarray objectAtIndex:indexPath.row];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.destinationViewController isKindOfClass: [BookDetailViewController class]]) {
BookDetailViewController *destination = segue.destinationViewController;
SEL selector = NSSelectorFromString(#"SetFile:");
if ([destination respondsToSelector:selector]) {
NSIndexPath *indexPath = [self.bookstableview indexPathForCell:sender];
PFObject * object = [Booksarray objectAtIndex:indexPath.row];
PFFile *file = [object objectForKey:#"BooksTableView"];
[destination setValue:file forKey:#"file"];
}
}
}
#end
.h
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#interface BookDetailViewController : UIViewController <NSObject> {
}
#property (weak, nonatomic) IBOutlet UIImageView *BookImage;
#property (weak, nonatomic) IBOutlet UILabel *bookTitle;
#property (weak, nonatomic) IBOutlet UILabel *bookDesc;
#property (weak,nonatomic)PFFile *file;
#end
.m
#import "BookDetailViewController.h"
#import "BooksTableViewController.h"
#interface BookDetailViewController ()
#implementation BookDetailViewController
#synthesize BookImage,bookTitle,bookDesc,file,bookInfo,Picture,object2;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self performSelector:#selector(RetrieveObjectsFromParse)];
self.bookTitle.text = [self.file objectForKey:#"Books"];
self.BookImage.image = [self.file objectForKey:#"BookImage"];
self.bookDesc.text =[self.file objectForKey:#"BookDetails"];
}
-(void)RetrieveObjectsFromParse {
PFQuery * GetObjects = [PFQuery queryWithClassName:#"BooksTableView"];
[GetObjects findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if(!error) {
details =[[NSArray alloc] initWithArray: objects];
};
NSLog(#"%#",objects);
}];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
Try this:
#1 create a segue from controller to controller:
#2 Give your segue an Id for example detailSegue.
#3 Perform the segue in didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"detailSegue" sender:sender];
}
#4 Implement the segue delegate:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if([segue.identifier isEqualToString:#"detailSegue"]){
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
BookDetailViewController *detailVC = (BookDetailViewController *)segue.destinationViewController;
detailVC.bookDesc.text=[Booksarray objectAtIndex:indexPath.row];
//I uncommented that because it looks like a typo, same value 3 times?
//detailVC.BookImage.image=[Booksarray objectAtIndex:indexPath.row];
//detailVC.bookTitle.text=[Booksarray objectAtIndex:indexPath.row];
}
}
If this is the log you get:
2014-03-21 15:06:20.151 BookStore[25539:90b]
BookIndex= { BookDetails = "Test
test"; BookImage = ""; Books = Languages; Code =
104; }
Then you need to do it like this instead:
detailVC.bookTitle.text=[[Booksarray objectAtIndex:indexPath.row]objectForKey:#"Books"];
detailVC.bookDesc.text= [[Booksarray objectAtIndex:indexPath.row]objectForKey:#"BookDetails"];
detailVC.BookImage.image=[[Booksarray objectAtIndex:indexPath.row]objectForKey:#"BookImage"];
Or to make it shorter:
NSArray *bookAtIndex = [Booksarray objectAtIndex:indexPath.row];
detailVC.bookTitle.text=[bookAtIndex objectForKey:#"Books"];
detailVC.bookDesc.text= [bookAtIndex objectForKey:#"BookDetails"];
detailVC.BookImage.image=[bookAtIndex objectForKey:#"BookImage"];
or even shorter
NSArray *bookAtIndex = Booksarray[indexPath.row];
detailVC.bookTitle.text= bookAtIndex[#"Books"];
detailVC.bookDesc.text= bookAtIndex[#"BookDetails"];
detailVC.BookImage.image= bookAtIndex[#"BookImage"];

TableViewController to 2nd level ViewController

I have a very specific problem. I am very new to Xcode, but so far I was able to make an app with tab bar controller, where 1 of the tab controllers is tableviewcontroller. I have no problem displaying table cells in tableviewcontroller and even clicking anyone of them segueing to detailviewcontroller where table cells have extensive info, but my problem is when I am trying to segue my way even further, by clicking menu button, where I want a label and an image of a menu to show. I am getting a blank screen. I can't even see a title, not even talking about pushing through an image.
I assume problem is with pushing through the info through a level.
Here is TableViewController.h:
#import <UIKit/UIKit.h>
#interface TableViewController1 : UITableViewController
#property (nonatomic, strong) NSArray *Menus;
#property (nonatomic, strong) NSArray *Images;
#property (nonatomic, strong) NSArray *Title;
#property (nonatomic, strong) NSArray *Description;
#end
And TableViewController.m:
#import "TableViewController1.h"
#import "TableCell1.h"
#import "DetailViewController.h"
#import "MenuViewController.h"
#interface TableViewController1 ()
#end
#implementation TableViewController1
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
self.tableView.separatorColor = [UIColor colorWithRed:0/255.0 green:181/255.0 blue:0/255.0 alpha:0.5];
UIBarButtonItem *NewBackButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleBordered target:nil action:nil];
[[self navigationItem] setBackBarButtonItem:NewBackButton];
_Title = #[#"Velvet Sport Villa",
#"GQ",
#"29",
#"Noodles",
#"La Roof",
#"Borgo Antico",
#"Vertalet",
#"Balcon",
#"Parmigiano",];
_Description = #[#"The New Great Place",
#"Want to feel some luxury",
#"The Old Good Place",
#"Food is amazing here",
#"Too expensive",
#"Royal place",
#"Before party or After party",
#"Great place, great deserts",
#"The first place in town of that level",];
_Images = #[#"Velvet.jpg",
#"GQ.jpg",
#"29.jpg",
#"Noodles.jpg",
#"La Roof.jpg",
#"Borgo Antico.jpg",
#"Vertalet.jpg",
#"Balcon.jpg",
#"Parmigiano.jpg",];
_Menus = #[#"Velvet Menu.jpg",
#"GQ Menu.jpg",
#"29 Menu.jpg",
#"Noodles Menu.jpg",
#"La Roof Menu.jpg",
#"Borgo Antico Menu.jpg",
#"Vertalet Menu.jpg",
#"Balcon Menu.jpg",
#"Parmigiano Menu.jpg",];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return _Title.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TableCell1";
TableCell1 *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
int row = [indexPath row];
cell.TitleLabel.text = _Title[row];
cell.DescriptionLabel.text = _Description[row];
cell.ThumbImage.image = [UIImage imageNamed:_Images[row]];
return cell;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ShowDetails"])
{
DetailViewController *detailviewcontroller = [segue destinationViewController];
NSIndexPath *myInderPath = [self.tableView indexPathForSelectedRow];
int row = [myInderPath row];
detailviewcontroller.DetailModal = #[_Title[row],_Description[row],_Images[row],_Menus[row]];
}
if ([[segue identifier] isEqualToString:#"MenuDetails"])
{
MenuViewController *menuviewcontroller = [segue destinationViewController];
NSIndexPath *myInderPath = [self.tableView indexPathForSelectedRow];
int row = [myInderPath row];
menuviewcontroller.MenuModal = #[_Title[row],_Menus[row]];
}
}
#end
TableCell1.h
#import <UIKit/UIKit.h>
#interface TableCell1 : UITableViewCell
#property(strong,nonatomic) IBOutlet UILabel *TitleLabel;
#property(strong,nonatomic) IBOutlet UILabel *DescriptionLabel;
#property(strong,nonatomic) IBOutlet UIImageView *ThumbImage;
#end
TableCell1.m
#import "TableCell1.h"
#implementation TableCell1
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
DetailViewController.h
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *Cuisine;
#property (weak, nonatomic) IBOutlet UILabel *Price;
#property (weak, nonatomic) IBOutlet UILabel *Decor;
#property (weak, nonatomic) IBOutlet UILabel *Service;
#property(strong,nonatomic) IBOutlet UILabel *TitleLabel;
#property(strong,nonatomic) IBOutlet UILabel *DescriptionLabel;
#property(strong,nonatomic) IBOutlet UIImageView *ThumbImage;
#property(strong,nonatomic) NSArray *DetailModal;
#end
DetailViewController.m
#import "DetailViewController.h"
#interface DetailViewController ()
#end
#implementation DetailViewController
- (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.
_TitleLabel.text = _DetailModal[0];
_DescriptionLabel.text = _DetailModal[1];
_ThumbImage.image = [UIImage imageNamed:_DetailModal[2]];
self.navigationItem.title = _DetailModal[0];
if ([_TitleLabel.text isEqualToString:#"Velvet Sport Villa"])
{
_Cuisine.text = #"German/American";
_Price.text = #"Above average";
_Decor.text = #"Great. Sporty, but cozy";
_Service.text = #"Exceptional";
}
if ([_TitleLabel.text isEqualToString:#"GQ"])
{
_Cuisine.text = #"Italian/English";
_Price.text = #"Above average";
_Decor.text = #"Exceptional";
_Service.text = #"Average";
}
if ([_TitleLabel.text isEqualToString:#"29"])
{
_Cuisine.text = #"Japanese/Italian";
_Price.text = #"Average";
_Decor.text = #"Cozy";
_Service.text = #"So So";
}
if ([_TitleLabel.text isEqualToString:#"Noodles"])
{
_Cuisine.text = #"Chinese/Italian";
_Price.text = #"Average";
_Decor.text = #"Interesting";
_Service.text = #"Groomy, but fast";
}
if ([_TitleLabel.text isEqualToString:#"La Roof"])
{
_Cuisine.text = #"American/Italian";
_Price.text = #"Very High";
_Decor.text = #"OK";
_Service.text = #"OK";
}
if ([_TitleLabel.text isEqualToString:#"Borgo Antico"])
{
_Cuisine.text = #"Medeterranean";
_Price.text = #"Above average";
_Decor.text = #"Marvelous";
_Service.text = #"Not Bad";
}
if ([_TitleLabel.text isEqualToString:#"Vertalet"])
{
_Cuisine.text = #"All";
_Price.text = #"Above average";
_Decor.text = #"Fine, nothing special";
_Service.text = #"Not Bad";
}
if ([_TitleLabel.text isEqualToString:#"Balcon"])
{
_Cuisine.text = #"Italian/Coffee";
_Price.text = #"Above Average";
_Decor.text = #"Modern";
_Service.text = #"Best";
}
if ([_TitleLabel.text isEqualToString:#"Parmigiano"])
{
_Cuisine.text = #"Italian";
_Price.text = #"Above Average";
_Decor.text = #"Stunning";
_Service.text = #"Annoying";
}
}
#end
Finally MenuViewController.h
#import <UIKit/UIKit.h>
#interface MenuViewController : UIViewController
#property(strong,nonatomic) IBOutlet UILabel *TitleLabel;
#property (strong,nonatomic) IBOutlet UIImageView *MenuImage;
#property(strong,nonatomic) NSArray *MenuModal;
#end
And Lastly MenuViewController.m
#import "MenuViewController.h"
#interface MenuViewController ()
#end
#implementation MenuViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title = _MenuModal[0];
_TitleLabel.text = _MenuModal[0];
_MenuImage.image = [UIImage imageNamed:_MenuModal[3]];
}
#end

Master - detail tableviews - not sure about how/where to do the IF-statement

In my app I´m using a master tableView with 3 cells, taken from a JSON. Each of these 3 cells will be connected to another tableView but Im not sure how to do this IF-statement.
Heres the .m for the master tableView. So far I only connected 1 detailView(tableView) to the master:
#import "GuideTableViewController.h"
#import "GuideDetailTableViewController.h"
#import <QuartzCore/QuartzCore.h>
#interface GuideTableViewController (){
NSArray *guide;
}
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#property (weak, nonatomic) IBOutlet UIImageView *imgHeader;
#property (weak, nonatomic) IBOutlet UIButton *btnMap;
#property (weak, nonatomic) IBOutlet UIImageView *ImgTitle;
#end
#implementation GuideTableViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
//JSONmetod
- (void) loadJSON{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//code
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"https://dl.dropbox.com/u/100670549/test.json"]];
NSError *error;
if (data)
{
guide = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
for (NSDictionary *dictionary in guide){
NSLog([dictionary description]);
}
}else
{
NSLog(#"Could not load data");
}
dispatch_sync(dispatch_get_main_queue(), ^{
// code
[self.tableView reloadData];
});
});
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//Anropa json
[self loadJSON];
//set background
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"background.jpg"]];
//rounded corners
[self.tableView.layer setCornerRadius:9.0];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//TableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 3;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
NSDictionary *dict = [guide objectAtIndex:indexPath.row];
cell.textLabel.text = [dict valueForKey:#"title"];
return cell;
}
//To detailView. Started with an IF here.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"showStay"]){
GuideDetailTableViewController *tvc = [segue destinationViewController];
NSIndexPath *index = sender;
NSDictionary *dict = [guide objectAtIndex:index.row];
tvc.stay = dict;
}
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[self performSegueWithIdentifier:#"showStay" sender:indexPath];
}
- (void) viewWillAppear:(BOOL)animated{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:self.tableView.indexPathForSelectedRow];
//ta bort markeringen när man går tillbaka till master från detailView.
[cell setSelected:NO];
//Hide navbar
[self.navigationController setNavigationBarHidden:YES];
}
//Show navbar in detailView
-(void)viewWillDisappear:(BOOL)animated{
[self.navigationController setNavigationBarHidden:NO];
}
#end
Thanks in advance!
Your code is all right.
The if-statement is at the right place.
If you already linked your prototype cell to the detail view in the storyboard you don't need to implement tableView:DidSelectRowAtIndexPath:
prepareForSegue:sender: is called automaticaly.

tableView doesn't show anything

I'm sure my code is withour mistake, because I have two same tableViews and both with same code, same content and same design. But I don't understand why one of my tableViews is shown, and the other one isn't. I'm using Dynamic Prototype Content, Grouped Style and both tableViews are in container view in other ViewController. Here is code:
table.h
#import <UIKit/UIKit.h>
#interface table : UIViewController <UITableViewDataSource, UITableViewDelegate>
{
NSArray *tabledata;
NSIndexPath* checkedIndexPath;
}
#property (nonatomic, retain) NSArray *tabledata;
#property (nonatomic, assign) int number;
#property (nonatomic, retain) NSIndexPath* checkedIndexPath;
#property (strong, nonatomic) IBOutlet UITableView *tableView;
+(table*)instance;
#property (nonatomic) NSInteger selectedRow;
#end
table.m
#import "table.h"
#interface table ()
#end
#implementation table
#synthesize tabledata;
#synthesize tableView;
#synthesize checkedIndexPath;
#synthesize number;
+(InstrumentsI*)instance {
static table *statInst;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
statInst = [[table alloc] init];
});
return statInst;
}
#synthesize selectedRow;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
tabledata = [[NSArray alloc] initWithObjects:#"row1", #"row2", #"row3", nil];
self.selectedRow = 0;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - TableView Data Source methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [tabledata count];
}
- (UITableViewCell *)tableView:(UITableView *)tableview cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = nil;
cell = [tableview dequeueReusableCellWithIdentifier:#"identifer"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"identifer"];
}
cell.textLabel.text = [tabledata objectAtIndex:indexPath.row];
if (indexPath.row == self.selectedRow)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
#pragma mark TableView Delegate methods
- (void)tableView:(UITableView *)tableview didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[table instance].selectedRow = indexPath.row;
if (indexPath.row != self.selectedRow) {
self.selectedRow = indexPath.row;
}
[tableView reloadData];
}
- (void)viewDidUnload {
[self setTableView:nil];
[super viewDidUnload];
}
#end
Check if you have implemented all the delegates and datasource methods.
Also confirm that you have set your file's owner or controller as delegates and datasource.
Try to reload the tableview after loading the data, like:
- (void)viewDidLoad
{
[super viewDidLoad];
tabledata = [[NSArray alloc] initWithObjects:#"row1", #"row2", #"row3", nil];
self.selectedRow = 0;
[self.tableView reloadData];
}

IOS 5.1 ARC Unrecognized Selector Sent to Instance

I have been looking at similar question but couldn't figure it out what is the problem.It seems it should work but it gives me error.
In IOS 5.1 Ipad Stortyboard application I have a right navigation bar item when user click a popover view should open. I had a working popover view but design was not good so I replaced it with a new popover class now it gives me following error
-[UIButton view]: unrecognized selector sent to instance 0xa17ba80
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIButton view]: unrecognized selector sent to instance 0xa17ba80'
I have tried following functions but none has worked so far. It gives me similar errors when I change the code.
- (IBAction)setColorButtonTapped:(id)sender{
- (void)setColorButtonTapped:(id)sender{
- (IBAction)setColorButtonTapped:(id)sender forEvent:(UIEvent*)event {
- (void)setColorButtonTapped:(id)sender forEvent:(UIEvent*)event {
and ofcourse I have changed ti following regarding to ibaction or void
[backButton2 addTarget:self action:#selector(setColorButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
here is the code
my.h file
#import <UIKit/UIKit.h>
#import "ColorPickerController.h"
#interface MeetingViewController : UITableViewController<UIApplicationDelegate,UIAlertViewDelegate,DropDownListDelegate,MFMailComposeViewControllerDelegate,EGORefreshTableHeaderDelegate,ColorPickerDelegate>{
UIPopoverController *_popover;
ColorPickerController *_colorPicker;
UIPopoverController *_colorPickerPopover;
}
#property (nonatomic, strong) UIPopoverController *popover;
#property (nonatomic, strong) ColorPickerController *colorPicker;
#property (nonatomic, strong) UIPopoverController *colorPickerPopover;
- (IBAction)setColorButtonTapped:(id)sender;
#end
my.m file
#synthesize popover = _popover;
#synthesize colorPicker = _colorPicker;
#synthesize colorPickerPopover = _colorPickerPopover;
- (void)viewDidLoad
{
[super viewDidLoad];
//gear button on navigation Bar
UIImage* imageback2 = [UIImage imageNamed:#"ICON - Gear#2x.png"];
CGRect frameimgback2 = CGRectMake(0, 0, 40, 40);
UIButton *backButton2 = [[UIButton alloc] initWithFrame:frameimgback2];
[backButton2 setBackgroundImage:imageback2 forState:UIControlStateNormal];
[backButton2 addTarget:self
action:#selector(setColorButtonTapped:)
forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *btn2 = [[UIBarButtonItem alloc] initWithCustomView:backButton2];
self.navigationItem.rightBarButtonItem = btn2;
}
#pragma mark ColorPickerDelegate
- (void)colorSelected:(NSString *)color {
[self.colorPickerPopover dismissPopoverAnimated:YES];
}
#pragma mark Callbacks
- (IBAction)setColorButtonTapped:(id)sender {
if (_colorPicker == nil) {
self.colorPicker = [[ColorPickerController alloc] initWithStyle:UITableViewStylePlain];
_colorPicker.delegate = self;
self.colorPickerPopover = [[UIPopoverController alloc] initWithContentViewController:_colorPicker];
}
[self.colorPickerPopover presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
utility class
ColorPickerController.h
#import <UIKit/UIKit.h>
#protocol ColorPickerDelegate
- (void)colorSelected:(NSString *)color;
#end
#interface ColorPickerController : UITableViewController {
NSMutableArray *_colors;
id<ColorPickerDelegate> __weak _delegate;
}
#property (nonatomic, strong) NSMutableArray *colors;
#property (nonatomic, weak) id<ColorPickerDelegate> delegate;
#end
utilityclass
ColorPickerController.m
#import "ColorPickerController.h"
#implementation ColorPickerController
#synthesize colors = _colors;
#synthesize delegate = _delegate;
#pragma mark -
#pragma mark Initialization
/*
- (id)initWithStyle:(UITableViewStyle)style {
// Override initWithStyle: if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
if ((self = [super initWithStyle:style])) {
}
return self;
}
*/
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
self.clearsSelectionOnViewWillAppear = NO;
self.contentSizeForViewInPopover = CGSizeMake(150.0, 140.0);
self.colors = [NSMutableArray array];
[_colors addObject:#"Red"];
[_colors addObject:#"Green"];
[_colors addObject:#"Blue"];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Override to allow orientations other than the default portrait orientation.
return YES;
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return [_colors count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
NSString *color = [_colors objectAtIndex:indexPath.row];
cell.textLabel.text = color;
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (_delegate != nil) {
NSString *color = [_colors objectAtIndex:indexPath.row];
[_delegate colorSelected:color];
}
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
// For example: self.myOutlet = nil;
}
- (void)dealloc {
self.delegate = nil;
}
#end
Help is much appreciated , thanks
You're using a UIButton as a customView for a UIBarButtonItem. This could be the problem.
I suggest you use UIBarButtonItem's initWithImage:style:target:action: initializer instead.
UIButton is a view and as such has no view property or instance method.