I have two buttons in my custom-made UITableViewCell.
Each button click should call the desired segue.
I setup a delegate on a cell like this:
CustomCell.h
#protocol CustomCellDelegate
-(void)seeQuestions;
-(void)seeLessons;
#end
#interface CustomCell : UITableViewCell
#property (weak, nonatomic) id <CustomCellDelegate> delegate;
- (IBAction)seeQuestions:(UIButton *)sender;
- (IBAction)seeLessons:(UIButton *)sender;
CustomCell.m
- (IBAction)seeQuestions:(UIButton *)sender {
[self.delegate seeQuestions];
}
- (IBAction)seeLessons:(UIButton *)sender {
[self.delegate seeLessons];
}
Now, in the ViewController class, where I have my UITableView, showing the custom cell, I import the CustomCell.h file, and connect delegates
ViewController.h
#import "CustomrCell.h"
#interface ViewController : UIViewController <CustomCellDelegate>
#property (strong, nonatomic) IBOutlet UITableView *tableView;
-(void)seeQuestions;
-(void)seeLessons;
#end
ViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:#"CustomCell"];
cell.delegate = self;
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.title.text = [NSString stringWithFormat:#"%#",_topicsArray[indexPath.row]];
return cell;
}
-(void)seeQuestions
{
[self performSegueWithIdentifier:#"seeQuestions" sender:self];
}
-(void)seeLessons
{
[self performSegueWithIdentifier:#"seeLessons" sender:self];
}
But, when the I click the buttons, nothing happens. I am sure Im missing out some realy obvious thing, but after couple of hours staring at my code, i cannot seem to figure out what am I doing wrong.
Any suggestions ?
Related
I have a tableview in my view controller. I took one protype cell in which I created a label and connected it to the tableVieCell.h file. The problem is when I try to access the label in my view to get it loaded with the textfield input, I am not getting the label component. Please check. Here is my MyCell.h file.
#import <UIKit/UIKit.h>
#interface MyCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UILabel *label1;
#property (strong, nonatomic) IBOutlet UILabel *label2;
#property (strong, nonatomic) IBOutlet UITextField *celltextField;
#end
here is my viewController.h file.
#import <UIKit/UIKit.h>
#import "MyCell.h"
#interface ViewController :UIViewController<UITableViewDelegate,UITableViewDataSource>
{
NSMutableArray *contacts;
}
- (IBAction)leftBtn:(id)sender;
- (IBAction)rightBtn:(id)sender;
- (IBAction)nextBtn:(id)sender;
- (IBAction)SendBtn:(id)sender;
#property (strong, nonatomic) IBOutlet UITableView *tabV1;
#property (strong, nonatomic) IBOutlet UITextField *txtField;
#end
#import "ViewController.h"
#interface ViewController ()
{
MyCell *cell;
}
#end
#implementation ViewController
- (void)viewDidLoad {
contacts= [[NSMutableArray alloc]init];
[super viewDidLoad];
}
-(BOOL)textFieldShouldReturn:(UITextField *) textField{
[textField resignFirstResponder];
return YES;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section
{
return contacts.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// [cell.zoomButton addTarget:self action:#selector(navigateAction:) forControlEvents:UIControlEventTouchUpInside];
// cell.zoomButton.tag=indexPath.row;
cell= [[MyCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MyCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
// cell.textLabel.text=contacts[indexPath.row];
cell.label2.text=[contacts objectAtIndex:indexPath.row];
return cell;
}
- (IBAction)leftBtn:(id)sender {
}
- (IBAction)rightBtn:(id)sender {
}
- (IBAction)nextBtn:(id)sender {
}
-(void)someMethod:(UIButton *)sender{
}
- (IBAction)SendBtn:(id)sender {
// if (_leftBtn.tag==1) {
// cell.label1.text=_txtField.text;
//
// }else{
// cell.label2.text=_txtField.text;
// }
[self->contacts addObject:_txtField.text];
// label2.text=_txtField.text;
[_tabV1 reloadData];
_txtField.text=#"";
}
#end
Change this
cell= [[MyCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MyCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
to this
MyCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
I have implemented my own UITableViewCell and created a .xib for it. I have connected all the labels using a strong IBOutlet and initialized the UILabels in the awakeFromNib() method. However, whenever I run the iOS Simulator, I run into an issue where the UILabel is (null) in NSLog.
I am wondering if it has to do with how I am loading in the text for the UILabel. I have tried to create a shortened version of the project below that outlines the issue I'm running into.
I would also like to note that I can click on the actual rows, but that there is still no text displaying.
My code:
ToDoCell.h
#import <UIKit/UIKit.h>
#interface ToDoCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UILabel *minutesLeft;
#property (strong, nonatomic) IBOutlet UILabel *hoursLeft;
#property (strong, nonatomic) IBOutlet UILabel *daysLeft;
#property (strong, nonatomic) IBOutlet UILabel *taskLabel;
#end
ToDoCell.m
#import "ToDoCell.h"
#implementation ToDoCell
#end
ToDoViewController.m
#import "ToDoViewController.h"
#import "ToDoCell.h"
#interface ToDoViewController ()
#property NSMutableArray *toDoItems;
#end
#implementation ToDoViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.toDoItems = [[NSMutableArray alloc] init];
[self loadInitialData];
}
- (void)loadInitialData {
NSString *item1 = #"Testing";
[self.toDoItems addObject:item1];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ToDoCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ToDoCell" forIndexPath:indexPath];
cell.taskLabel.text = #"Testing";
NSLog(#"Fudge Monkeys: %#", cell.taskLabel.text);
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
#end
Issue is you are creating new objects for labels but then you are not adding them to superview but calling [self addSubview:label] ssigning them to properties does not add them to super view.
But this is totally unnecessary you should not init them in awakeNib. , and one thing more I will say about your code now you don't need to use #synthesis anymore as well. Any particular reason you are making IBOutlets strong?
Update you need to register nib with tableView first add following lines in viewDidLoad
[tableView registerNib:[UINib nibWithNibName:#"ToDoCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:#"ToDoCell"];
You can read more about this here
If the UILabel instances are connected in Interface Builder via IBOutlet, you must not initialize them explicitly.
Just delete the complete awakeFromNib() method
Add this in viewDidLoad
NSString *strName = NSStringFromClass([ToDoCell class]);
[self.toDoItems registerNib:[UINib nibWithNibName:strName bundle:nil] forCellReuseIdentifier:strName];
You are using xib file but not loading it by registering it for the tableView. This is required when you use separate xib file. If you do not register, then only class will load and xib won't. And your awakeFromNib won't be called.
First of all delete awakeFromNib and make sure that you gave Cell Identifier in cell nib file.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"ToDoCell";
ToDoCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
if (!cell)
cell = [[ToDoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: cellIdentifier];
cell.taskLabel.text = #"Testing";
return cell;
}
Don't forget to add following code for register nib.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.tableView registerNib:[UINib nibWithNibName:#"ToDoCellTableViewCell" bundle:nil] forCellReuseIdentifier:#"ToDoCell"];
}
Here is the sample code for your problem.
May this help to solve your problem.
You .xib why cell should be set through:
- (UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
{
ToDoCell *cell = [tableView dequeueReusableCellWithIdentifier:[ToDoCell reuseIdentifier]];
if (!cell) {
cell = (ToDoCell *)
[[NSBundle mainBundle] loadNibNamed:#"ToDoCell" owner:self options:nil].firstObject;
}
cell.taskLabel.text = #"Testing";
NSLog(#"Fudge Monkeys: %#", cell.taskLabel.text);
return cell;
}
I'm trying to subclass a UITableView. However, I'm unable to get an indexPath that isn't nil. The tableView has custom cells.
Here is my TouchTableView.h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h> //I brought this in because I'm saving audio files in my app
#import "SimpleTableCell.h"
#protocol myTableViewDelegate;
#interface TouchTableView : UITableView <UITableViewDelegate, UITableViewDataSource, AVAudioRecorderDelegate, AVAudioPlayerDelegate, UITextViewDelegate, UITextFieldDelegate, UIAlertViewDelegate>
#property (nonatomic, weak) id<myTableViewDelegate> myDelegate;
#property (strong, nonatomic) NSMutableArray *sortedFiles;
#property (strong, nonatomic) NSString *simpleTableIdentifier;
#property (strong, nonatomic) SimpleTableCell *cell;
#property BOOL inverted;
-(void)refreshTable;
#end
#protocol myTableViewDelegate <NSObject>
- (void)selectedFile:(TouchTableView *)tableView withURL: (NSURL *) tableViewURL IndexPath:(NSIndexPath *)indexPath;
-(void)didDelete:(TouchTableView *)tableView IndexPath:(NSIndexPath *)indexPath;
-(void)setSortedFile:(TouchTableView *)tableView;
#end
I attach a longpress like so:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//bring in your custom cell here
simpleTableIdentifier = #"SimpleTableCell";
cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
[cell.textField setEnabled:NO];
//put in long press
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPress:)];
[longPressGesture setMinimumPressDuration:1.0];
[cell addGestureRecognizer:longPressGesture];
}
}
return cell;
}
Then I have the following method for when the longpress activates:
- (void)longPress:(UILongPressGestureRecognizer *)gesture
{
if (![cell.textField isEnabled]) {
// only when gesture was recognized, not when ended
if (gesture.state == UIGestureRecognizerStateBegan)
{
// get affected cell
cell = (SimpleTableCell *)[gesture view];
// get indexPath of cell
NSIndexPath *indexPath = [self indexPathForCell:cell];
[self selectRowAtIndexPath:indexPath animated:NO scrollPosition:0];
[cell.textField setEnabled:YES];
[cell.textField becomeFirstResponder];
}
}
}
In my viewController in viewDidLoad I have:
self.touchTableView = [[TouchTableView alloc] init];
[self.tableView setDelegate:self.touchTableView];
[self.tableView setDataSource:self.touchTableView];
self.touchTableView.myDelegate = self;
The problem is that the indexPath is always nil. You'll note that I'm calling self instead of self.tableView because self is the tableView. Is there a way to get the indexPath?
Sorry for the mess all. rmaddy was right. Ridiculous. The solution:
in my ViewController.h I set up:
#property (weak, nonatomic) IBOutlet TouchTableView *tableView;
Then I changed the last code in my example to
[self.tableView setDelegate:self.tableView];
[self.tableView setDataSource:self.tableView];
self.tableView.myDelegate = self;
[self.tableView refreshTable];
Now I'm getting the index path.
I may be barking up the wrong tree but I'm trying to duplicate functionality I wrote for ios5 in a project thats been updated to ios7.
I've copied and pasted the code across, I get this error
*** Assertion failure in -[UITableView dequeueReusableCellWithIdentifier:forIndexPath:], /SourceCache/UIKit/UIKit-2903.23/UITableView.m:5261
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier TableView - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
*** First throw call stack:
(0x30829f4b 0x3ac6a6af 0x30829e25 0x311d1fe3 0x3310891f 0x11bebf 0x330cea5b 0x33076e7d 0x33076699 0x32f9cda3 0x32c23c6b 0x32c1f47b 0x32c1f30d 0x32c1ed1f 0x32c1eb2f 0x32c1885d 0x307f51cd 0x307f2b71 0x307f2eb3 0x3075dc27 0x3075da0b 0x35484283 0x33001049 0x81597 0x7b558)
Everything is the same as another controller where it works except when I examine the xib
Working one:
Crashing one:
The difference being there no Referencing outlet tableCell -> File's Owner
HOW? WHY?
Here's the code just in case
Viewcontroller.h
#import <UIKit/UIKit.h>
#import "blogCellVC.h"
#interface BlogsListingiPhoneVC : UIViewController <UITableViewDataSource, UITableViewDelegate>
{
NSArray *blogsListing;
UITableView *tableView;
IBOutlet blogCellVC *tableCell;
}
Viewcontroller.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIndentifier = #"MyCell";
blogCellVC *cell = (blogCellVC *)[self.tableView dequeueReusableCellWithIdentifier:MyIndentifier forIndexPath:indexPath];
if (cell == nil)
{
[[NSBundle mainBundle] loadNibNamed:#"blogCellVC" owner:self options:nil];
cell = tableCell;
}
blogsListingModel *info = [_blogsListing objectAtIndex:indexPath.row];
if (info.blogActive == 0)
{
[cell cellHead:info.blogName];
[cell cellHeadCol:[UIColor lightGrayColor]];
[cell cellIcon:#"blank.png"];
}else {
[cell cellHead:info.blogName];
[cell cellHeadCol:[UIColor blackColor]];
[cell cellIcon:#"tick.png"];
}
return cell;
}
Customcell.h
#import <UIKit/UIKit.h>
#interface blogCellVC : UITableViewCell {
IBOutlet UILabel *cellHead;
IBOutlet UIImageView *cellIcon;
}
- (void)cellHead:(NSString *)_text;
- (void)cellIcon:(NSString *)_text;
- (void)cellHeadCol:(UIColor *)aCol;
#end
Customcell.m
#import "blogCellVC.h"
#interface blogCellVC ()
#end
#implementation blogCellVC
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code.
}
return self;
}
- (void)cellHead:(NSString *)_text {
cellHead.text = _text;
}
- (void)cellHeadCol:(UIColor *)aCol {
cellHead.textColor = aCol;
//cellStandfirst.textColor = aCol;
}
- (void)cellIcon:(NSString *)_text {
cellIcon.image = [UIImage imageNamed:_text];
}
- (void)dealloc {
[super dealloc];
}
#end
PS. I have set the custom class of the File's Owner in the Identity inspector to 'blogCellVC' and the identifier in the attributes inspector to 'MyCell'
I found the solution here:
No Visible View in Custom Table View Cell
In the custom uitableviewcell, in the identity inspector assign the Files Owner's class as the view with the table, and override uitableview cell with your custom class
My mistake as trying to re-use the custom class with a second view.
For completeness' sake, minimum code
parent.h
#import "blogCellVC.h"
#interface BlogsListingiPhoneVC : UIViewController <UITableViewDataSource, UITableViewDelegate>
{
UITableView *tableView;
IBOutlet blogCellVC *tableCell;
}
parent.m
- (void)viewDidLoad
{
[super viewDidLoad];
[tableView registerClass: [blogCellVC class] forCellReuseIdentifier:#"MyCell"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIndentifier = #"MyCell";
blogCellVC *cell = (blogCellVC *)[self.tableView dequeueReusableCellWithIdentifier:MyIndentifier forIndexPath:indexPath];
if (cell == nil)
{
cell = [[blogCellVC alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MyCell"];
}
[cell cellHead:info.blogName];
[cell cellHeadCol:[UIColor lightGrayColor]];
[cell cellIcon:#"blank.png"];
return cell;
}
blogCellVC.h
#import <UIKit/UIKit.h>
#interface blogCellVC : UITableViewCell {
IBOutlet UILabel *cellHead;
IBOutlet UIImageView *cellIcon;
}
- (void)cellHead:(NSString *)_text;
- (void)cellIcon:(NSString *)_text;
- (void)cellHeadCol:(UIColor *)aCol;
#end
blogCellVC.m
#interface blogCellVC ()
#end
#implementation blogCellVC
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code.
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"blogCellVC" owner:self options:nil];
self = [nib objectAtIndex:0];
}
return self;
}
Lastly make sure in the xib/storyboard you've put "MyCell" or whatever in the Identifier field in the Attributes Inspector.
This works in X Code 5, ios7
I'm a newbie in objective-c and iOS
I created several custom table cells with outlets in it. But I'm not sure if I use the right way.
What I want to do is to get the property of an Outlet which is inside the custom cell, by an IBAction defined in the table view controller.
I have a custom table cell called KolonNumberCell, and a UISlider in it.
I want to define an IBAction called playNumbers in the UITableViewController. The slider seems to work fine in the custom cell. I can get its value.
But I cannot figure out how to get the value of this slider when the playButton outlet is tapped.
I would be so grateful if you could give me some information or show me a way.
Thanks in advance
TableController.h
#import <UIKit/UIKit.h>
#class KolonNumberCell;
#class BankoNumberCell;
#interface TableViewController : UITableViewController{
NSArray *bundleArray;
IBOutlet KolonNumberCell *kolonCell;
IBOutlet BankoNumberCell *bankoCell;
UIButton *playButton;
}
#property (strong) IBOutlet KolonNumberCell *kolonCell;
#property (strong) IBOutlet BankoNumberCell *bankoCell;
#property (nonatomic,retain) NSArray *bundleArray;
#property (nonatomic,retain) IBOutlet UIButton *playButton;
- (void)playNumbers:(id)sender;
#end
part of TableController.m
#import "TableViewController.h"
#interface TableViewController ()
#end
#implementation TableViewController
#synthesize bundleArray,kolonCell,bankoCell,playButton;
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *bundle1 = [[[NSBundle mainBundle] loadNibNamed:#"KolonNumberCell" owner:self options:nil] objectAtIndex:0];
NSArray *bundle2 = [[[NSBundle mainBundle] loadNibNamed:#"BankoNumberCell" owner:self options:nil] objectAtIndex:0];
bundleArray = [[NSArray alloc] initWithObjects:bundle1,bundle2, nil];
}
- (void)playNumbers:(id)sender
{
NSLog(#"button");
// Get the value of the slider in KolonNumberCell... but how?
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
tableView.allowsSelection = NO;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [bundleArray objectAtIndex:indexPath.section];
}
return cell;
}
#end
One of my customtableviewcell implementation file
#import "KolonNumberCell.h"
#implementation KolonNumberCell
#synthesize label,slider;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
self.backgroundView = [[UIImageView alloc] initWithImage:[ [UIImage imageNamed:#"doubleRound.png"] stretchableImageWithLeftCapWidth:0.0 topCapHeight:0.0]];
}
- (IBAction)sliderChanged:(id)sender
{
[label setText:[NSString stringWithFormat:#"%i",(int)slider.value]];
}
+ (NSString *)reuseIdentifier {
return #"Cell";
}
#end
Your design is odd because your code will become really messy with more Cells.
Matt Gallagher has a nice implementation for Custom TableViews. He is using the TableViewCell as a Controller and puts all the logic related to cell in the cells class. The discussion thread on Stack Overflow:
CustomTableViewController
If you still want to do it your way:
Give your Slider a tag: slider.tag = x //Make sure that the tag is unique
In PlayNumbers:
UISlider *slider = (UISlider *)[[[bundleArray objectAtIndex:0] contentView] viewWithTag:x];
NSLog(#"%i",(int)slider.value);
Edit: thanks for correcting the syntax