I have two view controllers/
1. SetupRingBoardViewController
2. SetupRingBoard*ADD*ViewController
the first view controller is UITableViewController.
when we first launch the view - the ViewController has a 1 fixed section with a 1 fixed row.
In that ViewController, there is a UIBarButton that is calling the SetupRingBoardADDViewController (modal - default, I'm using storyboard).
the second view controller is UIView controller.
this viewController contains a UITableView and a UINavigationBar.
the UITableView is actually a one big form, that the user can enter data into it.
the UINavigationBar contains an 'Add' UIBarButton.
When this button is being pressed, the method 'addButton' is being called.
The 'addButton' method should refresh the UITableView in the SetupRingBoardViewController.
In the end, after pressing the 'addButton' button - there should be 2 sections in the SetupRingBoardViewController's UITableView:
1. The fixed section with 1 row in it.
2. A section with X rows in it, each row will have a title: #"A Row!";
(X = the number of 'addButton' being pressed).
Finally, here's the code:
SetupRingBoardViewController.h :
//
// SetupRingBoardViewController.h
//
//
// Created by on 12/24/12.
// Copyright (c) 2012 Noam. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "SetupRingBoardADDViewController.h"
//#import "StudyHour.h"
#interface SetupRingBoardViewController : UITableViewController
#property (nonatomic, strong) NSMutableArray *listOfStudyHours;
#end
SetupRingBoardViewController.m :
//
// SetupRingBoardViewController.m
//
//
// Created by on 12/24/12.
// Copyright (c) 2012 Noam. All rights reserved.
//
#import "SetupRingBoardViewController.h"
#import "SetupEmptyListViewController.h"
#interface SetupRingBoardViewController ()
#end
#implementation SetupRingBoardViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
-(id)init
{
self = [super init];
if(self != nil)
{
if(!_listOfStudyHours) _listOfStudyHours = [[NSMutableArray alloc] init];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if(_listOfStudyHours) NSLog(#"%#",_listOfStudyHours);
[self.tableView reloadData];
// 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 reloadData];
}
- (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.
if(![_listOfStudyHours count])
{
NSLog(#"numberOfSectionsInTableView: 1");
return 1;
}
else return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if(section == 0) return 1;
else return [_listOfStudyHours count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(![indexPath section])
{
NSLog(#"It got to the first");
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
return cell;
}
else
{
NSLog(#"It got to the second");
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = [_listOfStudyHours objectAtIndex:indexPath.row];
return cell;
}
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
*/
}
#end
SetupRingBoardADDViewController.h :
// SetupRingBoardADDViewController.h
//
//
// Created by on 12/26/12.
// Copyright (c) 2012 Noam. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "SetupRingBoardViewController.h"
#import "UITableViewCell+Checkmark.h"
//#import "StudyHour.h"
#interface SetupRingBoardADDViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
- (IBAction)addButton:(id)sender;
#end
SetupRingBoardADDViewController.m :
- (IBAction)addButton:(id)sender {
SetupRingBoardViewController *rbVC = [[SetupRingBoardViewController alloc] init];
[rbVC.listOfStudyHours addObject:#"A row!"];
NSLog(#"%#",rbVC.listOfStudyHours);
[[rbVC tableView] reloadData];
[self dismissViewControllerAnimated:YES completion:nil];
}
(This is not the whole code, but it is the only thing that is relevant.)
The problem is that the method cellForRowAtIndexPath is not being called when I call the [tableView reloadData].
I hope you'll help me, I'm trying to figure it out for a long time :/
Please check if you have set/connected Delegate and Datasource to the File's Owner.
And check the array count of your model, if it contains value of not?
NSLog in the numberOfRowsInSection method and check it by using breakpoints and step over.
I think you need to make 2 changes. One, put the creation of the array in viewDidLoad instead of init (neither initWithStyle: nor init will be called if you created your table view controller in a storyboard -- initWithCoder: will be, so you could use that instead of viewDidLoad):
- (void)viewDidLoad
{
[super viewDidLoad];
if(!_listOfStudyHours) _listOfStudyHours = [[NSMutableArray alloc] init];
if(_listOfStudyHours) NSLog(#"%#",_listOfStudyHours);
[self.tableView reloadData];
}
Secondly, In your button method, you need to go back to the same instance that you came from, not create a new one. You can use the presentingViewController property to do that:
- (IBAction)addButton:(id)sender {
SetupRingBoardViewcontroller *rbVC = (SetupRingBoardViewcontroller *)self.presentingViewController;
[rbVC.listOfStudyHours addObject:#"A row!"];
NSLog(#"%#",rbVC.listOfStudyHours);
[[rbVC tableView] reloadData];
[self dismissViewControllerAnimated:YES completion:nil];
}
Related
Okay so i have been fiddling with some iOS development, I am fairly new to this. Usually more of a PHP and JavaScript guy. But here is my issue... in my app I am creating that pulls a friendslist from a local xml file (it will be pointing to a php page on a server that generates a users friendslist but for simplicity sake of debugging and development I am using local.)
I have a View Controller (storybaord) that is loaded when I click "friends", as of now, the view loads but with no data, in the debugger I can see that its pulling the data from the XML, so I thought, okay maybe the TableView is never being called, so i put a breakpoint on the
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
But the app still continued to load the page,
So to recap I have a View Controller, with a search bar, toolbar and a table view, the table view has a placeholder cell given the identifier Cell, heres the coding the for friendsListTableViewController.h
//
// friendsListTableViewController.h
// #ME
//
// Created by Aaron Russell on 1/22/13.
// Copyright (c) 2013 Aaron Russell. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "TBXML.h"
#interface friendsListTableViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, NSObject>{
NSMutableArray *friendList;
TBXML * tbxml;
IBOutlet UIImage *imageFile;
}
#property (nonatomic, strong) NSMutableArray *_friends;
#property (nonatomic, strong) NSString *lname;
#end
and here is the friendsListTableViewController.m file
//
// friendsListTableViewController.m
// #ME
//
// Created by Aaron Russell on 1/22/13.
// Copyright (c) 2013 Aaron Russell. All rights reserved.
//
#import "friendsListTableViewController.h"
#interface friendsListTableViewController ()
#end
#implementation friendsListTableViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)viewDidLoad {
[super viewDidLoad];
//USED TO CONNECT TO SERVERS XML
// NSData *xmlData = [[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:#"www.soontobesite.com"]];
//tbxml = [[TBXML alloc]initWithXMLData:xmlData];
NSString *xmlData = [[NSBundle mainBundle] pathForResource:#"friendlist" ofType:#"xml"];
NSData *data = [[NSData alloc] initWithContentsOfFile:xmlData];
tbxml = [[TBXML alloc]initWithXMLData:data];
//strings
// Obtain root element
TBXMLElement * root = tbxml.rootXMLElement;
if (root)
{
TBXMLElement * elem_PLANT = [TBXML childElementNamed:#"friend" parentElement:root];
while (elem_PLANT !=nil)
{
TBXMLElement * elem_BOTANICAL = [TBXML childElementNamed:#"fname" parentElement:elem_PLANT];
NSString *botanicalName = [TBXML textForElement:elem_BOTANICAL];
[friendList addObject:botanicalName];
elem_PLANT = [TBXML nextSiblingNamed:#"friend" searchFromElement:elem_PLANT]; //IF I CALL BREAKPOINT ON THIS LINE THE SIMULATOR BREAKS
}
//TBXMLElement *fname = [TBXML childElementNamed:#"fname" parentElement:elem_PLANT];
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [friendList count];
}
- (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];
}
cell.textLabel.text = [friendList objectAtIndex:indexPath.row];
return cell;
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
*/
}
#end
//EDIT//
I got a little further, thanks to some advice listed in the comments below before it wouldnt break at numberOfSectionsInTableView or numberOfRowsInSection but now it will break when i put a break on the numberOfSectionsInTableView or numberOfRowsInSection but still not the cellForRowAtIndexPath
You forgot to allocate the friendList instance variable. At the beginning of viewDidLoad (or even better in the initializer) do the following:
friendList = [[NSMutableArray alloc] initWithCapacity:0];
If friendList is not initialized it has a nil value. Sending a message to nil in Objective-C does not crash the application, it just does not do anything. Also see this SO question.
In your code, invoking [friendList addObject:botanicalName] simply does nothing. Later on, when you invoke [friendList count] in numberOfRowsInSection, you will return 0 (zero) to the table view. Since the table view thinks that there are no rows it will never call cellForRowAtIndexPath.
I Have a tabbar with two items, one is a ViewController with a switch, the other is a Tableview, what i want to do is:
when the user hits the button the tableview will earn a new cell...
Codes:
viewclass.h:
#import <UIKit/UIKit.h>
#interface viewclass : UIViewController
#property (strong, nonatomic) IBOutlet UISwitch *myswitch;
#end
viewclass.m:
#import "viewclass.h"
#implementation viewclass
#synthesize myswitch;
- (void)viewDidUnload {
[self setMyswitch:nil];
[super viewDidUnload];
}
#end
tableviewclass.h:
#import <UIKit/UIKit.h>
#interface tableviewclass : UITableViewController{
NSMutableArray *list;
}
#end
tableviewclass.m:
#import "tableviewclass.h"
#import "viewclass.h"
#implementation tableviewclass
- (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
{
classedasrespostas *testswitch;
[super viewDidLoad];
list = [[NSMutableArray alloc] init];
if (testswitch.myswitch.on == YES) {
[list addObject:#"myobject"];
}
// 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)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#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 [lista 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];
}
// Configure the cell...
return cell;
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
*/
}
#end
This, classedasrespostas *testswitch;, does not create an object; it only declares a pointer that is going to hold the address of an object. Since you don't assign anything to it, there's nothing for it to act on when you get to if (testswitch.myswitch.on == YES) {.
Put NSLog(#"testswitch: %#", testswitch); before the if statement to see the problem.
I have a first table view and a segue that pushes to another table view. I'm already able to push the second table view when the user touches a cell from the first table view, but I can't but data in the second table view. My second table view is using my custom controller which inherits from UITableViewController. I use the method "cellForRowAtIndexPath:(NSIndexPath *)indexPath" to put text in my cells, but the code never gets to that method. I don't understand what the problem is.
Here is my custom class:
#import "TableViewControllerTop.h"
#interface TableViewControllerTop ()
#end
#implementation TableViewControllerTop
#synthesize tableView;
#synthesize cells;
- (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;
}
- (void)viewDidUnload
{
[self setTableView:nil];
[self setCells:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
#warning Incomplete method implementation.
// Return the number of rows in the section.
return 6;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Top 50 list";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Configure the cell...
cell.textLabel.text = #"Test";
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"selected");
}
#end
Thanks for your help. I can post more code if necessary.
Looks like your code is returning 0 for number of sections. So therefore it thinks there is nothing to show.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 0;
}
I have a Core Data stack in which there are two entities: 'Client' and 'Car'. Both are represented by tableViewControllers.
The first tableViewController fetches the list of clients and then once selected, the second displays a list of cars that client owns. Both are pushed onto a navigation controller. When I go 'back' from the second viewcontroller the program shows the firstviewcontroller successfully, waits a second or so then crashes. When I did a 'build and debug' the console gave this error:
Program received signal: “EXC_BAD_ACCESS”.
I dont understand it. Where should I look to find the error?
EDIT:I have included some code below to see if it is due to bad memory handling... I have deleted all commented out methods and as well as those not used before error crops up.
This is my ClientListViewController...
#implementation ClientListViewController
#synthesize clientsArray;
#synthesize coreDataModel;
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
// Set the title
self.title=#"Clients";
[self populateTable];
}
-(void)populateTable {
[self setClientsArray:[coreDataModel retrieveClientList]];
}
- (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 [clientsArray 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] autorelease];
}
// Configure the cell...
Client *client = (Client *)[clientsArray objectAtIndex:indexPath.row];
cell.textLabel.text = [client name];
return cell;
[client release];
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Create and push new view controller.
ClientCarsViewController *clientCarsViewController = [[ClientCarsViewController alloc] initWithNibName:#"ClientCarsViewController" bundle:nil];
//Pass the CoreDataModel to the view controller
clientCarsViewController.coreDataModel = coreDataModel;
// Pass the selected object to the new view controller
Client *client = (Client *)[clientsArray objectAtIndex:indexPath.row];
clientCarsViewController.client = client;
// Push the new viewController
[self.navigationController pushViewController:clientCarsViewController animated:YES];
// Release the objects
[clientCarsViewController release];
[client release];
}
#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.
self.clientsArray = nil;
}
- (void)dealloc {
[clientsArray release];
[coreDataModel release];
[super dealloc];
}
#end
This is my ClientCarsViewController implementation...
#implementation ClientCarsViewController
#synthesize carsArray;
#synthesize coreDataModel;
#synthesize client;
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
self.title = client.name;
// Get client's cars
NSSet *cars = client.cars;
// Import them into the carsArray
[self setCarsArray: [NSMutableArray arrayWithArray:[cars allObjects]]];
[cars release];
}
-(void)addCarToClient {
[coreDataModel addCarToClient:(Client *)client];
}
- (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 [carsArray 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] autorelease];
}
// Configure the cell...
Car *car = (Car *)[carsArray objectAtIndex:indexPath.row];
cell.textLabel.text = [car carName];
return cell;
[car release];
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here. Create and push another view controller.
}
#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.
self.carsArray = nil;
}
- (void)dealloc {
[self.client release];
[self.coreDataModel release];
[self.carsArray release];
[super dealloc];
}
#end
You are releasing objects you don't own. Have o look at Objective-C Memory Management Rules.
For example, when you obtain an object client like this:
Client *client = (Client *)[clientsArray objectAtIndex:indexPath.row];
You don't own it and should not release it.
I have been struggling to understand the difference between Storyboards and coding in Objective-C. It appears you can create a UITableView by both dragging the object into your Storyboard, or coding in a new view within Objective-C.
The problem is that I want to keep my Storyboard as slim as possible. So I'm trying to build and populate a UITableView with an NSArray of 5 strings. My code will only run 1 row before returning a compiler error... I am going to scrap the whole project and start fresh.
I would be very grateful if somebody familiar with the new Xcode 4.2/iOS5/Storyboards can provide a reasonable solution for building the UITableView. I know this is such a basic task which is why it's so frustrating to begin with. I can get the Table View working, but I cannot seem to get an Array to dynamically fill and create #X number of rows...
Let me know if I can provide any more info. I've tried to be as straightforward as possible - just need to get a TableView working and populate with an Array :)
EDIT - here is my project source code you can download to check out where I'm at.
The reason it crashes is that in the storyboard you have to change the tableview to dynamic prototypes instead of static cells.
For some reason Static Cells is the default setting. Once you get the hang of the Storyboards it's great, especially when dealing with tableviews. Your initial View is set up as the NavigationController which has your MasterviewController as the RootViewController, so it's being loaded as the firstView. Click on the TableView in the MainStoryboard and change the Cels to Dynamic Prototypes or it will use the static ones that you create right in the storyboard. You can make custom cells right on the tableview in the storyboard. One more thing to note is the re-use identifier has to be set to the same name in the storyboard and the TableViewController.
You can also just up the count of static cells to the number you want if you know it will always be the same.
Here's a trivial sample with subclassing UITableViewController populated with an NSArray (NSMutableArray) from my sample code. It doesn't use story boards but you said that's OK in your comment. Hopefully my sample code helps you.
Header:
#interface MainTableViewController : UITableViewController
{
NSMutableArray *_items;
}
#end
Implementation:
#implementation MainTableViewController
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark Lifetime
#pragma mark -
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self)
{
// datastore
_items = [[NSMutableArray alloc] init];
for (int index=0; index < 5; index++)
{
[_items addObject:[NSString stringWithFormat:#"item #%d", index]];
}
}
return self;
}
- (void)dealloc
{
[_items release];
[super dealloc];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark Table View DataSource
#pragma mark -
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// a typical table has one section
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// number of rows
return [_items count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// NSIndexPath contains an array of indexes. For UITableView:
// indexAtPosition:0 is the section number
// indexAtPosition:1 is the row number
// create an identifier for this type of cell
static NSString *CellIdentifier = #"Cell";
// get a cell of this type from the re-use queue or create one
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
NSString *title = [_items objectAtIndex:[indexPath indexAtPosition:1]];
[[cell textLabel] setText:title];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
return cell;
}
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// Delete the row from the data source
NSLog(#"delete section: %d rol: %d", [indexPath indexAtPosition:0], [indexPath indexAtPosition:1]);
[_items removeObjectAtIndex:[indexPath indexAtPosition:1]];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert)
{
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
NSLog(#"insert section: %d rol: %d", [indexPath indexAtPosition:0], [indexPath indexAtPosition:1]);
}
}
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
NSString *fromItem = [_items objectAtIndex:[fromIndexPath indexAtPosition:1]];
[_items removeObjectAtIndex:[fromIndexPath indexAtPosition:1]];
[_items insertObject:fromItem atIndex:[toIndexPath indexAtPosition:1]];
}
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark UITableViewDelegate
#pragma mark -
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"selected section: %d rol: %d", [indexPath indexAtPosition:0], [indexPath indexAtPosition:1]);
// get the selected cell
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
// navigate to detail
DetailedTableViewController *detailedView = [[DetailedTableViewController alloc] init];
[[self navigationController] pushViewController:detailedView animated:YES];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark View lifecycle
#pragma mark -
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
}
- (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] setRightBarButtonItem: [self editButtonItem]];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end