I am trying to implement programmatically a UITableView.
I have a UIView (named IndexView). Here is the constructor :
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
MyTableViewController* favorite_table_view_controller = [[MyTableViewController alloc] init];
UITableView* theTableView = [[UITableView alloc] initWithFrame:CGRectMake(20, 65, 280, 350) style:UITableViewStylePlain];
theTableView.delegate = favorite_table_view_controller;
theTableView.dataSource = favorite_table_view_controller;
[self addSubview:theTableView];
}
return self;
}
MyTableViewController is defined this way :
#interface MyTableViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
And implements the two necessary functions :
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return data.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"Cell"];
[cell.textLabel setText:[data objectAtIndex:indexPath.row]];
return cell;
}
And I get this error :
[__NSMallocBlock__ tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x6897de0
2012-07-18 12:07:24.607 ButtonsTest[22854:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSMallocBlock__ tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x6897de0'
I think there is a problem when I'm binding the controller to the view. But I can't find where.
Any idea where does the problem come from ?
You should not construct your viewcontroller from a view. It should be done the other way around.(construct views from UIVIewControllers)
make a ViewController that subclasses UIViewController and then let it implement the UITableViewDelegate and UITableViewDataSource. If you still need to control the UITableView from a another controller class setup this connection in the parent UIViewController, never from the View itself. That is the basic premise of the MVC used intensively in iOS
Related
I'm creating a table view and custom view for my UITableView. Basically I have FirstViewController with table view and CustomTableViewCell. In custom cell, I had link all the controls to header and implements in the file which superclass with UITableViewCell. I'm creating a button, and want to programatically using "instantiateViewControllerWithIdentifier" for more flexibility in future. Here's come a problem :
Button being initialized
[self.playButton addTarget:self action:#selector(NavigationMethod) forControlEvents:UIControlEventTouchUpInside];
NavigateMethod
UIViewController *secondViewController = [[UIStoryboard storyboardWithName:#"Main" bundle:nil]instantiateViewControllerWithIdentifier:#"SecondViewController"];
[(FirstViewController*) presentViewController:secondViewController animated:YES completion:nil];
Because everything is in UITableViewCell instead of UIViewController.
You're breaking Model View Controller methodology here... In FirstViewController you should have
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
MYCustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
{
cell = [[MYCustomTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; // might not be UITableViewCellStyleDefault
[cell.playButton addTarget:self action:#selector(navigationMethod) forControlEvents:UIControlEventTouchUpInside];
}
// all indexPath based tableViewCell changes here
return cell;
}
Now -(void)navigationMethod can go in your FirstViewController class also. Which will allow you to call
[self presentViewController:secondViewController animated:YES completion:nil];
or
[self.navigationController presentViewController:secondViewController animated:YES completion:nil];
Just to add in as well.. unrecognised selector sent to instance means in this case the method NavigationMethod is not found in your UITableViewCell subclass
I am passing a mutable array over from another viewcontroller by saving it in nsuserdefaults. I then retrieve it in the new viewcontroller in which it nslogs just fine. I run into a problem when my code reaches numberofrowsinsections. It seems like my tableview is not recognizing my array object. Thanks for any help as I am new at coding.
#import "ViewController.h"
#import "RecordView.h"
#import "bookCellTableViewCell.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize arr;
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray *arr = [[NSMutableArray alloc]init];
arr = [[NSUserDefaults standardUserDefaults] valueForKey:#"projects"];
NSLog(#"arr%#", [arr description]);
#pragma mark - Table view data source
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [arr count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//static NSString *CellIdentifier = #"Cell";
bookCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ToBook"];
if(cell != nil)
{
cell.songTitle.text = [arr objectAtIndex:indexPath.row];
testLabel.text = #"Hello";
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [bookView cellForRowAtIndexPath:indexPath];
}
#end
It's a scope issue:
You have declared your datasource in viewDidLoad
NSMutableArray *arr = [[NSMutableArray alloc]init];
That's not correct, your datasource should be a property , or a variable on class scope at least.
You should initialize it in viewDidLoad but declare it on the class level.
It seems like you have one property called arr already, a smart compiler should warn you that is ambiguous.
To fix this just remove NSMutableArray * part of that line, just like this:
arr = [[NSMutableArray alloc]init];
You are also misusing NSUserdefault it is not meant to pass data between controller, it is more appropriate for storing basic user settings values.
To pass data, simply set values on the ViewController properties before presenting it.
In Xcode 5.1, using StoryBoards, I'm having trouble getting a custom UITableViewCell to show it's contents. The cell appears -- I can tap to select it -- but the label text doesn't appear.
I've given the Cell my custom class GCell and identifier MyCell
I've connected an IBOutlets to a label in the prototype cell.
#import <UIKit/UIKit.h>
#interface GCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UILabel *nameLabel;
#end
In my class that extends UITableViewController, I have
#implementation PayGroupViewController
- (id)initWithStyle:(UITableViewStyle)style
{
NSLog (#"[PayGroupViewController] initWithStyle");
self = [super initWithStyle:style];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.delegate = self;
self.tableView.dataSource = self;
// [self.tableView registerClass:[GCell class] forCellReuseIdentifier:#"MyCell"];
_groups = [NSMutableArray arrayWithCapacity:20];
GroupModel *gm = [[GroupModel alloc] init];
gm.title = #"DINNER";
gm.names = [NSMutableArray arrayWithCapacity:10];
[gm.names addObject:#"Me"];
[gm.names addObject:#"Albert"];
[_groups addObject:gm];
NSLog (#"[PayGroupViewController] viewDidLoad. [self groups].count:%d" ,[self groups].count);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog (#"[PayGroupViewController] tableView. [self groups].count:%d" ,[self groups].count);
return [self groups].count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog (#"[PayGroupViewController] tableView cellForRowAtIndexPath");
GCell *c = (GCell *)[tableView dequeueReusableCellWithIdentifier:#"MyCell" forIndexPath:indexPath];
GroupModel *group = [self.groups objectAtIndex:indexPath.row];
NSLog (#"[PayGroupViewController] group.title: %#",group.title); // Outputs "DINNER"
c.nameLabel.text = group.title; // It does not show up
NSLog (#"[PayGroupViewController] cell: %#",c); // outputs <GCell: 0x9976ed0, etc. so it does exist
NSLog (#"[PayGroupViewController] cell.nameLabel: %#",c.nameLabel); // outputs (null)
return c;
}
Also, here is the entire xCode project if anyone cares to take a look.
http://www.brainjelly.com/WhoPaid.zip
Note that the prototype cell has a Disclosure Indicator Accessory, but that doesn't appear either.
Thanks… I've looked extensively over the other posts with this issue but none of those solutions helped me.
There are 2 problems in your xCode project.
You shouldn't register custom cell class in your code for prototype cells. Storyboard does that for you. When you register same class, you are basically overriding the one created by storyboard.
In your prototype cell there is an undefined outlet named "title", which is connected to Content View. Define or delete it.
After these, clear the project and recompile, it should be ok.
In my app I am trying to navigate to a new View from a TableViewCell, But i dont know how. Could you help guys? I am using Xcode 4.6. and .xib, no storyboard. I am very new to coding so please explain it as simple as possible! Here is what i have tried, please correct me:
- (void)viewDidLoad
{
tableData = [[NSArray alloc] initWithObjects:#"aaoversikt1", #"Paul", #"George", #"Ringo", nil];
[super viewDidLoad];
UILabel *nav_title1 = [[UILabel alloc] initWithFrame:CGRectMake(60, 10, 220, 25)];
nav_title1.font = [UIFont fontWithName:#"Arial-BoldMT" size:18];
nav_title1.textColor = [UIColor whiteColor];
nav_title1.adjustsFontSizeToFitWidth = NO;
nav_title1.textAlignment = NSTextAlignmentCenter;
nav_title1.text = #"Ă…lesund";
nav_title1.backgroundColor = [UIColor clearColor];
self.navigationItem.titleView = nav_title1;
}
#pragma mark - TableView Data Source methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section;
{
return [tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
UITableViewCell *cell = nil;
static NSString *CellIdentifier = #"Cell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
#pragma mark - TableView Delegate methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
AAOversiktViewController *aaoversikt1 = [[AAOversiktViewController alloc] initWithNibName:#"AAOversiktViewController" bundle:nil];
[self.navigationController pushViewController:aaoversikt1 animated:YES];
}
Thank You!
From first glance I would say that the problem lies within your [self.navigationController pushViewController] method. Have you initiated a navigation controller in your app either in the app delegate or root view controller?
If not i would recommend:
[self presentViewController:aaoversik1 animated:YES completion:NULL];
If you are wanting to push through the navigation stack so that you have a back button then I would look at implementing a UINaviationController.
Otherwise you can create a custom back button and use the same method in this post to present the root view controller (not totally recomended as using UINavigationController is much cleaner).
Let me know if this has been of any help, T
I am trying to connect a UITableViewController to a UIView using storyboards. I have a TabBarController that connects to a Navigation Controller that displays a UITableViewController, displaying a small array. I want to click on a row and that trigger a simple UIView with a label, still displayed in the UINavigationController so I can navigate back to the UITableViewController
I can get the UITableViewController to display OK, with the array, but I can't get the row to trigger when I select it.
This is my UITableViewController (AtoZController.m) file:
#import "AtoZController.h"
#import "StoreDetailsView.h"
#interface AtoZController ()
#end
#implementation AtoZController
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = NSLocalizedString(#"A to Z", #"An A to Z List of Stores");
AtoZArray = [[NSMutableArray alloc] init];
[AtoZArray addObject:#"Apple"];
[AtoZArray addObject:#"Boots"];
[AtoZArray addObject:#"Topman"];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
} else {
return 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 [AtoZArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
NSInteger row = [indexPath row];
cell.textLabel.text = [AtoZArray objectAtIndex:row];
return cell;
}
I have a segue connected, named storeDetailsSegue, from the UITableViewController to a UIView. I am attempting to use the prepareForSeque method to trigger the next view but have had no luck with the following code.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
StoreDetailsView *detail = [self detailForIndexPath:path];
[segue.destinationViewController setDetail:detail];
}
As it keeps saying there is an error as there is 'No visible #interface for "AtoZController declares the selector 'detailForIndexPath'". I may be doing something completely wrong as I have never used storyboards before. What I want is for a simple UIView to display a label that dynamically changes to display the row number that has been selected.
I don't know if the UITableViewController should infact be a UITableView but as I have never used segues or storyboards I have no idea what could be causing the problem.
Any advice at all would be greatly appreciated.
UPDATE:
So I managed to get the UIViewController to display but still can't get the label to update before I display the view.