Creating an editable Table View in iOS?

I am trying to create an editable table view in iOS using .xib files.

My code looks like this :

viewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UITableViewController

@property (nonatomic, strong) NSMutableArray *notes;

@end

viewController.m

#import "ViewController.h"
#import "Note.h"

@interface ViewController ()

@end

@implementation ViewController

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self setEditing:NO animated:NO];
}

- (void)viewWillAppear:(BOOL)animated{

    self.notes = [[Note savedNotes]mutableCopy];
    [self.tableView reloadData];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Button Events

- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
    [super setEditing:editing animated:animated];

    if (editing) {
        UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelButtonPressed:)];
        self.navigationItem.leftBarButtonItem = cancelButton;

        UIBarButtonItem *doneButton = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(rightButtonPressed:)];

        self.navigationItem.rightBarButtonItem = doneButton;

    }else{
        self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
                                                                                             target:self
                                                                                             action:@selector(addNoteButtonPressed:)];

        UIBarButtonItem *editButton = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemEdit
                                                                                   target:self
                                                                                   action:@selector(rightButtonPressed:)];

        self.navigationItem.rightBarButtonItem = editButton;
    }

}

- (void)rightButtonPressed:(id)sender{

    [self setEditing:!self.isEditing animated:YES];
}

- (void)cancelButtonPressed:(id)sender{
    [self setEditing:!self.isEditing animated:YES];
}

- (void)addNoteButtonPressed:(id)sender{
    //ATTViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:@"ATTViewController"];
    //[self.navigationController pushViewController:viewController animated:YES];
}

#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 [self.notes count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    // Configure the cell...

    Note *note = self.notes[indexPath.row];

    cell.textLabel.text = note.name;
    cell.detailTextLabel.text = note.event;

    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;
}

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return UITableViewCellEditingStyleDelete;
}


// 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
        Note *note = self.notes[indexPath.row];
        [note remove];
        [self.notes removeObjectAtIndex:indexPath.row];
        [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];
     */
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

@end

In the identity inspector of the .xib , i change the class from UIView to UITableView .

I connect the view with the datasource and/or with the delegate(i tried all combinations).

However i always get nothing on the phone. I dont get the table view , just an empty grey screen.

Any ideas what i am doing wrong? The code above was working in a project using storyboards and now i am trying to make it work with .xib files.

Screenshot :

Answers


I recommend checking out the free Sensible TableView framework. Will automatically handle displaying your arrays and will handle all inserts/deletes on your behalf. Saves a ton of time for me.


Add at least one item to your array or nothing will be displayed (currently your cellForRowAtIndexPath is returning 0). Also, make sure the tableView's delegate is assigned to your class in IB.


After some work I was able to do it and decided to make it public:

Code on GitHub

I was learning how to do this but I wanted to support move, delete and add.

Some examples showed only the add button on the last row and others only showed the move/delete.

The tricky bit for me was to support the 3 at the same time.

Hope it helps.

Here's the code:

EditTVC.h

#import <UIKit/UIKit.h>

@interface EditTVC : UITableViewController

@end

EditTVC.m

//
//  EditTVC.m
//  editTableViewTest
//

#import "EditTVC.h"

@interface EditTVC ()

@property (nonatomic) NSMutableArray *myItems;

@end

@implementation EditTVC

@synthesize myItems;

- (void)viewDidLoad
{
    [super viewDidLoad];

    myItems = [[NSMutableArray alloc] init];

    for (int i=0; i<5; i++)
    {
        [myItems addObject:[NSString stringWithFormat:@"Hey %d",i]];
    }

    NSLog(@"%@",myItems);


    // Display an Edit button in the navigation bar for this view controller.
    self.navigationItem.rightBarButtonItem = self.editButtonItem;
}

#pragma mark - Table view data source


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.

    if (self.editing) {
        return myItems.count +1;
    }

    return myItems.count;
}

-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row == myItems.count)
        return UITableViewCellEditingStyleInsert;
    else
        return UITableViewCellEditingStyleDelete;
}

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return NO if you do not want the item to be re-orderable.
    if (indexPath.row == myItems.count)
        return NO;
    else
        return YES;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"MyCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    // Configure the cell...

    if (self.editing && indexPath.row == myItems.count)
    {
        cell.textLabel.text = @"Add ...";
    }
    else
    {
        cell.textLabel.text = myItems[indexPath.row];
    }

    return cell;
}

-(void)setEditing:(BOOL)editing animated:(BOOL)animated {

    [super setEditing:editing animated:animated];

    if(editing)
    {
        //edit mode
    }

    else
    {
        //non-edit mode
    }

    [self.tableView reloadData];
}

// 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
        [myItems removeObjectAtIndex:indexPath.row];

        [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
        [myItems insertObject:[NSString stringWithFormat:@"Added %ld",(long)indexPath.row] atIndex:indexPath.row];
        [tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }
    NSLog(@"%@",myItems);
}

// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
    if (toIndexPath.row == myItems.count) //we only check the toIndexPath because we made the AddCell not to respond to move events
    {
        id tmp = [myItems objectAtIndex:fromIndexPath.row];
        [myItems removeObjectAtIndex:fromIndexPath.row];
        [myItems insertObject:tmp atIndex:toIndexPath.row-1]; //to keep it in valid range for the NSMutableArray

        [self.tableView reloadData];
    }

    else
    {
        id tmp = [myItems objectAtIndex:fromIndexPath.row];
        [myItems removeObjectAtIndex:fromIndexPath.row];
        [myItems insertObject:tmp atIndex:toIndexPath.row];
    }

    NSLog(@"%@",myItems);
}



@end

Need Your Help

OpenJPA, memory overhead for huge number of insertions

jpa garbage-collection openjpa

Basically I am creating a sort of graph on a huge dataset. I keep a bunch of nodes in memory and then I iteratively load another bunch of those to create the edges that connect them with the previous

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.