I've come to the point of pulling my hair out over this one. I keep getting a EXC_BAD_ACCESS when I call the reloadData for the UITableView. I'll lay the groundwork for you here.
MainViewController.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#class iPROSAppDelegate;
#interface MainViewController : UIViewController <UIScrollViewDelegate, UITableViewDelegate, UITableViewDataSource> {
iPROSAppDelegate *parent;
...
NSMutableArray *contentSeqList;
UITableView *contentSeqTable;
}
#property (nonatomic, retain) IBOutlet iPROSAppDelegate *parent;
...
#property (nonatomic, retain) NSMutableArray *contentSeqList;
#property (nonatomic, retain) IBOutlet UITableView *contentSeqTable;
...
- (IBAction)changeMainView:(id)sender;
#end
MainViewController.m
- (IBAction)changeMainView:(id)sender{
//do logs to make sure we get here and grab an NSDictionary object from another class
NSLog(#"got to a change of main view");
NSDictionary *myContentSequences = [[parent csList] grabCSListandReturnJSON:[sender tag]];
NSLog(#"got cs list for tag %#: %#", [sender currentTitle], myContentSequences);
//set up table view
contentSeqTable = [[UITableView alloc] initWithFrame:CGRectMake(40, 20, 240, 300) style:UITableViewStyleGrouped];
contentSeqTable.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
[contentSeqTable setDelegate:self];
[contentSeqTable setDataSource:self];
NSLog(#"delegate: %#, data source: %#", [contentSeqTable delegate], [contentSeqTable dataSource]);
contentSeqList = [[NSMutableArray alloc] init];
//populate nsmutablearray contentseqlist using the nsdictionary mycontentsequences
for (id dashboard in [myContentSequences objectForKey:#"dashboards"]){
if ([dashboard objectForKey:#"error"] == nil){
for (id contentsequence in [dashboard objectForKey:#"contentSequences"]){
[contentSeqList addObject:[contentsequence objectForKey:#"name"]];
NSLog(#"added object to content sequence list: %#", [contentsequence objectForKey:#"name"]);
}
}
}
[contentSeqTable reloadData];
...
}
changeMainView is called when a button is clicked in the main view. Here are the delegate methods also for UITableView. Notice that the NSLogs are the first lines in these methods, but I get neither showing in the console log before the EXC_BAD_ACCESS.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
NSLog(#"content seq list count: %#", [contentSeqList count]);
return [contentSeqList count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"setting up the cells");
NSUInteger index = [indexPath indexAtPosition:1];
NSString *myId = #"id";
if (tableView.editing) myId = #"idE";
UILabel *name;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:myId];
if (cell == nil){
cell = [[[UITableViewCell alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 20) reuseIdentifier:myId] autorelease];
float width = 260;
if (tableView.editing) width = 240;
name = [[[UILabel alloc] initWithFrame:CGRectMake(45, 1, width, 53)] autorelease];
[name setBackgroundColor:[UIColor clearColor]];
[name setTextColor:[UIColor blackColor]];
[name setFont:[UIFont fontWithName:#"Helvetica" size: 18]];
[name setAdjustsFontSizeToFitWidth:YES];
[name setMinimumFontSize:11];
[name setNumberOfLines:2];
name.tag = 1;
[cell.contentView addSubview:name];
}
else{
name = (UILabel *)[cell.contentView viewWithTag:1];
}
if ([tableView indexPathForSelectedRow]){
if (indexPath == [tableView indexPathForSelectedRow]){
[name setTextColor:[UIColor whiteColor]];
}
else{
[name setTextColor:[UIColor blackColor]];
}
}
else{
[name setTextColor:[UIColor blackColor]];
}
[name setText:[contentSeqList objectAtIndex:index]];
return cell;
}
The delegate methods are part of the same class, MainViewController. I've also checked that the UITableView was not nil via NSLog right before reloadData. I know I have to be missing something small here. Any suggestions would be much appreciated. Thanks!
Can you show call stack when EXC_BAD_ACCESS occurs?
BTW,
NSUInteger index = [indexPath row];
is much more readable than
NSUInteger index = [indexPath indexAtPosition:1];
Related
I am using a custom framework and I need to set the subclass of my 'TableView' and 'TableViewCell' to the custom framework. I would normally do this easily with the identity inspector but since I created everything programmatically, I do not know how to do it. I am also not using storyboards. Any tips?
---edit----
TableViewController.h
#import <UIKit/UIKit.h>
#import "Tasks.h"
#import "Properties2ViewController.h"
#import "PKRevealController.h"
#import "FMMoveTableView.h"
#import "FMMoveTableViewCell.h"
#import "DetailViewController.h"
#interface ToDoTableViewController : UITableViewController <Properties2ViewControllerDelegate, UITableViewDelegate, FMMoveTableViewDataSource>
#property (strong, nonatomic) NSMutableArray *taskArray;
-(IBAction)addCell:(id)sender;
#end
TableViewController.m
#import "ToDoTableViewController.h"
#implementation ToDoTableViewController
#synthesize taskArray;
- (id)init {
self = [super initWithStyle:UITableViewStyleGrouped];
if (self) {
UINavigationItem *i = [self navigationItem];
[i setTitle:#"Task List"];
[[i title] uppercaseString];
UIBarButtonItem *bbi = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(addCell:)];
[[self navigationItem] setRightBarButtonItem:bbi];
[self.tableView setSeparatorColor:[UIColor colorWithRed:26.0/255 green:188.0/255 blue:156.0/255 alpha:1.0f]];
[self.tableView setBackgroundView:nil];
[self.tableView setBackgroundColor:[UIColor colorWithRed:26.0/255 green:188.0/255 blue:156.0/255 alpha:1.0f]];
}
return self;
}
- (id) initWithStyle:(UITableViewStyle)style{
return [self init];
}
-(void) viewDidLoad{
FMMoveTableView *mtc = [[FMMoveTableView alloc]init];
[mtc setDataSource:self];
[self.tableView setDelegate:self];
taskArray = [[NSMutableArray alloc] init];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell"];
if (!cell)
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"UITableViewCell"];
NSString *detailText = [NSString stringWithFormat:#"%.0f", [[taskArray objectAtIndex:[indexPath row]] timeInterval]];
[[cell textLabel] setText:[[taskArray objectAtIndex:[indexPath row]] taskName]];
cell.textLabel.text = [[[taskArray objectAtIndex:[indexPath row]] taskName] uppercaseString];
[[cell textLabel] setFont:[UIFont fontWithName:#"AvenirNext-DemiBold" size:15]];
[cell setBackgroundColor:[UIColor colorWithRed:236.0/255 green:240.0/255 blue:241.0/255 alpha:1.0f]];
cell.textLabel.textColor = [UIColor colorWithRed:26.0/255 green:188.0/255 blue:156.0/255 alpha:1.0f];
[[cell detailTextLabel] setText:detailText];
[[cell detailTextLabel] setFont:[UIFont fontWithName:#"Avenir-Black" size:16]];
return cell;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [taskArray count];
}
-(IBAction)addCell:(id)sender{
Properties2ViewController *pvc = [[Properties2ViewController alloc]init];
[pvc setDelegate:self];
[self presentViewController:pvc animated:YES completion:NULL];
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[[self tableView] reloadData];
}
-(void)properties2ViewControllerDidEnterPropertiesSuccesfully:(Tasks *)t{
if (![[t taskName] isEqual: #""]) {
[taskArray addObject:t];
}
[self.tableView reloadData];
}
-(void)moveTableView:(FMMoveTableView *)tableView moveRowFromIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath{
[tableView moveRowAtIndexPath:fromIndexPath toIndexPath:toIndexPath];
[tableView reloadData];
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
Tasks *task = [taskArray objectAtIndex:[indexPath row]];
DetailViewController *dvc = [[DetailViewController alloc]init];
[dvc setTestTask:task];
[[self navigationController] pushViewController:dvc animated:YES];
// PKRevealController *pkrc = [[PKRevealController alloc]initWithFrontViewController:self rightViewController:dvc options:nil];
//[pkrc showViewController:dvc animated:YES completion:NULL];
}
-(void)loadView{
[super loadView];
}
#end
If you are instantiating the UITableView yourself, just instantiate the library class instead. For example, if you said this:
UITableView *tableView = [[UITableView alloc] initWithFrame:frame
style: UITableViewStylePlain];
then do this instead:
LibraryTableView *tableView = [[LibraryTableView alloc] initWithFrame:frame
style:UITableViewStylePlain];
If LibraryTableView provides some other, more specialized initWith… method, you may need to use that instead.
If you're storing a reference to the table view in a property or instance variable, you may also want to change the type of that property or instance variable from UITableView * to LibraryTableView *.
UPDATE
I believe if you're using a UITableViewController, you can create your own table view and assign it to the controller's tableView property:
UITableViewController *tvc = ...;
tvc.tableView = [[LibraryTableView alloc] initWithFrame:frame
style:UITableViewStylePlain];
UPDATE 2
In your viewDidLoad, you're creating an FMMoveTableView, but you're not storing it in the view controller's tableView property. You must store it in the view controller's tableView property, and when you do, the view controller will automatically set the table view's dataSource and delegate to self.
-(void) viewDidLoad{
self.tableView = [[FMMoveTableView alloc] init];
taskArray = [[NSMutableArray alloc] init];
}
In your tableView:cellForRowAtIndexPath:, you need to instantiate an FMMoveTableViewCell, not a UITableViewCell. You send the alloc message to the class you want to instantiate:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (!cell) {
cell = [[FMMoveTableViewCell alloc]
initWithStyle:UITableViewCellStyleValue1
reuseIdentifier:#"Cell"];
}
// etc.
If you have your own custom subclass of FMMoveTableViewCell, instantiate that instead.
I have created custom TableViewCells before, you can create a custom class just like you would for viewControllers (File > New > File). When choosing which object to subclass, choose UITableViewCell.
Unfortunately, Xcode will not give you the option to include a .xib file, so you'll have to create one of those too: File > New > File, but this time on the left side of the window that pops up, select 'User Interface' instead of 'Cocoa Touch'. Choose the 'Empty' icon at this screen.
You will be asked whether the device family is iPhone or iPad. Since you are making a table view cell not a viewController, it doesn't matter which you pick.
When you create this object you will be presented with a blank canvas. Drag a 'Table View Cell' from the object library to the canvas and you're set to start creating!
It is of note that where you'd normally create outlets, you should create properties for TableViewCells. This is because other objects are going to be interacting with the TableViewCell, not just the TableViewCell's implementation file.
Here is what a header file for a custom TableViewCell might look like:
#interface MyCustomCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UIImageView *icon;
#property (weak, nonatomic) IBOutlet UILabel *label;
#property (weak, nonatomic) IBOutlet UILabel *number;
#end
My implementation file was empty.
However, that's not all. There is also some work to be done in the TableViewController that will utilize this cell. Be sure to import your TableViewCell's header file.
First, the cell has to be registered in the viewDidLoad method
// Resiter the Nib
UINib *nib = [UINib nibWithNibName:#"MyCustomCell" bundle:nil];
[[self tableView] registerNib:nib forCellReuseIdentifier:#"MyCustomCell"];
And then when the TableViewController determines how to draw the cells:
- (UITableViewCell *) tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyCustomCell"]
// Then here you can set the properties of each cell
[[cell label] setText:#"Some text here"];
[[cell number] setText:[NSString stringWithFormat:#"%d", 5]];
[[cell icon] setImage:[UIImage imageNamed:#"myImage]];
}
I hope this is helpful!
I updated my xcode using 6.1 simulator, my app was working fine for 5.1 simulator,
now i am getting the following error :
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UITableViewController loadView] loaded the "MySubscriptionsViewController" nib but didn't get a UITableView.'
my header file:
#import <UIKit/UIKit.h>
#interface MySubscriptionsViewController : UITableViewController{
}
#property (nonatomic,retain) NSString *serverAddress;
#property (nonatomic, retain) UITextField *airportField;
#property (nonatomic, retain) NSMutableArray *airportList;
#property (nonatomic, retain) NSMutableArray *colCode;
#property (nonatomic, retain) NSMutableArray *colAirport;
#property (nonatomic, retain) NSMutableArray *colStartDate;
#property (nonatomic, retain) NSMutableArray *colStartTime;
#property (nonatomic, retain) NSMutableArray *colEndTime;
#property (nonatomic, retain) NSMutableDictionary *tempAirport;
#property (nonatomic,strong) NSDictionary *countryList;
#property (nonatomic,strong) NSArray *countryKeys;
- (IBAction)Meetup:(id)sender;
- (IBAction)ViewBeacon:(id)sender;
-(IBAction)gotoHome:(id)sender;
-( void)beacon:(NSString *)theStr;
#end
my m file:
#import "MySubscriptionsViewController.h"
#import "MybeaconsViewController.h"
#import "SBJsonParser.h"
#import "GridTableViewCell.h"
#import "MeetupViewController.h"
#import "ViewBeaconViewController.h"
#import "DataClass.h"
#import "MemberPanelViewController.h"
#interface MySubscriptionsViewController ()
#end
#implementation MySubscriptionsViewController
#synthesize countryList,countryKeys,serverAddress,airportField,airportList,tempAirport,colStartTime,colEndTime,colStartDate,colAirport,colCode;
- (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];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0,0);
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
DataClass *obj=[DataClass getInstance];
// serverAddress = #"http://www.cloudnetpk.com/transbeacon_design/services";
NSString *strURL = [NSString stringWithFormat:#"http://www.cloudnetpk.com/transbeacon_design/services/get_my_beacon_subscriptions.php?code=%#",obj.str];
NSLog(#" url => %#",strURL);
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]];
NSString *strResult = [[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding];
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSArray *datos = [parser objectWithString:strResult error:nil];
tempAirport = [[NSMutableDictionary alloc] init];
airportList = [[NSMutableArray alloc] init];
colStartTime = [[NSMutableArray alloc] init];
colEndTime = [[NSMutableArray alloc] init];
colStartDate= [[NSMutableArray alloc] init];
colAirport= [[NSMutableArray alloc] init];
colCode= [[NSMutableArray alloc] init];
countryList = datos;
NSLog(#"beacons count %d",datos.count);
for (int i=0; i<datos.count; i++){
int a=0;
NSString *startDate = [[[datos objectAtIndex:i] objectForKey:#"start_date" ] lowercaseString];
NSString *airPort= [[[datos objectAtIndex:i] objectForKey:#"airport" ] lowercaseString];
NSString *startTime = [[[datos objectAtIndex:i] objectForKey:#"start_time" ] lowercaseString];
NSString *endTime = [[[datos objectAtIndex:i] objectForKey:#"end_time" ] lowercaseString];
NSString *code = [[[datos objectAtIndex:i] objectForKey:#"code" ] lowercaseString];
//NSLog(#" here =>%#",code);
[colStartDate insertObject:startDate atIndex:i ];
[colAirport insertObject:airPort atIndex:i ];
[colStartTime insertObject:startTime atIndex:i ];
[colEndTime insertObject:endTime atIndex:i ];
[colCode insertObject:code atIndex:i];
//[ tempAirport setObject:lcString forKey:lcStringValue];
}
[super viewDidLoad];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [countryList count];
}
/*
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell =[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"cell"];
NSString *currentCountryName=[countryKeys objectAtIndex:[indexPath row]];
[[cell textLabel] setText:currentCountryName];
//cell.detailTextLabel.text=#"testing here ";
return cell;
}
*/
-(UITableViewCell *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
static NSString *CellIdentifier = #"SectionHeader";
//UITableViewCell *headerView = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(10,0,300,60)] ;
UIImage *myImage=[UIImage imageNamed:#"top_bar.png"];
UIImageView *imageView =[[UIImageView alloc] initWithImage:myImage];
imageView.frame= CGRectMake(0, 0, 400, 50);
[headerView addSubview:imageView];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(110,3, tableView.bounds.size.width - 170,40)];
label.text = #"Subscriber List";
label.textColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1];
label.font = [UIFont fontWithName:#"Arial-BoldMT" size:16];
label.backgroundColor = [UIColor clearColor];
[headerView addSubview:label];
UIButton *circularButton = [UIButton buttonWithType:UIButtonTypeCustom];
CGRect circularRect = CGRectMake(5.0, 5, 58.0, 32.0);
[circularButton setFrame:circularRect];
[circularButton addTarget:self action:#selector(Meetup:) forControlEvents:UIControlEventTouchUpInside];
UIImage *buttonImage = [UIImage imageNamed:#"back_btn.png"];
[circularButton setImage:buttonImage forState:UIControlStateNormal];
[headerView addSubview:circularButton];
UIButton *homeButton = [UIButton buttonWithType:UIButtonTypeCustom];
CGRect circularRectHome = CGRectMake(250.0, 5, 58.0, 32.0);
[homeButton setFrame:circularRectHome];
[homeButton addTarget:self action:#selector(gotoHome:) forControlEvents:UIControlEventTouchUpInside];
UIImage *buttonImageHome = [UIImage imageNamed:#"home_btn.png"];
[homeButton setImage:buttonImageHome forState:UIControlStateNormal];
[headerView addSubview:homeButton];
return headerView;
}
-(IBAction)gotoHome:(id)sender{
// redirect
MemberPanelViewController *window =[[MemberPanelViewController alloc]init];
[self presentModalViewController:window animated:YES];
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
return 50;
}
- (IBAction)Meetup:(id)sender{
NSLog(#" button clicked here");
MeetupViewController *window =[[MeetupViewController alloc]init];
[self presentModalViewController:window animated:YES];
}
- (IBAction)ViewBeacon:(id)sender{
ViewBeaconViewController *window=[[ViewBeaconViewController alloc]init];
[self presentModalViewController:window animated:YES];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
GridTableViewCell *cell = (GridTableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[GridTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.lineColor = [UIColor blackColor];
}
// Since we are drawing the lines ourself, we need to know which cell is the top cell in the table so that
// we can draw the line on the top
if (indexPath.row == 0)
cell.topCell = YES;
else
cell.topCell = NO;
// Configure the cell.
//cell.cell1.text = [NSString stringWithFormat:#"%i",indexPath.row];
//cell.cell2.text = [NSString stringWithFormat:#"%i", indexPath.row];
//cell.cell3.text = #"test here text";
cell.cell1.text =[colStartDate objectAtIndex:indexPath.row];
cell.cell2.text =[colAirport objectAtIndex:indexPath.row];
cell.cell3.text =[colStartTime objectAtIndex:indexPath.row];
cell.cell4.text = [colEndTime objectAtIndex:indexPath.row];
NSString *value = [colCode objectAtIndex:indexPath.row];
NSLog(#" value => %#",value);
UIButton *circularButton = [UIButton buttonWithType:UIButtonTypeCustom];
CGRect circularRect = CGRectMake(260.0, 2, 60.0, 40.0);
[circularButton setFrame:circularRect];
[circularButton addTarget:self action:#selector(beacon:) forControlEvents:UIControlEventTouchUpInside];
circularButton.tag=value;
UIImage *buttonImage = [UIImage imageNamed:#"view.png"];
[circularButton setImage:buttonImage forState:UIControlStateNormal];
[cell.contentView addSubview:circularButton];
return cell;
}
-( void)beacon:(NSString *)theStr{
NSInteger *tid = ((UIControl*)theStr).tag;
NSLog(#" here is parameter %#",tid);
ViewBeaconViewController *window=[[ViewBeaconViewController alloc]init];
// window.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
window.theDataYouWantToPass =tid;
window.lastscreen =#"subscription";
[self presentModalViewController:window animated:YES];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
*/
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UITableViewController loadView] loaded the "MySubscriptionsViewController" nib but didn't get a UITableView.' This error Ocurce becouse some bellow issue.
I think the problem is because you are subclassing UITableViewController instead of UIViewController.
you need to put UIViewController as a subclass and connect IBoutlet of UITableview in XIB with its delegare. your TableVIew in UIView of XIB so you just connect fileOWner to UIView as a View and UITableview with your TableView Outlate.
#interface MySubscriptionsViewController : UIViewController<UITableViewDelegate, UITableViewDataSource>
OR
else there you remaining some referance of old copy you trying with restart xcode and remove catch or clean derive data
I just had the same issue; I fixed it by subclassing my newly created viewController file.
I was subclassing my newly created tableView file by mistake.
Or
If you want the table view to be the root view in your initial view (it will fill up the whole screen with cells) then you will delete the view in the project outline. second you will control drag the table view in the project outline to the menu (above it) and then you will click delegate for the outlet and do the same for the data source. finally you will open the table view controller file and add UITableViewDelegate and UITableViewDataSource so that it looks like this (using your created name of course).
class MainMenuTableViewController: UITableViewController, UITableViewDelegate, UITableViewDataSource
Hope this helps.
I can't get my first UITableView to update with a setting made in a second UITableView.
A user clicks a row in firstTableView causing secondTableView to be displayed. When the user selects a row, secondTableView disappears and firstTableView is reappears. However, the data isn't updated.
I tried using the following in firstTableView:
- (void) viewWillAppear:(BOOL)animated {
// (verified it's defenitely section 2, row 0 by logging it before and after...)
// (also verified that the source data has been updated before viewWillAppear is called...)
NSIndexPath *durPath = [NSIndexPath indexPathForRow:0 inSection:2];
NSArray *paths = [NSArray arrayWithObject:durPath];
[self.firstTableView reloadRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationNone];
// If I use some row animation, I can clearly see that the correct row is being animated, it's just not being updated.
}
But the label does not update. Obviously I'm missing something.
Both views are modal view controllers.
Here's my cell construction:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [firstTableView dequeueReusableCellWithIdentifier:CellIdentifier];
UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(150.0, 15.0, 120.0, 17.0)];
myLabel.backgroundColor = [UIColor clearColor];
myLabel.font = [UIFont systemFontOfSize:14];
myLabel.textAlignment = UITextAlignmentLeft;
static NSString* kConstants[] = {kOption0,kOption1,kOption2,kOption3,kOption4,kOption5,kOption6,kOption7,kOption8,kOption9,kOption10,nil};
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
if (indexPath.section == 2) {
[cell addSubview:myLabel];
}
}
switch (indexPath.section) {
case 0:
// … deal with a bunch of UISwitches
break;
case 1:
// … deal with section 1 stuff
break;
case 2:
{
NSLog(#"Verify that intType has in fact been changed here: %i, %#",intType, kConstants[intType]);
// Even though intType and the constant string reflects the correct (updated) values when returning from secondTableView, myLabel.text does not change, ie: it's correct one line above, but not correct one line below. The myLabel.text is just not updating to the new value.
myLabel.text = kConstants[intType];
cell.textLabel.text = #"Choose Some Value:";
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
}
break;
case 3:
// … deal with section 3 stuff
break;
}
[myLabel release];
return cell;
}
I have finally found the problem: when you reload the cell, (cell == nil) will be false, since the cell is already present.
Also, even if (cell == nil) is true, you are adding a new subview, and not modifying the existing one -- which is not only a memory management problem, it also makes the text unreadable by placing the labels on top of each other.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
static NSString* kConstants[] = {kOption0,kOption1,kOption2,kOption3,kOption4,kOption5,kOption6,kOption7,kOption8,kOption9,kOption10,nil};
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(150.0, 15.0, 120.0, 17.0)];
myLabel.backgroundColor = [UIColor clearColor];
myLabel.font = [UIFont systemFontOfSize:14];
myLabel.textAlignment = UITextAlignmentLeft;
myLabel.tag = 1;
myLabel.text = kConstants[intType];
[cell addSubview:myLabel];
[myLabel release];
cell.textLabel.text = #"Label";
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
} else {
UILabel *myLabel = (UILabel *)[cell viewWithTag:1];
myLabel.text = kConstants[intType];
}
return cell;
}
For anyone who stumbles upon this in the future, I'm posting a complete solution to my question here, thanks especially to Antal for showing me the major error in my table construction.
Using ViewWillAppear to reload the table is a bad idea in general, because it causes the table, or portions of the table to load twice. The proper way to do this is using the Delegate method of the second view controller, which I've done here.
I'm posting the relevant portions of the two view controllers. Both are setup as UViewControllers, not as UITableViewControllers. Both are modal views.
I hope someone finds this useful.
//
// FirstViewController.h
//
#import <UIKit/UIKit.h>
#import "SecondViewController.h"
#interface FirstViewController : UIViewController
<SecondViewControllerDelegate, UITableViewDataSource, UITableViewDelegate>
{
UITableView *firstTableView;
NSArray *myArray;
}
#property (nonatomic, retain) IBOutlet UITableView *firstTableView;
#property (nonatomic, assign) NSArray *myArray;
- (void) didSelectOptions:(NSInteger *)intOptionType;
- (void) didCancelOptions;
#end
//
// FirstViewController.m
//
#import "FirstViewController.h"
#import "Constants.h"
#implementation FirstViewController
#synthesize firstTableView;
#synthesize myArray;
- (void) viewDidLoad {
// Load the array that contains the option names, in this case, constants stored in Constants.h
myArray = [[NSArray alloc] initWithObjects:kStoredRowName0, kStoredRowName1, kStoredRowName2, nil];
}
// do everything else to deal with the first view . . .
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Use the indexPath.section as the identifier since objects in each section share unique construction, ie: switches, etc.
NSString *identifier = [NSString stringWithFormat: #"%d", [indexPath indexAtPosition: 0]];
// In this example I'm storing the important integer value in NSUserDefaults as kStoredConstant
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
UITableViewCell *cell = [firstTableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle: UITableViewCellStyleDefault
reuseIdentifier:identifier]
autorelease];
switch (indexPath.section) {
case 0: // OnOff Controls using UISwitch
NSLog(#"Section 0");
// set up switches …
break;
case 1: // Segmented Controls using UISegmentedControl
NSLog(#"Section 1");
// set up segmented controls …
break;
case 2: // Label that will be selected from SecondViewContoller
NSLog(#"Section 2");
// set up label
UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(150.0, 15.0, 120.0, 17.0)];
myLabel.backgroundColor = [UIColor clearColor];
myLabel.font = [UIFont systemFontOfSize:14];
myLabel.textColor = [UIColor colorWithRed:0.25 green:0.0 blue:0.0 alpha:1.0];
myLabel.textAlignment = UITextAlignmentLeft;
myLabel.tag = indexPath.section;
myLabel.text = [myArray objectAtIndex:[userDefaults integerForKey:kStoredConstant]];
[cell addSubview:myLabel];
[myLabel release];
cell.textLabel.text = #"Choose A Value:";
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
break;
}
} else {
switch (indexPath.section) {
case 0: // OnOff Controls using UISwitch
NSLog(#"Section 0");
break;
case 1: // Segmented Controls using UISegmentedControl
NSLog(#"Section 1");
break;
case 2: // Label that will be selected from SecondViewContoller
{
NSLog(#"Section 2");
UILabel *myLabel = (UILabel *)[cell viewWithTag:indexPath.section];
myLabel.text = [myArray objectAtIndex:[userDefaults integerForKey:kStoredConstant]];
}
break;
}
}
// Format the cell label properties for all cells
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.textLabel.font = [UIFont systemFontOfSize:14];
cell.textLabel.textColor = [UIColor colorWithRed:0.25 green:0.0 blue:0.0 alpha:1.0];
cell.textLabel.highlightedTextColor = [UIColor colorWithRed:1.0 green:1.0 blue:0.9 alpha:1.0];
return cell;
}
- (void) tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
// Un-highlight the selected cell
[firstTableView deselectRowAtIndexPath:indexPath animated:YES];
switch (indexPath.section) {
case 0: // Deal with changes in UISwitch Controls
NSLog(#"Section 0");
break;
case 1: // Deal with changes in Segmented Controls
NSLog(#"Section 1");
break;
case 2: // Launch the SecondViewContoller to select a value
{
SecondViewController *secondViewController = [[SecondViewController alloc] init];
secondViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
secondViewController.secondViewControllerDelegate = self;
[self presentModalViewController:secondViewController animated:YES];
[secondViewController release];
}
break;
}
}
#pragma mark -
#pragma mark SecondViewControllerDelegate
- (void) didSelectOptions:(NSInteger *)intOptionType {
// User selected a row in secondTableView on SecondViewController, store it in NSUserDefaults
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setInteger:(int)intOptionType forKey:kStoredConstant];
[userDefaults synchronize];
// Reload only the row in firstTableView that has been changed, in this case, row 0 in section 2
[self.firstTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:2]]withRowAnimation:UITableViewRowAnimationNone];
[self dismissModalViewControllerAnimated:YES];
}
- (void) didCancelOptions {
// User didn't select a row, instead clicked a done or cancel button on SecondViewController
[self dismissModalViewControllerAnimated:YES];
}
// Make sure and release Array and Table
//
// SecondViewController.h
//
#import <UIKit/UIKit.h>
#protocol SecondViewControllerDelegate <NSObject>
- (void) didCancelOptions;
- (void) didSelectOptions:(NSInteger *)optionType;
#end
#interface SecondViewController : UIViewController
<UITableViewDataSource, UITableViewDelegate>
{
NSArray *myArray;
UITableView *secondTableView;
id secondViewControllerDelegate;
}
#property (nonatomic, retain) NSArray *myArray;
#property (nonatomic, retain) IBOutlet UITableView *secondTableView;
#property (nonatomic, assign) id<SecondViewControllerDelegate> secondViewControllerDelegate;
- (IBAction) doneViewingOptions:(id)sender; // This is wired to a Cancel or a Done Button
#end
//
// SecondViewController.m
//
#import "SecondViewController.h"
#import "Constants.h"
#implementation SecondViewController
#synthesize secondViewControllerDelegate;
#synthesize myArray;
#synthesize secondTableView;
- (void) viewDidLoad {
// Load the array that contains the option names, in this case, constants stored in Constants.h
myArray = [[NSArray alloc] initWithObjects:kStoredRowName0, kStoredRowName1, kStoredRowName2, nil];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Build a default table. This one is simple so the following is the only important part:
cell.textLabel.text = [myArray objectAtIndex:indexPath.row];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Return the changed row value to the FirstViewController using secondViewControllerDelegate
[self.secondViewControllerDelegate didSelectOptions:(NSInteger *)indexPath.row];
}
- (IBAction) doneViewingOptions:(id)sender {
// User didn't select a row, just clicked Done or Cancel button
[self.secondViewControllerDelegate didCancelOptions];
}
// Make sure and release Array and Table
You can use reloadRowsAtIndexPaths to reload a specific row (or rows) and avoid having to reload the entire table.
As for the label that displays the string value, could you post the code so we can see?
I am quite new to IOS development, so forgive me if this problem turns out to be trivial. The following is the case:
I want to be able to call the didSelectRowAtIndexPath method to trigger some action when a user interacts with a table view cell. However, it seems that this method is never called for some reason. I am fairly certain that my code is valid. I set the delegate and dataSource properties and I conform to the UITableViewDelegate and UITableViewDataSource protocols.
If someone could shed some light on this, I would be very grateful.
My code:
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
#class Employee;
#define kTelephoneRowIndex 0
#define kEmailRowIndex 1
#define kLeftLabelTag 4096
#define kRightLabelTag 4097
#interface PersonnelDetailsViewController : UIViewController <UITableViewDelegate,
UITableViewDataSource, MFMailComposeViewControllerDelegate> {
UITableView *contactDetailsTable;
Employee *employee;
}
#property (nonatomic, retain) UITableView *contactDetailsTable;
#property (nonatomic, retain) Employee *employee;
+ (NSString *)resourceFilePath:(NSString *)fileName ofType:(NSString *)type;
#end
and my .m file
#import <QuartzCore/QuartzCore.h>
#import "PersonnelDetailsViewController.h"
#import "Employee.h"
#implementation PersonnelDetailsViewController
#synthesize contactDetailsTable, employee;
+ (NSString *)resourceFilePath:(NSString *)fileName ofType:(NSString *)type {
return [[NSBundle mainBundle] pathForResource:fileName ofType:type];
}
- (void)loadView {
[super loadView];
// Create the header view for the table view
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 110)];
// Set the image, using rounded corners
UIImage *employeeImage;
if ([employee.image length] == 0)
employeeImage = [UIImage imageNamed:#"logoL1nda70by80"];
else
employeeImage = [UIImage imageNamed:employee.image];
UIImageView *employeeImageView = [[UIImageView alloc] initWithImage:employeeImage];
employeeImageView.frame = CGRectMake(10, 15, 70, 80);
employeeImageView.layer.masksToBounds = YES;
employeeImageView.layer.cornerRadius = 5.0;
employeeImageView.layer.borderWidth = 1.0;
employeeImageView.layer.borderColor = [[UIColor grayColor] CGColor];
[headerView addSubview:employeeImageView];
UILabel *nameView = [[UILabel alloc] initWithFrame:CGRectMake(95, 35, 180, 20)];
nameView.text = employee.name;
nameView.font = [UIFont boldSystemFontOfSize:18];
[headerView addSubview:nameView];
UILabel *functionView = [[UILabel alloc] initWithFrame:CGRectMake(95, 55, 140, 16)];
functionView.text = employee.function;
functionView.textColor = [UIColor grayColor];
functionView.font = [UIFont systemFontOfSize:14];
[headerView addSubview:functionView];
[employeeImage release];
[employeeImageView release];
[nameView release];
[functionView release];
contactDetailsTable = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 370) style: UITableViewStyleGrouped];
contactDetailsTable.backgroundColor = [UIColor clearColor];
contactDetailsTable.tableHeaderView = headerView;
[headerView release];
contactDetailsTable.delegate = self;
contactDetailsTable.dataSource = self;
[self.view addSubview:contactDetailsTable];
}
- (void)viewDidUnload {
self.contactDetailsTable = nil;
self.employee = nil;
[super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated {
[contactDetailsTable reloadData];
}
- (void)dealloc {
[contactDetailsTable release];
[employee release];
[super dealloc];
}
#pragma mark -
#pragma mark Table View Data Source Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 2;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;did
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *contactDetailIdentifier = #"contactDetailIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:contactDetailIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:contactDetailIdentifier] autorelease];
UILabel *leftLabel = [[UITextField alloc] initWithFrame:CGRectMake(5, 12, 70, 25)];
leftLabel.textAlignment = UITextAlignmentRight;
leftLabel.textColor = [UIColor grayColor];
leftLabel.tag = kLeftLabelTag;
leftLabel.userInteractionEnabled = NO;
[cell.contentView addSubview:leftLabel];
[leftLabel release];
UILabel *rightLabel = [[UITextField alloc] initWithFrame:CGRectMake(90, 12, 160, 25)];
rightLabel.font = [UIFont boldSystemFontOfSize:16];
rightLabel.tag = kRightLabelTag;
rightLabel.userInteractionEnabled = NO;
[cell.contentView addSubview:rightLabel];
[rightLabel release];
}
NSUInteger row = [indexPath row];
UILabel *leftLabel = (UILabel *)[cell viewWithTag:kLeftLabelTag];
UILabel *rightLabel = (UILabel *)[cell viewWithTag:kRightLabelTag];
switch (row) {
case kTelephoneRowIndex:
leftLabel.text = #"telefoon";
rightLabel.text = employee.phone;
break;
case kEmailRowIndex:
leftLabel.text = #"e-mail";
rightLabel.text = employee.email;
break;
default:
break;
}
return cell;
}
#pragma mark -
#pragma mark Table View Delegate Methods
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
return nil;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = indexPath.row;
if (row == 1) {
MFMailComposeViewController *mailController = [[MFMailComposeViewController alloc] init];
[mailController setToRecipients:[NSArray arrayWithObject:employee.email]];
[mailController.navigationBar setTintColor:[UIColor blackColor]];
[self presentModalViewController:mailController animated:YES];
mailController.mailComposeDelegate = self;
[mailController release];
}
NSLog(#"Row selected is: %d", row);
}
#pragma mark -
#pragma mark MFMailCompose View Delegate Methods
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
[self dismissModalViewControllerAnimated:YES];
}
#end
Check the doc for tableView:willSelectRowAtIndexPath::
Return an NSIndexPath object other than indexPath if you want another cell to be selected. Return nil if you don't want the row selected.
You are returning nil, basically saying the table view that you don't want that row selected. Therefore tableView:didSelectRowAtIndexPath: is not called.
When I had this problem I found the solution was to use willSelectRowAtIndexPath. In other places in the same project didSelectItemAtIndexPath is getting called fine.
#pragma mark - UITableViewDelegate
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// for some reason this is getting called instead of didSelectItemAtIndexPath
[self viewDetails:indexPath.row];
return indexPath;
}
- (void)tableView:(UITableView *)tableView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
// [self viewDetails:indexPath.row];
}
i have try the label value pass one view to another view .i have use the table view and table view put a label . code......
such as
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:#"%i %i",indexPath.row,indexPath.section];
UITableViewCell *cell =[self.tableViewdequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryNone;
NSMutableArray *arr=[NSMutableArray arrayWithArray:[finalArray objectAtIndex:indexForAll]];
NSLog(#"-=-= arr count %d -=-====",[arr count]);
NSLog(#"%#",[[arr objectAtIndex:indexPath.row]description]);
NSLog(#"-====== row value %d -=======",indexPath.row);
NSLog(#"--=-=--- strike value %#",[[arr objectAtIndex:indexPath.row]valueForKey:#"Strike"]);
//indexForAll=indexPath.row
cell.accessoryType = UITableViewCellAccessoryNone;
cell.highlighted = YES;
NSMutableArray *arr2=[NSMutableArray arrayWithArray:[arr objectAtIndex:indexPath.row]];
NSLog(#" -=-=-=-= Arr2 value : %d ",[arr2 count]);
NSLog(#"%#",[arr2 description]);
//.......................................Strike value.....................................//
UILabel *label1;
label1 =[[UILabel alloc]initWithFrame:CGRectMake(10, 3,50, 15)];
NSLog(#"-=-=--= lable1 value -%#",[[arr2 objectAtIndex:0]valueForKey:#"Strike"]);
[label1 setText:[NSString stringWithFormat:#"%#",
[[arr2 objectAtIndex:0]valueForKey:#"Strike"]]];
label1.textAlignment = UITextAlignmentCenter;
[label1 setFont:[UIFont fontWithName:#"Helvetica" size:12]];
[label1 setTextColor:[UIColor blackColor]];
[cell.contentView addSubview:label1];
NSLog(#"lable1 addded");
[self.tableView reloadData];
i have want to label1 value fetch another view.i have trid but even not success .if any helped
thanks
i have tried
such
AppDelegate_iPhone *appDelegate = (AppDelegate_iPhone *)[[UIApplication sharedApplication] delegate];
but value not pass.
Code for CurrentViewControllerHavingTableView
Hi try making a property of your UILabel and synthesize it in the .m file
#property (nonatomic,retain) UILabel *label1;
#synthesize label1;
Now make an object of your current view in the calling class like this
Code for Calling Class
CurrentViewControllerHavingTableView *viewController = [[CurrentViewControllerHavingTableView alloc] initWithNibName:#"CurrentViewControllerHavingTableView" bundle:[NSBundle mainBundle]];
Make a UILabel *label2;
label2.textlabel.text=viewController.label1.textlabel.text;
This will surely work for you.
Make a Nstring type property in appDeleagate suppose NSString *labelText;
and now
AppDelegate_iPhone *appDelegate = (AppDelegate_iPhone *)[[UIApplication sharedApplication] delegate];
In this class where you set this property.
Now before this line
--->[label1 setText:[NSString stringWithFormat:#"%#", [[arr2 objectAtIndex:0]valueForKey:#"Strike"]]];
set that property of appDelegate.
appDelegate.labelText=[NSString stringWithFormat:#"%#", [[arr2 objectAtIndex:0]valueForKey:#"Strike"]];
And now where you want to use this property make object of appDelegate and access this property by using . operator.
This will definately help you if you implement in correct way.