Can anybody tell me how to create a tableview
with two cells by colums in the Iphone SDK??
order in like this :
_____________
| 1 | 2 |
|_____|______|
| 3 | 4 |
|_____|______|
Best regards
In ios UITableView you can only have one column/cell. If you want more propertyes, in a same cell you need to create a custom table view cell by subcalssing UITableViewCell. In interface builder you can customize the layout. TUTORIAL: http://adeem.me/blog/2009/05/30/iphone-sdk-tutorial-part-6-creating-custom-uitableviewcell-using-interface-builder-uitableview/
Concrete example for your problem:
the .h file:
#import <UIKit/UIKit.h>
#interface MyCell : UITableViewCell {
UIButton * column1;
UIButton * column2;
UILabel* column1_label1;
UILabel* column1_label2;
UILabel* column2_label1;
UILabel* column2_label2;
}
#property (nonatomic,retain) UIButton * column1;
#property (nonatomic,retain) UIButton * column2;
#property (nonatomic,retain) UILabel* column1_label1;
#property (nonatomic,retain) UILabel* column1_label2;
#property (nonatomic,retain) UILabel* column2_label1;
#property (nonatomic,retain) UILabel* column2_label2;
#end
the .m file:
#import "MyCell.h"
#implementation MyCell
#synthesize column1,column1_label1,column1_label2,column2,column2_label1,column2_label2;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
column1 = [UIButton buttonWithType: UIButtonTypeCustom];
column1.tag = 1;
column1.autoresizingMask = 292;
column1.backgroundColor = [UIColor redColor];
column1.frame = CGRectMake(0, 0, self.contentView.bounds.size.width/2, self.contentView.bounds.size.height);
column1_label1 = [[UILabel alloc] initWithFrame: CGRectMake(column1.bounds.size.width*1/5,
0,
column1.bounds.size.width*4/5,
column1.bounds.size.height/2)];
column1_label1.backgroundColor = [UIColor redColor];
[column1 addSubview:column1_label1];
column1_label2 = [[UILabel alloc] initWithFrame: CGRectMake(column1.bounds.size.width*1/5,
column1.bounds.size.height/2,
column1.bounds.size.width*4/5,
column1.bounds.size.height/2)];
column1_label2.backgroundColor = [UIColor greenColor];
[column1 addSubview:column1_label2];
[self.contentView addSubview: column1];
column2 = [UIButton buttonWithType: UIButtonTypeCustom];
column2.tag = 2;
column2.autoresizingMask = 292;
column2.backgroundColor = [UIColor greenColor];
column2.frame = CGRectMake(self.contentView.bounds.size.width/2, 0, self.contentView.bounds.size.width/2, self.contentView.bounds.size.height);
column2_label1 = [[UILabel alloc] initWithFrame: CGRectMake(column2.bounds.size.width*1/5,
0,
column2.bounds.size.width*4/5,
column2.bounds.size.height/2)];
column2_label1.backgroundColor = [UIColor redColor];
[column2 addSubview:column2_label1];
column2_label2 = [[UILabel alloc] initWithFrame: CGRectMake(column2.bounds.size.width*1/5,
column2.bounds.size.height/2,
column2.bounds.size.width*4/5,
column2.bounds.size.height/2)];
column2_label2.backgroundColor = [UIColor greenColor];
[column2 addSubview:column2_label2];
[self.contentView addSubview: column2];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)dealloc
{
[super dealloc];
}
#end
the usage in UITableViewController:
- (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 40;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
MyCell * mycell2 = ((MyCell*)cell);
if (cell == nil) {
cell = [[[MyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
[mycell2.column1 addTarget:self action:#selector(column1Selected:) forControlEvents:UIControlEventTouchUpInside];
[mycell2.column2 addTarget:self action:#selector(column1Selected:) forControlEvents:UIControlEventTouchUpInside];
}
// Configure the cell...
mycell2.column1_label1.text = #"column1_label1";
mycell2.column1_label2.text = #"column1_label2";
mycell2.column1.tag = indexPath.row*2;
mycell2.column2_label1.text = #"column2_label1";
mycell2.column2_label2.text = #"column2_label2";
mycell2.column2.tag = indexPath.row*2 +1;
return cell;
}
- (void) column1Selected: (id) sender
{
UIAlertView *alert = [[ UIAlertView alloc]
initWithTitle: #" Alert"
message: [NSString stringWithFormat: #"button %d",((UIButton *) sender).tag]
delegate: nil
cancelButtonTitle: #" OK"
otherButtonTitles: nil];
[alert show] ;
[alert release];
}
In iOS6 you can use the UICollectionView.
If you need iOS5 support AQGridView is a grid control that will give you what you are after.
Related
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 have an app which has a UITableView that uses custom cells, which I created a new class for, CustomCell. A new cell is created every time a press a certain button, and every cell has a UITextField. I want to know how do I make the UITextField in a cell resign first responder after I tap it. Keep in mind that it is initialised in another class, called CustomCell.
UIViewController code:
- (void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
}
-(void)dismissKeyboard{
}
(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier= #"Cell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
if (indexPath.row%2==0){
n=1;
cell.inOut.text = [NSString stringWithFormat:#"Entrada %d:", indexPath.row/2 +1];
cell.entryTime.text = [NSString stringWithFormat:#"%#", [_entryArray objectAtIndex:(indexPath.row+2)]];
if (indexPath.row==0){
cell.delta.text=#"";
}
else {
cell.delta.text = [_timeSinceLastEntryArray objectAtIndex:indexPath.row];
}
}
else{
cell.inOut.text = [NSString stringWithFormat:#"SaĆda %d:", (indexPath.row+1)/2];
cell.entryTime.text = [NSString stringWithFormat:#"%#",[_entryArray objectAtIndex:(indexPath.row+2)]];
cell.delta.text = [_timeSinceLastEntryArray objectAtIndex:indexPath.row];
if (whichButton==YES){}
else{
}
n=2;
}
if( [indexPath row] % 2)
[cell setBackgroundColor:[UIColor whiteColor]];
else
[cell setBackgroundColor:[UIColor lightGrayColor]];
return cell;
}
CustomCell.h code:
#interface CustomCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UITextField *inOut;
#property (strong, nonatomic) IBOutlet UILabel *entryTime;
#property (strong, nonatomic) IBOutlet UILabel *delta;
- (void) dismissInOutKeyboard;
#end
CustomCell.m code:
#implementation CustomCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
_inOut = [[UITextField alloc]init];
_entryTime = [[UILabel alloc]init];
_delta = [[UILabel alloc]init];
[self.contentView addSubview:_entryTime];
[self.contentView addSubview:_inOut];
[self.contentView addSubview:_delta];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#synthesize inOut=_inOut, entryTime=_entryTime, delta=_delta;
- (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier]) {
// Initialization code
_inOut = [[UITextField alloc]init];
_inOut.textAlignment = UITextAlignmentLeft;
_entryTime = [[UILabel alloc]init];
_entryTime.textAlignment = UITextAlignmentLeft;
_delta = [[UILabel alloc]init];
_delta.textAlignment = UITextAlignmentLeft;
[self.contentView addSubview:_entryTime];
[self.contentView addSubview:_inOut];
[self.contentView addSubview:_delta];
}
return self;
}
#end
Simply call findAndResignFirstResponder for the top-most view you have , i.e. UIViewController.view
Declaration:
#interface UIView (findAndResignFirstResponder)
- (void)findAndResignFirstResponder;
- (UIView *)findFirstResponder;
#end
Definition:
#implementation UIView (findAndResignFirstResponder)
- (void)findAndResignFirstResponder {
[self.findFirstResponder resignFirstResponder];
}
- (UIView *)findFirstResponder {
for (UIView *subView in self.subviews) {
if (subView.isFirstResponder)
return subView;
UIView* firstResponder = subView.findFirstResponder;
if(firstResponder)
return firstResponder;
}
return nil;
}
One crude but working implementation that I have used is to create a new UITextField, set it to be a first responder, and then immediately delete it. A basic method of doing this (within a view) is to do something like this:
UITextField *cell = [UITextField new];
[self addSubview:cell];
[cell becomeFirstResponder];
[cell resignFirstResponder];
[cell removeFromSuperview];
cell = nil;
This creates a new cell, adds it to the view so that it can be selected, has it take the focus of the keyboard away from the currently selected cell, hides the keyboard, and then deletes the new cell.
Edit: If you are going to be setting another textfield to be the first responder afterwards, this code is entirely unnecessary. Then, you'd just have to call becomeFirstResponder on the new textfield, and the keyboard focus will automatically shift.
In my application i am trying to adjust the position of the textlabel and detailtextlabel in a tableview cell.I am doing like this `
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
UIImageView* img = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"cell_with_arrow.png"]];
[cell setBackgroundView:img];
[img release];
}
cell.textLabel.frame = CGRectMake(0,0, 150, 40);
cell.detailTextLabel.frame = CGRectMake(155, 55, 150, 40);
cell.textLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size:14.0];
cell.textLabel.textColor = [UIColor blackColor];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.textLabel.text =#"name";
cell.detailTextLabel.text=#" status";
cell.detailTextLabel.backgroundColor = [UIColor clearColor];
//cell.detailTextLabel.textAlignment = UITextAlignmenteft;
//cell.textLabel.textAlignment = UITextAlignmentLeft;
return cell;
}
`but seems to be having no effect.can anybody help me to point me where i am going wrong?
textLabel and detailTextLabel are readonly so you can not change them.
#property(nonatomic, readonly, retain) UILabel *textLabel
#property(nonatomic, readonly, retain) UILabel *detailTextLabel
See here
What I would suggest is that you could create your custom UITableViewCell instead, you will have more control over it's content and can add custom subviews in there as well.
Here are some tutorials for that:
From IB
From Code
you need to override layoutSubviews method
Create a customcell class and inherit with uitableviewcell
#try this code
CustomCell.h
#import <UIKit/UIKit.h>
#interface CustomCell : UITableViewCell
#end
CustomCell.m
#import "CustomCell.h"
#implementation CustomCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
-(void)layoutSubviews{
//Set here your frame
self.textLabel.frame = CGRectMake(0, , 320, 30);
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
In my UITableViewCell i have a UIButton and a label which is been dynamically added to the cell.
I have a background image for the cell too so when this button gets clicked i want either the background of the cell to get replace with another image or i want the text color of the label to change to something else like gray or blue.
Is that possible?
Here's the code for ny cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
NSArray *subviews = cell.contentView.subviews;
for (UIView *vw in subviews)
{
if ([vw isKindOfClass:[UILabel class]])
{
[vw removeFromSuperview];
}
}
NSArray * temp;
NSData * imageData;
if (dataToDisplay!=nil) {
temp = [dataToDisplay objectAtIndex:indexPath.row];
imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString: [temp objectAtIndex:4]]];
}
playButtonImage = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"music_player_play_button.png"]];
pauseButtonImage = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"music_player_pause_button.png"]];
UIButton* preview = [UIButton buttonWithType:UIButtonTypeCustom];
preview.tag = 100 + indexPath.row;
[preview addTarget:self
action:#selector(playPreview:)
forControlEvents:UIControlEventTouchUpInside];
preview.backgroundColor = [UIColor clearColor];
preview.frame = CGRectMake(11,6, 36, 35);
[preview setBackgroundImage:playButtonImage.image forState:UIControlStateNormal];
[cell addSubview:preview];
UILabel * songName = [[UILabel alloc]initWithFrame:CGRectMake(60,15, 150, 15)];
songName.tag = 100+indexPath.row;
songName.text = [temp objectAtIndex:5];
songName.font = [UIFont boldSystemFontOfSize:12];
songName.backgroundColor = [UIColor clearColor];
[cell addSubview:songName];
UIButton * buy = [UIButton buttonWithType:UIButtonTypeCustom];
[buy addTarget:self
action:#selector(buySong:)
forControlEvents:UIControlEventTouchUpInside];
[buy setImage:[UIImage imageNamed:#"button_buy.png"] forState:UIControlStateNormal];
buy.tag = 200 + indexPath.row;
[buy setTitle:#"Buy" forState:UIControlStateNormal];
buy.titleLabel.font = [UIFont boldSystemFontOfSize:8.0];
buy.frame = CGRectMake(255,9,41, 30);
[cell addSubview:buy];
songsResults.tableHeaderView = headerView;
UIImage * cellIcon;
if (indexPath.row==[dataToDisplay count]-1) {
cellIcon = [UIImage imageNamed:[cellViewImages objectAtIndex:1]];
}
else {
cellIcon = [UIImage imageNamed:[cellViewImages objectAtIndex:0]];
}
cell.backgroundView = [[UIImageView alloc]initWithImage:cellIcon];
cell.clipsToBounds = YES;
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
Using the tag as an identifier of the cell whose button was pressed. That way you can determine which cell you need to change:
-(void)buySong:(id)sender {
UIButton *buttonPressed = (UIButton*)sender;
NSUInteger rowSelected = buttonPressed.tag - 200;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:rowSelected inSection:0];
CustomTableViewCell *cellSelected = (CustomTableViewCell)[self.tableView cellForRowAtIndexPath:indexPath];
cellSelected.label.textColor = [UIColor redColor];
}
You should subclass UITableViewCell so you can add new attributes to it and access them later on, like I did with CustomTableViewCell.
Here is a tutorial on how to create a custom UITableViewCell.
Cheers
I'd make a subclass of UITableViewCell that has its own action method to receive the button click, and use a block to handle that click so that your controller code could look something like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
SongCell *cell = [tableView dequeueReusableCellWithIdentifier:[SongCell identifier]];
if (cell == nil) {
cell = [[SongCell alloc] init];
}
cell.songData = [dataToDisplay objectAtIndex:indexPath.row];
cell.onPreviewClick =
^
(SongCell *cell)
{
cell.isPlaying = YES;
[self playSongAtIndexPath:indexPath]; // method to start the preview
};
return cell
}
To support this, your UITableViewCell subclass would look something like this:
// SongCell.h
#interface SongCell : UITableViewCell
#property (nonatomic, strong) NSArray *songData; // NSDictionary would be better
#property (nonatomic, copy) void(^onPreviewClick)(SongCell *cell);
#property (nonatomic, assign) BOOL isPlaying;
+ (NSString *)identifier;
#end
with this implementation:
// SongCell.m
#import "SongCell.h"
#interface SongData()
#property (nonatomic, strong) NSArray *_songData;
#property (nonatomic, assign) BOOL _isPlaying;
#property (nonatomic, strong) UIButton *playImage;
#property (nonatomic, strong) UIButton *pauseImage;
#property (nonatomic, strong) UIButton *previewButton;
#property (nonatomic, strong) UILabel *songNameLabel;
- (void)previewButtonPressed:(UIButton *)button;
#end
#implementation SongCell
#synthesize onPreviewClick, _songData, _isPlaying, playImage, pauseImage, previewButton, songNameLabel;
- (id)init {
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[SongCell identifier]])) {
self.selectionStyle = UITableViewCellSelectionStyleNone;
self.playImage = [UIImage imageNamed:#"music_player_play_button.png"];
self.pauseImage = [UIImage imageNamed:#"music_player_pause_button.png"];
self.previewButton = [UIButton buttonWithType:UIButtonTypeCustom];
previewButton.frame = CGRectMake(11,6, 36, 35);
[previewButton addTarget:self
action:#selector(previewButtonPressed:)
forControlEvents:UIControlEventTouchUpInside];
[self addSubview:previewButton];
self.songNameLabel = [[UILabel alloc]initWithFrame:CGRectMake(60,15, 150, 15)];
songNameLabel.font = [UIFont boldSystemFontOfSize:12];
[self addSubview:songNameLabel];
}
return self;
}
+ (NSString *)identifier {
return #"SongCell";
}
- (void)setSongData:(NSArray *)songData
{
self._songData = songData;
[self updateSubviews];
}
- (NSArray *)songData {
return _songData;
}
- (void)setIsPlaying:(BOOL)isPlaying {
self._isPlaying = isPlaying;
[self updateSubviews];
}
- (BOOL)isPlaying {
return _isPlaying;
}
- (void)previewButtonPressed:(UIButton *)button {
if (onPreviewClick) onPreviewClick(self);
}
- (void)updateSubviews {
if (_isPlaying) {
[previewButton setBackgroundImage:pauseImage forState:UIControlStateNormal];
}
else {
[previewButton setBackgroundImage:playImage forState:UIControlStateNormal];
}
songNameLabel.text = [_songData objectAtIndex:5];
}
#end
Caveat: I didn't test this. Hopefully it doesn't have too many errors.
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];
}