I'm trying to create a UITableView in a UIViewController (I'd use UITableViewController but I want the UITableView to only use half of the screen space) that will create a new custom cell every time I press a button, and display the current time in that cell and the time since the last time I pressed the button (so the time in this cell minus the time in the cell above it).
The problem is, when I press the button, either nothing happens or, if I don't initialise the property I created for the UITableView, a blank cell appears.
My cell has 3 UILabel's in it, inOut, entryTime and delta, and the IBOutlet I created for the UITableView is timeTable. newEntry is the button. I have set my UITableView's datasource and delegate to my UIViewController, have "called" the protocols UITableViewDataSource, UITableViewDelegate on my UIViewController's header. I can't find what's wrong.
here's my code for the UIViewController:
#interface MainViewController ()
#property (strong, nonatomic) Brain *brain;
#end
#implementation MainViewController{
#private
NSMutableArray *_entryArray;
NSMutableArray *_timeSinceLastEntryArray;
}
#synthesize brain=_brain;
#synthesize timeTable=_timeTable;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
_brain = [[Brain alloc] init];
_entryArray = [[NSMutableArray alloc] init];
_timeSinceLastEntryArray = [[NSMutableArray alloc] init];
_timeTable = [[UITableView alloc] initWithFrame:CGRectZero];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [_entryArray count];
}
- (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:CellIdentifier];
}
if (indexPath.row%2==0){
cell.inOut.text = [NSString stringWithFormat:#"Entrada %d", indexPath.row/2 +1];
cell.entryTime.text = [NSString stringWithFormat:#"%#", [_entryArray objectAtIndex:indexPath.row]];
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]];
cell.delta.text = [_timeSinceLastEntryArray objectAtIndex:indexPath.row];
}
return cell;
}
- (IBAction)newEntry:(id)sender {
[_entryArray addObject:[self.brain currentTime]];
NSInteger numberOfEntrys= [_entryArray count];
if (numberOfEntrys >1){
NSString *timeSinceLastEntry = [_brain timeSince:[_entryArray objectAtIndex:(numberOfEntrys-2)]];
[_timeSinceLastEntryArray addObject:timeSinceLastEntry];
}
else {
[_timeSinceLastEntryArray addObject:#"0"];
}
[_timeTable reloadData];
}
#end
and for CustomCell:
#implementation CustomCell
- (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
}
#synthesize inOut=_inOut, entryTime=_entryTime, delta=_delta;
- (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier]) {
// Initialization code
_inOut = [[UILabel 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
Thanks for the help :)
I see you put the initialize code in
- (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier
But you create object with
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
and you did not provided the Frame to the view that you created
_inOut = [[UILabel alloc]init];
_entryTime = [[UILabel alloc]init];
_delta = [[UILabel alloc]init];
Hope it helps you
Related
I have a TableViewCell subclass and I am trying to create a table with this cell type. However the table won't show the custom cells content.
The values of the cell derive from data core model. But there isn't an issue with it as I have also tried with simple literals and it still wouldn't work. Any help is appreciated.
Here is my code:
favCell.m
#import "favCell.h"
#implementation favCell
#synthesize view;
#synthesize namelbl;
#synthesize scorelbl;
#synthesize prodimage;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
view = [[UIView alloc] initWithFrame:self.frame];
[self addSubview:view];
// initiate
prodimage = [[UIImageView alloc]initWithFrame:CGRectMake(2,20, 20, 20)];
namelbl = [[UILabel alloc]initWithFrame:CGRectMake(3,20, 40, 40)];
scorelbl = [[UILabel alloc]initWithFrame:CGRectMake(70,20, 30, 30)];
[view addSubview:namelbl];
[view addSubview:scorelbl];
[view addSubview:prodimage];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
favTable.m
#import "favTable.h"
#import "ecoAppDelegate.h"
#import "favCell.h"
#interface favTable ()
#end
#implementation favTable
#synthesize favArr;
#synthesize managedObjectContext;
#synthesize fetchedResultsController;
#synthesize favName;
#synthesize favScore;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
favCell*cell = (favCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[favCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.namelbl.text = [favName objectAtIndex:indexPath.row];
cell.scorelbl.text = [favScore objectAtIndex:indexPath.row];
cell.prodimage.image = [UIImage imageNamed:#"test1.jpg"];
return cell;
}
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.
I have a tab based application. On the first tab I have several views one of which is a navigation controller. My goal is to load this list view(working) then goto a detailview on the cell click(not working).
On the cell click I am logging
NSLog(#"%#",self.navigationController);
which is returning a null. I can only assume that I have not done something right with setting up the navigation controller but I do not know what.
on button click the table view is called:
#import "Reviews.h"
#import "XMLParser.h"
#import "Detailed_Review.h"
#implementation Reviews
#synthesize reviewsTableView;
XMLParser *xmlParser;
CGRect dateFrame;
UILabel *dateLabel;
CGRect contentFrame;
UILabel *contentLabel;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[xmlParser reviews] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
Review_Object *currentReview = [[xmlParser reviews] objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
CGRect contentFrame = CGRectMake(10, 2, 265, 30);
UILabel *contentLabel = [[UILabel alloc] initWithFrame:contentFrame];
contentLabel.tag = 0011;
contentLabel.numberOfLines = 2;
contentLabel.font = [UIFont boldSystemFontOfSize:12];
[cell.contentView addSubview:contentLabel];
CGRect reviewFrame = CGRectMake(10, 40, 265, 10);
UILabel *reviewLabel = [[UILabel alloc] initWithFrame:reviewFrame];
reviewLabel.tag = 0012;
reviewLabel.font = [UIFont systemFontOfSize:10];
[cell.contentView addSubview:reviewLabel];
}
UILabel *contentLabel = (UILabel *)[cell.contentView viewWithTag:0011];
contentLabel.text = [currentReview rating];
UILabel *dateLabel = (UILabel *)[cell.contentView viewWithTag:0012];
dateLabel.text = [currentReview review];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 55;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Detailed_Review *dvController = [[Detailed_Review alloc] initWithNibName:#"Detailed_Review" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:dvController animated:YES];
NSLog(#"%#",self.navigationController);
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
xmlParser = [[XMLParser alloc] loadXMLByURL:#"http://www.mywebsite.com/api/reviews/xml.php?page=1"];
self.title = #"Reviews";
}
- (void)viewDidUnload
{
[self setReviewsTableView:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (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];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
xib photos:
.h file:
#import <UIKit/UIKit.h>
#import "XMLParser.h"
#import "Review_Object.h"
#interface Reviews : UIViewController
#property (retain, nonatomic) IBOutlet UITableView *reviewsTableView;
#end
You omitted the part where the navigationController is allocated and initialized. Can you add that, including the relevant part from the .h file too?
Either create it with IB or programatically, see https://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/ViewControllerPGforiOSLegacy/NavigationControllers/NavigationControllers.html#//apple_ref/doc/uid/TP40011381-CH103-SW27
I just create a simple UITableView in the UIViewController.
.h
#import <UIKit/UIKit.h>
#interface RootController : UIViewController <UITableViewDataSource>
{
NSMutableArray *_tableData;
UITableView *_tableView;
}
#end
.m
#import "RootController.h"
#implementation RootController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
if (!_tableData) {
_tableData = [[NSMutableArray alloc] initWithCapacity:20];
for (int i = 0; i < 50; i++) {
[_tableData addObject:[NSString stringWithFormat:#"%d", i]];
}
}
}
return self;
}
- (void)dealloc
{
[_tableView release];
[_tableData release];
[super dealloc];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)loadView
{
UIView *view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.view = view;
[view release];
self.view.backgroundColor = [UIColor whiteColor];
if (!_tableView) {
_tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
_tableView.dataSource = self;
}
[self.view addSubview:_tableView];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"TableViewCellIdentifier";
UITableViewCell *cell = nil;
cell = [_tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
}
cell.textLabel.text = [_tableData objectAtIndex:indexPath.row];
return cell;
}
#end
I used instruments to detect memory leak for this, when I scrolled the UITableView, memory
leak occurred.
I use Xcode 4.3.1 and iOS5.1 (iPod touch4).
Someone had this problem?
If you look at the 'responsible library' column, you can see that the culprit is not your code. The leaks are small, you can safely ignore them.
Here is a similar question: WebView: libdispatch leaks in an ARC-enabled app
I created UI for Iphone that has a button and label above tableview. The problem is that data doesn't show in table despite setting it in cellForRowAtIndexPath method.
I get this:
This is my code for controller of third tab. Header:
#import <UIKit/UIKit.h>
#interface ThirdView : UIViewController <UITableViewDelegate,UITableViewDataSource> {
//model
NSMutableArray *podatki;
//view
UITableView *myTableView;
}
#property(nonatomic,retain) NSMutableArray *podatki;
#property(nonatomic,retain) UITableView *myTableView;
-(IBAction)pritisnuGumb:(UIButton *) sender; //
#end
Implementation:
#import "ThirdView.h"
#implementation ThirdView
#synthesize podatki;
#synthesize myTableView;
-(void)viewDidLoad{
myTableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStylePlain];
myTableView.delegate = self;
myTableView.dataSource = self;
myTableView.autoresizesSubviews = YES;
podatki = [[NSMutableArray alloc] init];
[podatki addObject:#"Sunday"];
[podatki addObject:#"MonDay"];
[podatki addObject:#"TuesDay"];
[super viewDidLoad];
//self.view = myTableView;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [podatki count];
}
-(IBAction)pritisnuGumb:(UIButton *) sender {
NSLog(#"buca");
}
- (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];
}
cell.textLabel.numberOfLines = 4;
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
NSString *naslov = [podatki objectAtIndex:indexPath.row];
cell.textLabel.text = naslov;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"kliknu na vrstico");
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)dealloc {
[podatki release];
[super dealloc];
}
#end
If i uncomment line "self.view = myTableView;" i get tableview with data but label and button above it disappear (tableview is fullscreen).
What am i doing wrong here?
#Jennis:
I tried your solution and data inside table is now visible but upper part is squeezed like this:
I believe that you can do like
[self.view addSubview:myTableView];
[self.view sendSubviewToBack:myTableView].
hope it helps