UITableView removing and adding rows - objective-c

I have an NSMutableArray containing sequential numbers 1,2...,n and have a UITableView that displays cells vertically ascending and in order. How would I go about deleting a row, m between 1 and n, both visually and in the data, as well as in the NSMutableArray, and then decrement by 1 the value of all cells that followed the deleted cell in the data and visually such that the firstResponder does not resign control like a reloadData method call would?
#interface TableController : UIViewController
#property (nonatomic, retain) NSMutableArray *data;
#end
#implementation TableController
#synthesize data;
- (id)init
{
if(self = [super init]) {
data = [NSArray arrayWithObjects:#"1",#"2",#"3",#"4",#"5",nil];
}
return self;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [data count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [UITableViewCell new];
[cell.textLabel setText:[data objectAtRow:indexPath.row]];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 20;
}
#end
How would I remove row 3 and then make rows four and five then become 3 and 4 respectively?

Just edit your view model and then reload the table.
[data removeObjectAtIndex:2];
[tableView reloadData];
Another option is the UITableView method deleteRowsAtIndexPaths:withRowAnimation:. This approach is UI only, you must also update your view model in case the cells ever get reloaded at a later time. The advantage of this approach is that only the cells you specify get changed. Existing cells are not reloaded.
If the cell you are deleting is your first responder then you could handle this case by telling the next cell to become first responder.

For user driven deletion, your [tableview dataSource] should implement the method tableView:commitEditingStyle:forRowAtIndexPath:.
Here's an implementation from my code…
-(void) tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if(editingStyle == UITableViewCellEditingStyleDelete)
{
[[STLocationsModel sharedModel] deleteLocationAtIndex: [indexPath row]];
[tableView deleteRowsAtIndexPaths: #[indexPath] withRowAnimation: UITableViewRowAnimationLeft];
}
}
To allow editing, you'll also want…
-(BOOL) tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
To get the table in to editing mode to allow deletions, you need to put it in to editing mode. You could place this in your viewDidLoad, or you might toggle it with a button:
[[self tableView] setEditing:YES animated:NO];
And if you also want to be able to make selections while the table is edited (again, this could go in your viewDidLoad…
[[self tableView] setAllowsSelectionDuringEditing: YES];

Related

Save checkmark in NSUserDefaults - dynamic TableView

Solution!!
Thanks Josh for all the patience :D
So the code in the initial question always ticks the selected cell and deselects a previously selected cell without saving anything to the NSUserDefaults. After a lot of help from Josh the new code (right below) is the following (exactly the same as in his reply/I only clened it up a little and removed #properties defined in previous attempts to make it work).
The user taps one of the 7 cells. The indexPath of tapped cell is then saved in the NSUserdefaultsand when the TableView is open again a checkmark is displayed next to the previously tapped cell. The indexpath is always saved in the same NSObjectso only one checkmark will ever be displayed.
#import "CycleTableViewController.h"
#import "SettingsTableViewController.h"
#interface CycleTableViewController ()
#property (nonatomic) int selectedRow;
#end
#implementation CycleTableViewController
#synthesize array;
- (void)viewDidLoad {
//load array containing options
array=#[#"1", #"2", #"3", #"4", #"5", #"6", #"7"];
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void) viewWillDisappear:(BOOL)animated{
//save indexpath of tapped cell to NSUserdefaults
[[NSUserDefaults standardUserDefaults] setObject:#(indexPath.row) forKey:#"cycle"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIndentifier=#"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIndentifier forIndexPath:indexPath];
cell.textLabel.text = [array objectAtIndex:indexPath.row];
//display checkmark next to the tapped cell
if(indexPath.row == self.selectedRow){
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else{
ell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//assign indexpath to selectedRow, so NSUserdefaults can save them
self.selectedRow = indexPath.row;
[self.tableView reloadData];
}
//save indexpath of tapped cell to NSUserdefaults
[[NSUserDefaults standardUserDefaults] setObject:#(indexPath.row) forKey:#"cycle"];
[[NSUserDefaults standardUserDefaults] synchronize];
#end
Initial question
I've been reading through tons of posts on here on saving an index path to the user defaults, but none of them has worked for me...
In the following TableView I have an array of data (1-7) that is displayed and then passed to another ViewController once a cell is pressed. The pressed cell gets a checkmark and if I go back using the Navigation Controller I can see the checkmark. Only one item is selected at a time. If I press another row, the checkmark changes.
So now I want to save the indexpath of the selected row to the UserDefaults (in the didselectrowat indexpath) and the load it in the viewdidload but I always get a build failed, whatever I try...
Can somebody please point me in the right direction? This should be easy, but I somehow just can't get it to work :/
Updated Code! Once I get it working I'll upload the finished answer!
#import "CycleTableViewController.h"
#import "SettingsTableViewController.h"
#interface CycleTableViewController (){
NSString *currentCategory; // pointer to the currently checked item
}
// other #property declarations here or in your .m file
#define CHECKED_KEY #"kCheckedBoxKey"
#property (nonatomic) int selectedRow;
#end
#implementation CycleTableViewController
#synthesize array;
- (void)viewDidLoad {
//load tickmark according to newCell;
array=#[#"21+7", #"22+6", #"23+5", #"24+4", #"25+3", #"26+2", #"28"];
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void) viewWillAppear:(BOOL)animated {
self.selectedRow = [[[NSUserDefaults standardUserDefaults] objectForKey:#"cycle"] intValue];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIndentifier=#"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIndentifier forIndexPath:indexPath];
cell.textLabel.text = [array objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[[NSUserDefaults standardUserDefaults] setObject:#(indexPath.row) forKey:#"cycle"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSIndexPath *IndexPath = [NSIndexPath indexPathForRow:self.selectedRow inSection:0];
UITableViewCell *Cell = [tableView cellForRowAtIndexPath:IndexPath];
Cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
#end
#import "CycleTableViewController.h"
#import "SettingsTableViewController.h"
#interface CycleTableViewController (){
NSString *currentCategory; // pointer to the currently checked item
}
// other #property declarations here or in your .m file
#define CHECKED_KEY #"kCheckedBoxKey"
#property (nonatomic) int selectedRow;
#end
#implementation CycleTableViewController
#synthesize array;
- (void)viewDidLoad {
//load tickmark according to newCell;
array=#[#"21+7", #"22+6", #"23+5", #"24+4", #"25+3", #"26+2", #"28"];
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void) viewWillAppear:(BOOL)animated {
self.selectedRow = [[[NSUserDefaults standardUserDefaults] objectForKey:#"cycle"] intValue];
}
- (void) viewWillDisappear:(BOOL)animated{
[[NSUserDefaults standardUserDefaults] setObject:#(indexPath.row) forKey:#"cycle"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIndentifier=#"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIndentifier forIndexPath:indexPath];
cell.textLabel.text = [array objectAtIndex:indexPath.row];
if(indexPath.row == self.selectedRow){
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.selectedRow = indexPath.row;
[self.tableView reloadData];
}
#end
Where in the code are you saving the user defaults?
In didSelectRowAtIndexPath, you could add:
[[NSUserDefaults standardUserDefaults] setObject:#(indexPath.row) forKey:#"nameOfSetting"];
[[NSUserDefaults standardUserDefaults] synchronize];
In the cellForRowAtIndexPath you can check if
indexPath.row == [[[NSUserDefaults standardUserDefaults] objectForKey:#"nameOfSetting"] intValue]
and if so, add the checkmark accessory. If not, show no accessory.
Note that I would actually create a property that holds the selectedValue, and only upon leaving the settings page or tapping a save button do you actually update the user defaults. Then in viewWillAppear I would set this property equal to the setting in the user defaults and call reload on the table.
EDIT
To expand on the final note, you can do the following:
In the interface...
#property (nonatomic) int selectedRow;
In the implementation...
self.selectedRow = [[NSUserDefaults standardUserDefaults] objectForKey:#"nameOfsetting"] intValue];
You can place this code in viewWillAppear, viewDidAppear or even in prepareForSegue in the previous view controller that you are segueing from as long as the selectedRow property is declared in the header file. I would not put this code in viewDidLoad.
Then separately in cellForRowAtIndexPath I would add something like:
if(indexPath.row == self.selectedRow){
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else{
cell.accessoryType = UITableViewCellAccessoryNone;
}
EDIT #2
In the OptionsViewController where the current setting is displayed you can load the setting from standardUserDefaults. You can save a number like I mentioned as the setting (i.e. if you have setting options, you can number them 0 - 6 and use a typedef to make the code more clear) or you can store a string. If you store your setting as a number, you just need a dictionary to map the number to a setting description. If you store your setting as a string, you could just display the string.
Regardless of the method chosen, in the OptionsViewController do this:
#import "SettingsViewController.h"
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.destinationViewController isKindOfClass:[SettingsViewController class]]){
SettingsViewController *settingsViewController = (SettingsViewController *) segue.destinationViewController;
settingsViewController.selectedSetting= <INSERT YOUR SETTING FROM STANDARDUSERDEFAULTS>
}
}
Basically, you are handing off your setting from the options to the settings view which contains your table. You can make your selectedSetting in the SettingsViewController a number or a string as above. Just as some point, you have to convert your setting into a number so that the table knows which row has the checkmark. I would keep the rest of the code the same, i.e. the if statement in the cellForRowAtIndexPath. You need to somehow check if the indexPath.row matches the selectedSetting (i.e. if it is a string, you need to convert it into a number). And in the viewWillAppear or viewDidAppear reload the tableView so the checkmark will be displayed.
When the user selects a different row, you can update the selectedSetting property and then in viewWillDisappear or prepareForSegue (i.e. before the unwind segue) you can update standardUserDefaults.

UITableView with Tab Bar Controller

I have a tab bar control and I want to show table view in first tab.
In my story board I have Tab Bar view controller with Items and I put the tableview and tableview cell in it. ( I am not sure about it. Should I put them to show data in tableview or should I do it programmatically?) I am getting the data from database (there is not any problem in this side) but can not bind the data in tableview.
What is wrong in my code?
My code:
.h file
#interface CategoryTabController : UIViewController<UITableViewDataSource, UITableViewDelegate>
{
DatabaseProcess *databaseProcess;
UITableView *categoryTableView;
NSMutableArray *categoryTableArray;
}
.m file
#implementation CategoryTabController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
databaseProcess = [[DatabaseProcess alloc]init];
//Get Category data to array
categoryTableArray = [[NSMutableArray alloc]initWithArray:[databaseProcess getAllActiveCategory]];
categoryTableView = [[UITableView alloc]init];
categoryTableView.delegate = self;
categoryTableView.dataSource = self;
[self.view addSubview: categoryTableView];
}
- (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 categoryTableArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CategoryCell" forIndexPath:indexPath];
cell.textLabel.text = [categoryTableArray objectAtIndex: indexPath.row];
return cell;
}
You must make categoryTableView as IBOutlet property and connect it to your table in IB. Also you must set "CategoryCell" as cell identifier in IB to 'dequeueReusableCellWithIdentifier' to work.

Swipe to delete

I Have a tableview and a cell in it :D with disclosure accessory selected. I created all ui elements with storyboard.
(didn't put a view in content of the cell)
I'm using SWTableViewCell to implement just swipe-to-delete, but everything seems work fine except when i put a breakpoint on to a method
#pragma mark -SWTableViewDelegate-
-(void)swipeableTableViewCell:(SWTableViewCell *)cell didTriggerRightUtilityButtonWithIndex:(NSInteger)index
{
NSIndexPath *path=[self.table indexPathForCell:cell];
[anArray removeObjectAtIndex:path.row];
[self.table deleteRowsAtIndexPaths:#[path] withRowAnimation:UITableViewRowAnimationRight];
}
and this will help you to understand what i simply done here
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
SWTableViewCell *cell=(SWTableViewCell*)[tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
if (!cell)
{
NSMutableArray *rightUtilityButtons = [NSMutableArray new];
[rightUtilityButtons sw_addUtilityButtonWithColor:[UIColor colorWithRed:1.0f
green:0.231f
blue:0.188
alpha:1.0f]
title:#"Delete"];
cell = [[SWTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell" containingTableView:_table leftUtilityButtons:nil rightUtilityButtons:rightUtilityButtons];
}
NSMutableDictionary *deDict=[[NSMutableDictionary alloc]initWithDictionary:[anArray objectAtIndex:indexPath.row]];
cell.textLabel.text= [deDict objectForKey:#"Name"];
return cell;
}
Yet, I don't get any error, because when i try to swipe on simulator, it simply does not work..
No need to use SWTableViewCell just Override following built-in methods of UITableView delegate for support conditional editing & swipe to delete
for conditional editing -- Optional --
//Override this method only if you are going to be returning NO for some items.
//By default, all items are editable.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return YES if you want the specified item to be editable.
return YES;
}
for swipe to delete
// Override to support editing the table view.
// for swipe to delete
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
//add code here for when you hit delete
}
}

How to get a custom UITableViewCell class created in IB to load into a UITableView?

I am new to this so please bear with me:
I have a .xib in IB containing a UIScrollView that has a UITableView embedded in it. I would like to load custom UITableViewCells into the UITableView. I have four/five custom cells created in IB but cannot get the first to load correctly.
Here are relevant screenshots from IB:
I have set the class for the custom UITableViewCell created in IB to the UITableView class I created called "itemCell". Additionally, I have connected the three text fields outlets and delegates to "itemCell".
Here is itemCell.h:
#import <UIKit/UIKit.h>
#interface itemCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UITextField *quantityTextField;
#property (weak, nonatomic) IBOutlet UITextField *itemTextField;
#property (weak, nonatomic) IBOutlet UITextField *priceTextField;
#end
Here is itemCell.m:
#import "itemCell.h"
#implementation itemCell
#synthesize quantityTextField,itemTextField,priceTextField;
- (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
In filecontroller.m, which is the rootcontroller .xib's implementation file I create a new cell based on the user pressing a button (add it to an array) and then reload the tableview. I am getting no errors but I am getting a normal cell loaded in rather than what I have created in IB. Here is rootcontroller.m. Any help is appreciated.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
scrollView =(UIScrollView *)self.view;
items = [[NSMutableArray alloc] init];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [items count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
return [items objectAtIndex:[indexPath row]];
}
- (UITableViewCell *)initiateNewCell{
itemCell *cell = [[itemCell alloc] init];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
return cell;
}
- (IBAction)addItem:(id)sender {
//creates the new cell to be added
[items addObject:[self initiateNewCell]];
[self.tableView reloadData];
As of iOS 5 you can now load a UITableViewCell from a nib for cell reuse with the following function.
- (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier
First make sure you create an IB file that contains only the UITableViewCell
Under Identify inspector: Set the class of the UITableViewCell to "itemCell"
Under attributes inspector: Set the identifier of the UITableViewCell to "itemCellIdentifier"
In viewDidLoad: place the following code, and replace itemCellNibName with the name of the nib that contains the UITableViewCell.
NSString *myIdentifier = #"itemCellIdentifier";
[self.tableView registerNib:[UINib nibWithNibName:#"itemCellNibName" bundle:nil] forCellReuseIdentifier:myIdentifier];
In cellForRowAtIndexPath: place the following code, you can now access your IBOutlet properties you set on the itemCell, and connected in the nib.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
static NSString *myIdentifier = #"itemCellIdentifier";
itemCell *cell = (itemCell *)[tableView dequeueReusableCellWithIdentifier:myIdentifier];
cell.textLabel.text = [NSString stringWithFormat:#"Test Row:%i!",indexPath.row];
return cell;
}
Also: You do not want to include the UITableView inside a UIScrollView, a UIScrollView is already built into the UITableView, which allows for proper cell queing.
Also: I suggest you just get the bare bones of this going first, before you start pulling data from an array.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 10;
}
Also: As someone else had mentioned, the array contains the data that will populate the UITableViewCells, not the actual cells themselves.
In your
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//This identifier string needs to be set in cell of the TableViewController in the storyboard
static NSString *CellIdentifier = #"Cell";
// Resuse the cell
SomeCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// If there are no cell to be reused we create a new one
if(cell == nil) {
cell = [SomeCustomCell new];
}
// Configure the cell...
NSString *someString = [yourArrayWithStringsOrWhatEver objectAtIndex:indexPath.row];
// Setting the some property of your custom cell
[cell.yourSpecificCellProperty someString];
[cell.yourOtherSpecificCellProperty setText:#"What Ever your want!"];
}
Your cell's properties could be whatever your have connected to your custom cell in interface builder.
Hope it helps!
Well there are a few things that aren't right:
The class name begins with upper case letter itemCell -> ItemCell
You should reuse the cell. The way you want to do this, you will create a separate cell for each index path.
the items array should only contain the data source of your table, not your cells
instead of calling reload data, you can add just one row to the table, and it can be animated too
Try something like:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
scrollView =(UIScrollView *)self.view;
items = [[NSMutableArray alloc] init];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [items count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[NSBundle mainBundle] loadNibNamed:#"itemCell" owner:self options:nil].lastObject;
cell.reuseIdentifier = CellIdentifier;
}
// Do any additional setup to the cell
return cell;
}
- (IBAction)addItem:(id)sender {
[items addObject:[NSNumber numberWithInt:items.count]]; // Here comes the data source
[self.tableView insertRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:items.count - 1 inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];
}
PS: I wrote it without an IDE so there might be some errors

Table view as an object in a view - how to initialize with an array of data?

My goal is to have something like a "select" option in a HTML form, but now in my app. After doing research it's probably best to do this with a table view. I though of the picker view, but the fixed height is too big.
With the interface builder I simply placed a table view on my subclass of UIViewController.
How do I fill the Table view with options? I've seen many tutorials, but those are all for having a UITableView as their own class and filling up the entire screen. In my application this is just a small piece of the entire form.
What a nightmare to create a relatively simple thing like a table view. It either crashes or I get a table view that covers my entire view and that is not filled with anything.
The variable countryTable is connected to the object in the interface builder.
Frustrated after a hard day of work. Anyone got the complete working code? That would be great. I already had a great look at apple's explenation AND various tutorials, but I can't figure it out.
I've tried multiple things, but this is my current code:
#interface myView: UIViewController
{
NSArray *countryArray;
IBOutlet UITableView * countryTable;
}
#property (nonatomic, retain) UITableView *countryTabel;
#end
and in my .m file
#implementation myView
#synthesize countryTable;
- (void)loadView
{
self.countryTable.dataSource = self;
}
- (void)viewDidLoad
{
NSArray *array = [[NSArray alloc] initWithObjects:#"test1", #"test2",
#"test3",nil];
self.countryTable = array;
[array release];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void) dealloc
{
[countryTable release];
[super dealloc];
}
#pragma mark -
#pragma mark Table View Data Source Methods
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return [self.countryTable count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier] autorelease];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [countryTable objectAtIndex:row];
return cell;
}
#end
You are on the right track. If you were to use a UITableViewController subclass, you would obviously have a full screen table view by default. Going the route of using a UIViewController subclass with a UITableView as a subview in the UIViewController's view is the right way to go. A few things that you will need to address are:
1) In the UIViewControllers header file you will need to add <UITableViewDatasource, UITableViewDelegate> as your view controller is responsible for fill implementing this functionally.
2) In viewDidLoad:, set self.contryTable.delegate = self; and self.countryTable.datasource = self;
The following protocol methods need to be implemented like so:
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
return countryArray.count;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier] autorelease];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [countryArray objectAtIndex:row];
return cell;
}
Hope this helps.