Veeru
Veeru

Reputation: 4936

Iphone programming: Multiple UITableViews reading from the same source?

This question is related to UITableView issue when using separate delegate/dataSource, though I have a different problem. I'm just starting to learn iPhone programming.

Basically I have one main view with a table. On the event of a cell click, a sub view with another table is shown.

The datasource and delegate for the main view's table are set as files' owner, and I have added the necessary code in there to handle the table data and everything is fine. But, when the second table in the sub-view seems to crash the application, I did the same thing, set the datasource and delegate to the file's owner and repeated the same procedure as for the main view's table. I have no idea why this is happening.

The sub-view has its only nib/xib file and its own outlet. If i do not attach any datasource to the subview's table, it takes the data from the main view's table; I don't understand why that is, since I have set the datasource to be the file's owner.

For example: the FirstView controller has a table FirstTable, the datasource and delegate are set to the owner of Files. I added the following in FirstView.m:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 4;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"LibraryListingCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                       reuseIdentifier:CellIdentifier] autorelease];
    }
    cell.textLabel.text =@"Table Cell";
    return cell;
}

Everything works perfectly. The moment I repeat this with a second table and a second view, the application crashes saying

reason: '-[UISectionRowData tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x69188d0'

I have done exactly the same for second table: implemented numberOfRowsInSection and cellForRowAtIndexPatch inside secondview.m and set the second table's delegate and datasource to the file's owner. If I remove the delegate and datasource for the second table, the application doesn't crash but has an empty table in the second view.

Any suggestions? or am I missing some key concept here ?

Upvotes: 1

Views: 3917

Answers (3)

iphony
iphony

Reputation: 536

This is the main View controller .h file.

#import <UIKit/UIKit.h>
#import "SubView.h"
@interface StackOverTableSubViewViewController : UIViewController <UITableViewDelegate,UITableViewDataSource>
{
    UIView *contentView;
    UITableView *tblVw;
    NSMutableArray *array;
    SubView *SubViewObj;
}
@property(nonatomic,retain) UIView *contentView;
@property(nonatomic,retain) UITableView *tblVw;
@property(nonatomic,retain) NSMutableArray *array;
@property(nonatomic,retain) SubView *SubViewObj;
@end

This is the main View controller .m file.

#import "StackOverTableSubViewViewController.h"
@implementation StackOverTableSubViewViewController
@synthesize contentView,tblVw,array,SubViewObj;

// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView
{
    contentView=[[UIView alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
    contentView.autoresizingMask=(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
    contentView.autoresizesSubviews=YES;
    contentView.backgroundColor=[UIColor whiteColor];

    tblVw=[[UITableView alloc]initWithFrame:[[UIScreen mainScreen]bounds] style:UITableViewStylePlain];
    tblVw.dataSource=self;
    tblVw.delegate=self;
    tblVw.scrollEnabled=YES;

    array=[[NSMutableArray alloc]init];
    [array addObject:@"Row1"];
    [array addObject:@"Row2"];
    [array addObject:@"Row3"];
    [array addObject:@"Row4"];
    [array addObject:@"Row5"];
    [array addObject:@"Row6"];
    [array addObject:@"Row7"];
    [array addObject:@"Row8"];
    [array addObject:@"Row9"];
    [array addObject:@"Row10"];
    [array addObject:@"Row11"];
    [array addObject:@"Row12"];
    [contentView addSubview:tblVw];
    self.view=contentView;
}

- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
{
    return [array count];
}

// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"CellIdentifier";

    // Dequeue or create a cell of the appropriate type.
    // UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        cell.accessoryType = UITableViewCellAccessoryNone;
        cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
        cell.textLabel.numberOfLines = 0;
        [cell.textLabel sizeToFit];
    }
    cell.textLabel.text=[array objectAtIndex:indexPath.row];
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    SubViewObj=[[SubView alloc]init];
    [self.view addSubview:SubViewObj.view];
}

/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
}
*/

// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}

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

- (void)dealloc {
    [contentView release];
    [SubViewObj release];
    [tblVw release];
    [array release];
    [super dealloc];
}

@end

Add a view controller called subview. Here's subview.h:

#import <UIKit/UIKit.h>
@interface SubView : UIViewController <UITableViewDelegate,UITableViewDataSource>
{
    UIView *contentView;
    UITableView *tblVw;
    NSMutableArray *array;
}
@property(nonatomic,retain) UIView *contentView;
@property(nonatomic,retain) UITableView *tblVw;
@property(nonatomic,retain) NSMutableArray *array;
@end

And subview.m: #import "SubView.h" #import @implementation SubView @synthesize contentView,tblVw,array;

// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
    contentView=[[UIView alloc]initWithFrame:CGRectMake(200, 10, 300, 600)];
    contentView.autoresizingMask=(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
    contentView.autoresizesSubviews=YES;
    contentView.backgroundColor=[UIColor whiteColor];

    tblVw=[[UITableView alloc]initWithFrame:CGRectMake(200, 10, 300, 600) style:UITableViewStylePlain];
    tblVw.dataSource=self;
    tblVw.delegate=self;
    tblVw.scrollEnabled=YES;
    tblVw.layer.borderWidth=4.0;
    tblVw.layer.borderColor=[[UIColor redColor]CGColor];
    array=[[NSMutableArray alloc]init];
    [array addObject:@"Data1"];
    [array addObject:@"Data2"];
    [array addObject:@"Data3"];
    [array addObject:@"Data4"];
    [array addObject:@"Data5"];
    [array addObject:@"Data6"];
    [array addObject:@"Data7"];
    [array addObject:@"Data8"];
    [array addObject:@"Data9"];
    [array addObject:@"Data10"];
    [array addObject:@"Data11"];
    [array addObject:@"Data12"];

    [contentView addSubview:tblVw];
    self.view=contentView;

}

/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
}
*/

- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
{
    return [array count];
}

// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"CellIdentifier";

    // Dequeue or create a cell of the appropriate type.
    // UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        cell.accessoryType = UITableViewCellAccessoryNone;
        cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
        cell.textLabel.numberOfLines = 0;
        [cell.textLabel sizeToFit];
    }
    cell.textLabel.text=[array objectAtIndex:indexPath.row];
    return cell;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Overriden to allow any orientation.
    return YES;
}

- (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 {
    [super dealloc];
}

@end

Try this code. This app was done for the iPad. Change the dimensions as needed for the iPhone.

Upvotes: 1

iphony
iphony

Reputation: 536

You can use same datasource and delegate methods for multiple tables. You have to mention in which table you are doing operations. For example:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([tableView isEqual:TableView1])
    {
       //do work for tableview1
     }
     else if([tableView isEqual:TableView2])
   {
      //do operations for tableview2
   }
}

Upvotes: 3

Mick
Mick

Reputation: 187

I had the EXACT same issue and fixed it by deleting my connection from the table view's datasource to the files owner. Then I pasted in the code below replacing the existing cellForRowAtIndexPath. I had to change the array name to match my array and then reconnect the datasource to the files owner, and it started working. Must have been a snafu in my function code somewhere.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"CellIdentifier";
    // Dequeue or create a cell of the appropriate type.
    // UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        cell.accessoryType = UITableViewCellAccessoryNone;
        cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
        cell.textLabel.numberOfLines = 0;
        [cell.textLabel sizeToFit];
    }
    cell.textLabel.text=[array objectAtIndex:indexPath.row];
    return cell;
}

Upvotes: 1

Related Questions