to use [self presentModalViewController: animated:] and black screen - ios

I create one program that show list of book from url in tableview (any book has many images)
I want when to click any cell to go in next page (next page is UIScroll that show images) and show images of that book
I have one problem that it is when to click any cell and when go next page show black screen instead UIScrollView include many images.
this is my code :
RecipeViewController.h
#import "RecipeViewController.h"
#interface RecipeViewController : UITableViewController<UITableViewDataSource,UITableViewDelegate>
#property (nonatomic,strong) IBOutlet UITableView *table;
#end
RecipeViewController.m
#import "RecipeViewController.h"
#import "Recipe.h"
#import "DetailViewController.h"
#implementation RecipeViewController
{
NSMutableArray *recipes;
NSInteger num;
}
#synthesize table;
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title = #"Recipe Book";
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleBordered target:nil action:nil];
[[self navigationItem] setBackBarButtonItem:backButton];
NSString *numberbook = [[NSString alloc]initWithContentsOfURL:[NSURL URLWithString:#"http://192.168.1.100/mamal/book.php?all"]];
NSInteger numbook = [numberbook integerValue];
for (int i = 1; i <= numbook; i++)
{
Recipe *si = [Recipe new];
//NSLog(#"%d,%#",i,si);
NSString *c = [[NSString alloc]initWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://192.168.1.100/mamal/book.php?info=1&b=%d",i]]];
NSData *data = [[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://192.168.1.100/mamal/book.php?p=1&b=%d",i]]];
si.name = [NSString stringWithString:c];
si.imageFile = data;
if(!recipes){
recipes = [NSMutableArray array];
}
[recipes addObject:si];
}
num = numbook;
// Remove table cell separator
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
// Assign our own backgroud for the view
self.parentViewController.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"common_bg"]];
self.tableView.backgroundColor = [UIColor clearColor];
// Add padding to the top of the table view
UIEdgeInsets inset = UIEdgeInsetsMake(5, 0, 0, 0);
self.tableView.contentInset = inset;
}
#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 recipes.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];
}
// Display recipe in the table cell
Recipe *recipe = [recipes objectAtIndex:indexPath.row];
UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
recipeImageView.image = [UIImage imageWithData:recipe.imageFile];
UILabel *recipeNameLabel = (UILabel *)[cell viewWithTag:101];
recipeNameLabel.text = recipe.name;
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *obj = [[DetailViewController alloc]init];
int x = (indexPath.row)+1;
NSLog(#"x : %d",x);
obj.yourValue = [NSString stringWithFormat:#"%d",(indexPath.row)+1];
NSLog(#"yourValue1 : %#",obj.yourValue);
obj.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:obj animated:YES];
}
#end
DetailViewController.h
#import <UIKit/UIKit.h>
#import "Recipe.h"
#import "RecipeViewController.h"
#interface DetailViewController : UIViewController<UIScrollViewDelegate>
{
UIScrollView *scroller;
}
#property (nonatomic,strong) IBOutlet UIScrollView *scroller;
#property (nonatomic,strong) Recipe *rec;
#property (nonatomic,strong) NSString *yourValue;
#end
DetailViewController.m
#import "DetailViewController.h"
#implementation DetailViewController
#synthesize scroller,yourValue;
- (void)viewDidLoad
{
[super viewDidLoad];
int m1 = [self.yourValue integerValue];
NSLog(#"M1 : %d",m1);
NSString *bookID = [[NSString alloc]initWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://192.168.1.100/mamal/book.php?info=0&b=%d",m1]]];
NSInteger num1 = [bookID integerValue];
NSLog(#"%d",num1);
for (int i = 1; i <= num1; i++)
{
NSString *s = [NSString stringWithFormat:#"http://192.168.1.100/mamal/book.php?p=%d&b=%d",i,m1];
NSData *dat = [[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:s]];
NSLog(#"%#",s);
UIImageView *imagen = [[UIImageView alloc] initWithImage:[UIImage imageWithData:dat]];
imagen.frame = CGRectMake((i-1)*320, 0, 320, 460);
[scroller addSubview:imagen];
}
scroller.delegate = self;
scroller.contentSize = CGSizeMake(320*num1, 460);
scroller.pagingEnabled = YES;
}
#end

I have just solved this problem, if you are using StoryBoard you have to init the view controller this way:
UIStoryboard *storybrd = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
storybrd = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
YourViewController *newVC =[storybrd instantiateViewControllerWithIdentifier:#"YourVCId"];
You have to put your identifier in the storyboard, selecting the view you want to show and then selecting the identity inspector, there you have the option to write the id that you want.

You need to call:
[[DetailViewController alloc]initWithNibName:#"nibName" bundle:nil]; rather than just [[DetailViewController alloc]init]; as at this point, it doesn't have an Xib to inflate (unless you overrode the init method)

You not at all calling DetailViewController How it shows the image .Try this in didSelectRowAtIndexPath: may help you
DetailViewController *DVC = [[DetailViewController alloc] initWithNibName:nil bundle:nil];
[self.navigationController pushViewController:DVC animated:YES];

Related

How to get back textfield data from tableViewCell in objective c?

I have two tableViewControllers, second tableViewController tableViewCell has textField and imageView, how can I get data from that textfield when I click navigationBarBackButton (I want to store that data in first tableViewController).
// code from second tableViewController...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"cellID"];
cell.textLabel.text = #"SIM Name";
cell.detailTextLabel.text = #"AirTel";
cell.imageView.image = [UIImage imageNamed:#"Star2.png"];
return cell;
}
TableViewCell1 *cell1 = [tableView dequeueReusableCellWithIdentifier:#"cell1"];
cell1.nameTextField.delegate = self;
if (indexPath.row == 1) {
NSArray *cell1XibRef = [[NSBundle mainBundle]loadNibNamed:#"TableViewCell1" owner:self options:nil];
cell1 = [cell1XibRef objectAtIndex:0];
cell1.imageView.image = [UIImage imageNamed:#"Con.png"];
self.nameString = cell1.nameTextField.text;
return cell1;
}
return nil;
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
return YES;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField{
//Whenever people start editing your textfield
self.nameString = textField.text;
NSLog(#"%#", self.nameString);
}
So many ways to do that but I prefer this way
Save the textfield.text value in NSUserDefaults like this
[[NSUserDefaults standardUserDefaults] setObject:textField.text forKey:#"controllerTwo"];
And get that value in first controller
NSString *secondContrllerText = [[NSUserDefaults standardUserDefaults] stringForKey:#"controllerTwo"];
You can directly add cells in one array and loads cells from that array which will returns you latest cell with all your edits.
NSMutableArray *arrCells = [[NSMutableArray alloc] init];
for (init i=0; i<20; i++){
UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"cellID"];
arrCells = cell;
}
In cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = arrCell[indexPath.row];
......
return cell;
}
here is the code i like to pass the data with block.here is the code wish to help you.
FirstViewController.h
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController
#end
FirstViewController.m
#import "FirstViewController.h"
#import "ViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)buttonClick
{
ViewController *controller = [[ViewController alloc] init];
controller.passTheTextFieldData = ^(NSString *textValue){
NSLog(#"show the %# textValue",textValue);
};
[self.navigationController pushViewController:controller animated:YES];
}
#end
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (nonatomic, strong) void (^passTheTextFieldData)();
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()<UITextFieldDelegate>
#property (nonatomic, strong) UITextField *textField;
#property (nonatomic, strong) NSString *textValue;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
[self.textField addTarget:self action:#selector(textFieldValueChanged) forControlEvents:UIControlEventValueChanged];
}
- (void)textFieldValueChanged
{
self.textValue = self.textField.text;
}
- (void)navigationbarBackClick
{
if (self.passTheTextFieldData) {
self.passTheTextFieldData(self.textValue);
}
}
#end
Set the tag property for textField in tableViewCell
Then loop through the cells
for (int i = 0 ; i < [cellDataArray count] ; i++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
UITextField *txtfield = [[cell contentView]viewWithTag:2];
//now get the text txtfield.text
}
Hope this helps
Either you can use delegate method to store your value or use NSUserdefaults.But you have to store one value to pass it to another table view i recommend you to use NSUserdefaults.
//suppose you have to save text (get your data)
NSString *valueToSave = cell1.nameTextField.text;
[[NSUserDefaults standardUserDefaults] setObject:valueToSave forKey:#"keyAbcd"];
[[NSUserDefaults standardUserDefaults] synchronize];
//another page where you want to show your data (paste your data)
NSString *savedValue = [[NSUserDefaults standardUserDefaults]
stringForKey:#"keyAbcd"];//your key have to be same
//print save value in nslog

How to show different view controller based on RowSelected in Tableviewcell?

I am new to iPhone Development and trying to create a small application(Recipe list) with multiple views. When the user selects one of the rows in tablecell, I would like to call a new view. For Instance, the menu card with items mushroom, pasta,steak must call another view with detailed recipe.
I have used UITableViewController to display a list of items with Accessory. These items are dynamically populated from a NSArray. When the user taps on one of the rows in the table, it should take him to a view controller based on the Row Selection. I know I have to implement tableView:didSelectRowAtIndexPath: function to call the appropriate view.
But I am not able to proceed. I read about Segue in storyboards, but even that seems a bit confusing for me.
I would really appreciate if someone solves my query. Here is my code.
RecipeViewController.h
#import "RecipeViewController.h"
#import "Recipe.h"
#interface RecipeViewController ()
#end
#implementation RecipeViewController
{
NSArray *recipes; //Recipe Array
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title = #"Hotel";
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleBordered target:nil action:nil];
[[self navigationItem] setBackBarButtonItem:backButton];
// Create recipe array for main screen.
Recipe *recipe1 = [Recipe new];
recipe1.headline = #"Mushroom";
recipe1.description = #"description";
recipe1.imageFile = #"mushroom.jpg";
Recipe *recipe2 = [Recipe new];
recipe2.headline = #"pasta";
recipe2.description = #"Pasta description";
recipe2.imageFile = #"pasta.jpg";
Recipe *recipe3 = [Recipe new];
recipe3.headline = #"Steak";
recipe3.description = #"Steak description";
recipe3.imageFile = #"steak.jpg";
recipes = [NSArray arrayWithObjects:recipe1, recipe2, recipe3,nil];
// Remove table cell separator
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
// Assign custom backgroud for the view
self.parentViewController.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"welcome_screen"]];
self.tableView.backgroundColor = [UIColor clearColor];
// Add padding to the top of the table view
UIEdgeInsets inset = UIEdgeInsetsMake(5, 0, 0, 0);
self.tableView.contentInset = inset;
}
- (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 recipes.count;
}
- (UIImage *)cellBackgroundForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger rowCount = [self tableView:[self tableView] numberOfRowsInSection:0];
NSInteger rowIndex = indexPath.row;
UIImage *background = nil;
if (rowIndex == 0) {
background = [UIImage imageNamed:#"cell_top.png"];
} else if (rowIndex == rowCount - 1) {
background = [UIImage imageNamed:#"cell_bottom.png"];
} else {
background = [UIImage imageNamed:#"cell_middle.png"];
}
return background;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Display recipe in the table cell
Recipe *recipe = [recipes objectAtIndex:indexPath.row];
UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
recipeImageView.image = [UIImage imageNamed:recipe.imageFile];
UILabel *recipeNameLabel = (UILabel *)[cell viewWithTag:101];
recipeNameLabel.text = recipe.headline;
UILabel *recipeDetailLabel = (UILabel *)[cell viewWithTag:102];
recipeDetailLabel.text = recipe.description;
// Assign our own background image for the cell
UIImage *background = [self cellBackgroundForRowAtIndexPath:indexPath];
UIImageView *cellBackgroundView = [[UIImageView alloc] initWithImage:background];
cellBackgroundView.image = background;
cell.backgroundView = cellBackgroundView;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
CampusViewController *campusViewController;
WhoViewController *whoViewController;
switch (indexPath.row)
{
case 0:
campusViewController=[[CampusViewController alloc] init];
[[self navigationController] pushViewController:campusViewController animated:YES];
break;
case 1:
whoViewController=[[WhoViewController alloc] init]; // not released as ARC is included in the project
[[self navigationController] pushViewController:whoViewController animated:YES];
break;
case 2:
break;
case 3:
break;
default:
break;
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ShowDetails"]) {
RecipeViewController *detailViewController = [segue destinationViewController];
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
/* NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
detailViewController.data = [self.dataController objectInListAtIndex:indexPath.row];
*/
}
}
#end
// Recipe.h
#import <Foundation/Foundation.h>
#interface Recipe : NSObject
#property (nonatomic, strong) NSString *headline; // name of recipe
#property (nonatomic, strong) NSString *description; // recipe detail
#property (nonatomic, strong) NSString *imageFile; // image filename of recipe
#end
Have you read any tutorials on how to do this? This is a very basic question and there are a lot of posts about this out there.
I'll only give you an explanation on how to do it but you will have to code it yourself.
The standard way we go about an application that shows the user different view controllers based on the selection of a UITableViewCell is by using a UINavigatorController. This controller gives you the methods:
– pushViewController:animated:
– popViewControllerAnimated:
... among others. With these two methods you can go back and forth between view controllers, which is what you want to do. So you have to give your navigator controller the table view controller that you already have. You can do that by using UINavigatorController's method – initWithRootViewController:
A little example of what your – tableView:willSelectRowAtIndexPath: might look like is:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIViewController *myViewController = [[UIViewController alloc] initWithNibName:#"YourNibName" bundle:nil];
self.navigationController pushViewController:[myViewController autorelease] animated:YES];
}
Hope this helps!
Further reading:
UINavigationController tutorial Ray Wenderlich
UINavigationController tutorial Techotopia

UITableViewController cells disappear if inside a UIScrollView

This is my storyboard:
My scrollView is contains 3 NavigationController(containing BubbleListController which is a sort of Table view). These 3 views are put one aside the other and this is the code:
ioBubbleListController.h
#import <UIKit/UIKit.h>
#interface ioBubbleListController : UITableViewController {
NSDictionary *bubbles;
}
#end
ioBubbleListController.m
#import "ioBubbleListController.h"
#interface ioBubbleListController ()
#property (nonatomic, retain) NSDictionary *bubbles;
#end
#implementation ioBubbleListController
#synthesize bubbles;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (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.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.bubbles = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"bubbles" ofType:#"plist"]];
// 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;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [self.bubbles count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [[self.bubbles allKeys] objectAtIndex:section];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *continent = [self tableView:tableView titleForHeaderInSection:section];
return [[self.bubbles valueForKey:continent] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CountryCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
NSString *continent = [self tableView:tableView titleForHeaderInSection:indexPath.section];
NSString *country = [[self.bubbles valueForKey:continent] objectAtIndex:indexPath.row];
cell.textLabel.text = country;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *continent = [self tableView:tableView titleForHeaderInSection:indexPath.section];
NSString *country = [[self.bubbles valueForKey:continent] objectAtIndex:indexPath.row];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil
message:[NSString stringWithFormat:#"You selected %#!", country]
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#end
This is my ioUIPager which puts one BubbleList aside the other
#import "ioUIPager.h"
#implementation ioUIPager
#synthesize scrollView;
- (void)viewDidLoad {
[super viewDidLoad];
[self scrollView].contentSize = CGSizeMake(self.scrollView.frame.size.width * 3, self.scrollView.frame.size.height);
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
// View1
UITableViewController *view1 = [sb instantiateViewControllerWithIdentifier:#"BubblesList"];
CGRect frame1;
frame1.origin.x = self.scrollView.frame.size.width * 0;
frame1.origin.y = 0;
frame1.size = self.scrollView.frame.size;
[self.scrollView addSubview:view1.view];
view1.view.frame = frame1;
view1.view.backgroundColor = [UIColor greenColor];
// View2
UIViewController *view2 = [sb instantiateViewControllerWithIdentifier:#"BubblesList"];
CGRect frame2;
frame2.origin.x = self.scrollView.frame.size.width * 1;
frame2.origin.y = 0;
frame2.size = self.scrollView.frame.size;
[self.scrollView addSubview:view2.view];
view2.view.frame = frame2;
view2.view.backgroundColor = [UIColor redColor];
// View2
UIViewController *view3 = [sb instantiateViewControllerWithIdentifier:#"BubblesList"];
CGRect frame3;
frame3.origin.x = self.scrollView.frame.size.width * 2;
frame3.origin.y = 0;
frame3.size = self.scrollView.frame.size;
[self.scrollView addSubview:view3.view];
view3.view.frame = frame3;
}
- (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 {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.scrollView = nil;
}
//- (void)dealloc {
// [scrollView release];
// [super dealloc];
//}
#end
Everything is rendered fine at first look, however any gesture/touch/tap I do on the UITableView/ioBubbleList, every cell disappears like this:
If from the storyboard I start from the navigator controller, then everything works fine. Any hint?
I solved this.
My issue was I was not keeping a reference of the UITableViewControllers and UITableViews I was adding inside the UIScrollView.
I just initialized and NSMutableArray and saved the UITableViewControllers the way I added the UITableViews into the UIScrollView.
EDIT
After some research I found that there is a smarter/better way to do this. Instead of keeping the instance inside our own array we should add the view controllers as childs to the container view controller (the UIViewController with the UIScrollView).
Here the explanation from apple docs:
https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/CreatingCustomContainerViewControllers/CreatingCustomContainerViewControllers.html
Here the code I used:
self.addChildViewController(tableViewController)
self.scrollView.addSubview(tableViewController.view)
tableViewController.didMoveToParentViewController(self)
Saving the tableViewControllers just in an array cannot keep track of the hierarchy inside the content view controller. This means that if we want to access the content view controller from the table view controllers we cannot. And several errors could happen with the UINavigationController if we are using it.

UILabel won't update

I need enlightenment with my view controllers. The first view controller has a UILabel and a UIButton. The UIButton leads to the second view controller.
The second view controller is a UITableView. Everything in this view is done programmatically including the UINavigationBar, UINavigationItem, and the UIBarButtonItem. It has NO UINavigationController.
So once a user selects a currency from the list, it should update the UILabel in the first view controller. But it won't.
first view controller .h:
#import <UIKit/UIKit.h>
#import "CurrencyListViewController.h"
#interface InformationViewController : UIViewController <CurrencyListViewControllerDelegate>
#property (nonatomic, retain) IBOutlet UILabel *currencyLabel;
- (IBAction)currencyButton;
#end
first view controller .m:
- (void)viewDidLoad
{
[super viewDidLoad];
[self createCurrencyButton];
[self createAcceptDeclineButton];
[self createCurrencyLabel];
}
- (IBAction)currencyButton
{
CurrencyListViewController *currencyView = [[CurrencyListViewController alloc] initWithNibName:#"CurrencyListViewController" bundle:nil];
currencyView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
currencyView.delegate = self;
[self presentViewController:currencyView animated:YES completion:nil];
}
- (void)createCurrencyLabel
{
currencyLabel = [[UILabel alloc] initWithFrame:CGRectMake(100.0, 100.0, 120.0, 40.0)];
currencyLabel.hidden = NO;
currencyLabel.textColor = [UIColor whiteColor];
currencyLabel.textAlignment = NSTextAlignmentCenter;
[currencyLabel setEnabled:NO];
[self.view addSubview:currencyLabel];
}
- (void)currencySelected: (NSString *)currencySelected
{
currencyLabel.text = [NSString stringWithFormat:#"%#", currencySelected];
NSLog(#"Current currency is %#", currencyLabel.text);
}
second view controller .h:
#import <UIKit/UIKit.h>
#protocol CurrencyListViewControllerDelegate <NSObject>
- (void)currencySelected: (NSString *)currencySelected;
#end
#interface CurrencyListViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
id<CurrencyListViewControllerDelegate> delegate;
}
#property (nonatomic, retain) UITableView *tableView;
#property (nonatomic, assign) id delegate;
#end
second view controller .m:
- (void)viewDidLoad
{
[super viewDidLoad];
UINavigationBar *navigationBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 44.0)];
UINavigationItem *navigationItem = [[UINavigationItem alloc] initWithTitle:#"Currency"];
UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithTitle: #"Cancel"
style:UIBarButtonItemStylePlain
target:self
action:#selector(cancelButtonPressed:)];
navigationItem.rightBarButtonItem = barItem;
UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(0.0, 44.0, self.view.frame.size.width, self.view.frame.size.height - navigationBar.frame.size.height) style:UITableViewStylePlain];
self.tableView = tableView;
[navigationBar pushNavigationItem:navigationItem animated:NO];
[self.view addSubview:tableView];
[self.view addSubview:navigationBar];
[self showCurrencies];
self.tableView.dataSource = self;
self.tableView.delegate = self;
}
- (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 = [arrayOfCurrencies objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
InformationViewController *informationViewController = [[InformationViewController alloc] init];
if ([_delegate respondsToSelector:#selector(currencySelected:)]) {
informationViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[_delegate currencySelected:[arrayOfCurrencies objectAtIndex:indexPath.row]];
NSLog(#"The user selects %#", [arrayOfCurrencies objectAtIndex:indexPath.row]);
}
[self presentViewController:informationViewController animated:YES completion:nil];
}
I am able to output:
2013-06-05 00:16:58.731 Testing[7056:c07] Current currency is AOA: Angolan Kwanza
2013-06-04 19:08:27.222 Testing[3613:c07] 2013-06-05 00:16:58.732 Testing[7056:c07] The user selects AOA: Angolan Kwanza
But the UILabel in my first view controller will NOT.
Why are presenting informationViewController again? dismiss the Current ViewController, which is CurrencyListViewController and do the currencySelected function
Should look like this:
[self dismissModalViewControllerAnimated:YES];
[_delegate currencySelected:[arrayOfCurrencies objectAtIndex:indexPath.row]];

NSInvalidArgumentException tableView:numberOfRowsInSection error...but I am not using a tabbed view and I haven't used the Interface Builder at all

I'm trying to create an app for the iPhone where I pull data from a database and then display it on a table (a completely new view from the main screen in which I ask the user to enter in data). I've used this framework to help switch views in my app:
http://www.pushplay.net/2009/05/framework-for-having-multiple-views-in-an-iphone-app/
And basically, I modified it a little bit. I have it implemented fine, but when I populate the table I have to pass the array of information from a class where I pull the data from into the view where I display the table. I found the problem with my code (displayed below).
-(void) displayView:(int)intNewView{
NSLog(#"%i", intNewView);
[currentView.view removeFromSuperview];
[currentView release];
ServiceProvider *g = [[ServiceProvider alloc] init];
ServiceProvider *l = [[ServiceProvider alloc] init];
[g setSPNAME:#"george"];
[l setSPNAME:#"luuuuuusaaaa"];
passInTableToTOI = [[NSMutableArray alloc] initWithObjects:g, l, nil];
ResultsPage *rP = [[ResultsPage alloc] initWithNibName:#"TableOfItems" bundle:[NSBundle mainBundle]];
TableOfItems *tOI = [[TableOfItems alloc] init];
switch (intNewView) {
case 1:
currentView = [[SearchPage alloc] init];
break;
case 2:
[tOI setPassedThroughTable:passInTableToTOI];
[rP setResultsTable:tOI];
currentView = rP;
break;
case 3:
currentView = [[ShowAllPage alloc] init];
break;
/*default:
break;*/
}
//[rP release];
//[tOI release];
[self.view addSubview:currentView.view];
}
The table gets passed fine, but when I try to display the view I get this error "Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ResultsPage tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x4e396c0". I feel like I'm not giving enough information, so please if you'd like more information don't hesitate. I'm not sure what else I'm being vague on so it'd help to let me know how I can be more specific. Thanks a lot everyone.
[[EDIT 1]]
//===========ResultsPage.h
#import <UIKit/UIKit.h>
#class TopBottomRectangles;
#class TableOfItems;
#class SearchTextBox;
#interface ResultsPage : UIViewController {
TopBottomRectangles *tbRects;
TableOfItems *resultsTable;
SearchTextBox *sTB;
}
#property (nonatomic, retain) IBOutlet TableOfItems *resultsTable;
#end
//===================ResultsPage.m file
#import "ResultsPage.h"
#import "TopBottomRectangles.h"
#import "TableOfItems.h"
#import "SearchTextBox.h"
#import "MultiviewAppDelegate.h"
#implementation ResultsPage
#synthesize resultsTable;
-(void)goToShowAllPage
{
MultiviewAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate displayView:3];
}
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
/*
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization.
}
return self;
}
*/
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
NSLog(#"load the results page");
tbRects = [[TopBottomRectangles alloc] init];
sTB = [[SearchTextBox alloc] init];
[self.view addSubview:[resultsTable view]];
[self.view addSubview:tbRects.bottomBG_View];
[self.view addSubview:tbRects.topBG_View];
[self.view addSubview:sTB.textBox_BG_border];
[self.view addSubview:sTB.textBox_BG];
[self.view addSubview:sTB.textBox];
//[self.view addSubview:btnTwo];
[super viewDidLoad];
}
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations.
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (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 {
NSLog(#"dealloc results page");
[sTB release];
[resultsTable release];
[tbRects release];
[super dealloc];
}
#end
[[EDIT 2]]
//====TableOfItems.h file
#import <UIKit/UIKit.h>
#interface TableOfItems : UITableViewController {
NSMutableArray *listOfItems;
NSMutableArray *passedThroughTable;
}
#property (nonatomic, retain) NSMutableArray* passedThroughTable;
#end
//=====TableOfItems.m file
#import "TableOfItems.h"
#import "MyTableCell.h"
#import "ServiceProvider.h"
#implementation TableOfItems
#synthesize passedThroughTable;
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
self.navigationController.navigationBarHidden = YES;
//set the size of the table
[self fixTableSize];
NSMutableArray *spName = [[NSMutableArray alloc] init];
for (int i = 0; i < [passedThroughTable count]; i++){
ServiceProvider *willBeGone = [[ServiceProvider alloc] init];
willBeGone = [passedThroughTable objectAtIndex:i];
[spName addObject:willBeGone.SPNAME];
NSLog(#"%#", [spName objectAtIndex:i]);
//[willBeGone release];
}
//Initialize the array.
listOfItems = [[NSMutableArray alloc] init];
NSArray *countriesToLiveInArray = [NSArray arrayWithObjects:#"Iceland", #"Greenland", #"Switzerland", #"Norway", #"New Zealand", #"Greece", #"Rome", #"Ireland", nil];
NSDictionary *countriesToLiveInDict = [NSDictionary dictionaryWithObject:countriesToLiveInArray forKey:#"Countries"];
NSArray *countriesLivedInArray = [NSArray arrayWithObjects:#"India", #"U.S.A", nil];
NSDictionary *countriesLivedInDict = [NSDictionary dictionaryWithObject:countriesLivedInArray forKey:#"Countries"];
[listOfItems addObject:countriesToLiveInDict];
[listOfItems addObject:countriesLivedInDict];
}
-(void)fixTableSize{
CGRect screenBounds = [[UIScreen mainScreen] bounds];
CGFloat screenScale = [[UIScreen mainScreen] scale];
NSInteger height = screenBounds.size.height * screenScale;
NSInteger windowHeight = 100;
NSInteger yFromTop = 60;
NSInteger yFromBottom = height + 30 - windowHeight;
self.tableView.frame = CGRectMake(0,yFromTop,320,yFromBottom - yFromTop);
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return [listOfItems count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSArray *sectionTitles = [[NSArray alloc] initWithObjects:#"Countries to visit", #"Countries visited", nil];
return [sectionTitles objectAtIndex:section];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
NSLog(#"====");
//Number of rows it should expect should be based on the section
NSDictionary *dictionary = [listOfItems objectAtIndex:section];
NSArray *array = [dictionary objectForKey:#"Countries"];
return [array count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *MyIdentifier = [NSString stringWithFormat:#"MyIdentifier %i", indexPath.row];
MyTableCell *cell = (MyTableCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
NSDictionary *dictionary = [listOfItems objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:#"Countries"];
if (cell == nil) {
cell = [[[MyTableCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];
UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(1, 1, 30.0,
tableView.rowHeight)] autorelease];
[cell addColumn:60];
//label.tag = FIRCOL_TAG;
label.font = [UIFont systemFontOfSize:12.0];
label.text = [NSString stringWithFormat:#"%d:00", indexPath.row];
label.textAlignment = UITextAlignmentRight;
label.textColor = [UIColor blueColor];
label.autoresizingMask = UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleTopMargin;
[cell.contentView addSubview:label];
label = [[[UILabel alloc] initWithFrame:CGRectMake(70.0, 0, 110,
tableView.rowHeight)] autorelease];
[cell addColumn:260];
//label.tag = SECCOL_TAG;
label.font = [UIFont systemFontOfSize:12.0];
label.text = [NSString stringWithFormat:#"%#", [array objectAtIndex:indexPath.row]];
label.textAlignment = UITextAlignmentLeft;
label.textColor = [UIColor blackColor];
label.autoresizingMask = UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleHeight;
[cell.contentView addSubview:label];
label = [[[UILabel alloc] initWithFrame:CGRectMake(270.0, 0, 30,
tableView.rowHeight)] autorelease];
//[cell addColumn:180];
//label.tag = THIRCOL_TAG;
label.font = [UIFont systemFontOfSize:12.0];
// add some silly value
label.text = [NSString stringWithFormat:#"$%d", indexPath.row * 4];
label.textAlignment = UITextAlignmentLeft;
label.textColor = [UIColor blueColor];
label.autoresizingMask = UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleHeight;
[cell.contentView addSubview:label];
}
return cell;
}
#end
I think the problem is not in the code that shows you. When you read the Exception, the problem is in ResultsPage class
ResultsPage *rP = [[ResultsPage alloc] initWithNibName:#"TableOfItems" bundle:[NSBundle mainBundle]];
in tableview data delegate method :
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
So maybe the returned value is wrong or some arguments. We need ResultsPage code.
Bye
The error message is telling you that you're calling a UITableViewDataSource method on something that is not a UITableViewDataSource, because it does not implement the method: tableView:numberOfRowsInSection.
This method has to do with UITableView objects, and I don't see any UITableView objects anywhere in your code (nor in the PushPlay examples.)
Without going through it with a fine-toothed comb, I'd say you're trying to use an NSMutableArray in place of a UITableView and it's delegates.
An array makes a fine data source for a UITableView, but is not a direct substitute for a tableView.
Hope that helps.
-Mike
I found my problem. It was this clause:
ResultsPage *rP = [[ResultsPage alloc] initWithNibName:#"TableOfItems" bundle:[NSBundle mainBundle]];
TableOfItems *tOI = [[TableOfItems alloc] init];
It's supposed to be
ResultsPage *rP = [[ResultsPage alloc] init];
TableOfItems *tOI = [[TableOfItems alloc] initWithNibName:#"TableOfItems" bundle:[NSBundle mainBundle]];
I had a .xib file called "TableOfItems" and that should be corresponding to the class that populates the user interface, TableOfItems. This class hass all those delegates which creates the rows and sections and whatnot.
I'm sorry that I made such a foolish error...I don't think this would have been easily found by someone who didn't have access to the .xcodeproj

Resources