UITextFields text in custom UITableViewCell appears in other cell while Scrolling - ios

I am new to iOS development. i create my app in Xcode 6(Storyboard).
My problem is text enter into textfield, scroll the table view that shuffle the textfield text to other text field randomly. There are two question i saw in stack-overflow like this. but that answer are not solve question.
MoneyEntry.xib is a uitableviewcell with one label and one text box. And add class file to it and connect IBOutlet and add identifier to the uitableviewcell as "MoneyEntryIdentifier".
//MoneyEntryTableViewCell.h
#interface MoneyEntryTableViewCell : UITableViewCell
//Money Entry Cell
#property (strong, nonatomic) IBOutlet UILabel *lblMemName;
#property (strong, nonatomic) IBOutlet UITextField *textAmount;
#end
//MoneyEntryTableViewCell.m
#import "MoneyEntryTableViewCell.h"
#implementation MoneyEntryTableViewCell
#synthesize lblMemName,textAmount;
- (void)awakeFromNib {
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
}
#end
In Main.storyboard add UITableView and connect IBOutlet and add Datasource and delegate.
//MoneyDetailViewController.h
#import <UIKit/UIKit.h>
#interface MoneyDetailViewController : UIViewController
#property (strong, nonatomic) IBOutlet UITableView *tblVwMoneyEntry;
#end
//MoneyDetailViewController.m
#interface MoneyDetailViewController ()
{
NSArray *tabledata;
}
#end
#implementation MoneyDetailViewController
- (void)viewDidLoad {
[super viewDidLoad];
tabledata = [NSArray arrayWithObjects:#"Egg Benedict", #"Mushroom Risotto",#"Full Breakfast", #"Hamburger", #"Ham and Egg Sandwich", #"Creme Brelee",#"White Chocolate Donut", #"Starbucks Coffee", #"Vegetable Curry", nil];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [tabledata count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"MoneyEntryIdentifier";
static NSString *CellNib = #"MoneyEntry";
MoneyEntryTableViewCell *cell = (MoneyEntryTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellNib owner:self options:nil];
cell = (MoneyEntryTableViewCell *)[nib objectAtIndex:0];
}
UILabel *lblname = (UILabel *) [cell lblMemName];
UITextField *txtfield = (UITextField *)[cell textAmount];
txtfield.tag = indexPath.row;
lblname.text = [tabledata objectAtIndex:indexPath.row];
txtfield.placeholder =#"0.00";
cell.selectionStyle =UITableViewCellSelectionStyleNone;
return cell;
}
#end
Please explain me detail. Thanks in advance

I found answer.... Just get the textfield text into Dictionary setObject by label text and again check by label Text assign the text to corresponding Textfield.. here is my code...
//In Interface
NSMutableDictionary *amounts;
amounts =[[NSMutableDictionary alloc]init];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"MoneyEntryIdentifier";
static NSString *CellNib = #"MoneyEntry";
MoneyEntryTableViewCell *cell = (MoneyEntryTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellNib owner:self options:nil];
cell = (MoneyEntryTableViewCell *)[nib objectAtIndex:0];
}
UILabel *lblname = (UILabel *) [cell lblMemName];
lblname.tag =100;
UITextField *txtfield = (UITextField *)[cell textAmount];
txtfield.tag =indexPath.row;
[txtfield addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
lblname.text = tabledata[indexPath.row];
txtfield.placeholder = [NSString stringWithFormat:#"%ld",(long)indexPath.row];
if ([amounts valueForKey:lblname.text] != nil) {
txtfield.text = [amounts valueForKey:lblname.text];
} else {
txtfield.text = #"";
}
cell.selectionStyle =UITableViewCellSelectionStyleNone;
return cell;
}
-(void)textFieldDidChange:(UITextField *)txtField
{
UILabel *label = (UILabel *)[txtField.superview viewWithTag:100];
NSString *labelString = label.text;
NSString *textFieldString = txtField.text;
[amounts setObject:textFieldString forKey:labelString];
}
There is no error while scroll table view...

Are you doing something to store the text entered into the textfield. The UITableView works by reusing UITableViewCells that are not visible or gone out of the screen to save memory.
So if you enter some text into a textfield in the cell and the cell goes out of the screen, the cell gets queued up for later use. As you scroll new rows are added from this queue, which bring the textfield with your previous text back. This is why you see your text randomly popping everywhere.
You need to save the data from each textfield in a separate array and reset it in cellForRowAtIndexPath: function.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Your code..
Item *item = itemArray[indexPath.row]
cell.txtfield.text = item.amount
}
You can use the UITextField's UIControlEventEditingChanged event to store the changed array values.
-(void)textFieldDidChange:(UITextField *)txtField
{
Item *item = itemArray[txtField.tag]
item.amount = txtField.text
}
You add the textField change method like this
[textField addTarget:self
action:#selector(textFieldDidChange:)
forControlEvents:UIControlEventEditingChanged];
Use a custom class called Item to store your data.
class Item
{
#property (nonatomic,strong) NSString *itemName;
#property (nonatomic) float amount;
}
itemArray will contain your items.
Item *it1 = [[Item alloc]init]
it1.itemName = #"Eggs Benedict"
it1.amount = ""
....
itemArray = [NSArray arrayWithObjects:it1,it2,it3,nil];

Related

tableView:indexPathForCell returns nil when clicking in cell

I know indexPath will return nil when the cell is hidden, but my question is why it is not visible?
My case is that:
There is a button in the cell when button is clicked, and it tries to get the indexPath( by selector indexPathForCell: )
Meanwhile the tableview is refreshed by another thread.
Sometimes the indexPath will get nil, my question is because the button is in the cell, when event was fired the cell must exist ( otherwise how should the button be clicked ), what happened causing the cell hidden?
thx.
//Cell.m
#property (nonatomic, weak) UIButton *button;
#property (nonatomic, weak) XXXDelegate *delegate;
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
UIButton * button = xxx;
[self.contentView addSubview:button];
[button addTarget:self action:#selector(xxxClick:) forControlEvents:UIControlEventTouchUpInside];
}
-(void)xxxClick:(id)sender{
[self.delegate xxxClick:self];
}
//Controller.m
-(void)loadView{
self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
self.tableView.delegate = self;
[self.tableView registerClass:[Cell class] forCellReuseIdentifier:#"xxx"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"xxx" forIndexPath:indexPath];
//update cell
cell.delegate = self;
return cell;
}
- (void)xxxClick:(UITableViewCell*) cell {
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
//indexPath is nil sometimes? why?
}
And also, the tableview reloads sometimes
Thx guys,I finally got the answer.
When the button is triggered and the tableview is "reloadData" in the same runloop, "reloadData" cause the cell to be invisible, and "indexPathForCell" will get nil.
It is dangerous if you do not check the value of indexPath.
Might you can have wrong reuse identifier which is defined in the custom cell in the storyboard.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell : SingleLabelTableCell = tableView.dequeueReusableCellWithIdentifier("SingleLabelTableCell", forIndexPath: indexPath) as! SingleLabelTableCell
let tempDict : NSDictionary = dataArray.objectAtIndex(indexPath.row) as! NSDictionary
cell.nameLabel.text = tempDict.valueForKey("title") as? String
return cell
}
or You can check it on this video tutorial link also
https://www.youtube.com/watch?v=OHue6nFUBO8
Try to use in below format
Cell.h
//
// Cell.h
// Projects
#import <UIKit/UIKit.h>
#interface Cell : UITableViewCell
#property (weak, nonatomic) IBOutlet UIButton *btnCall;
#end
Cell.m
//
// Cell.m
#import "Cell.h"
#implementation NearByDealDetailCell
- (void)awakeFromNib {
[super awakeFromNib];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
// ControllerVC.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *simpleTableIdentifier = #"Cell";
Cell *cell = (Cell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"Cell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.btnCall.tag = indexPath.row;
[cell.btnCall addTarget:self action:#selector(actionBtnCall:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
- (IBAction)actionBtnCall:(id)sender {
UIButton *btn = (UIButton *)sender;
NearByDealModel *activity = (NearByDealModel *)[self.activityList objectAtIndex:[btn tag]];
}

TextView array to TableView

I need to use a UITextView to enter in information, which then moves the information into a UITableView.
I need it to update the tableview each time a new line has been added.
I thought i could create an array out of the information in the TextView and place it into a TableView but i cant seem to figure out how to do this.
With this it still doesn't populate the table with what i type in the 'UITextView'.
-(void)textViewDidChange:(UITextView *)textView{
listArray=[[NSMutableArray alloc]initWithArray:[textView.text componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]]];
[self.tableView reloadData];
}
- (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];
}
cell.textLabel.text = [listArray objectAtIndex:indexPath.row];
return cell;
}
First set the delegate property of the UITextView to your viewController. Then use textViewDidChange method to initialize your array--
in ViewController.h file-
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate,UITextViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#property (weak, nonatomic) IBOutlet UITextView *txtView;
#end
and in ViewController.m file
#import "ViewController.h"
#interface ViewController (){
NSMutableArray *listArray;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.txtView.delegate = self;
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(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];
}
cell.textLabel.text = [NSString stringWithFormat:#"%#",[listArray objectAtIndex:indexPath.row]];;
return cell;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return listArray.count;
}
-(void)textViewDidChange:(UITextView *)textView{
listArray=[[NSMutableArray alloc]initWithArray:[textView.text componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]]];
[self.tableView reloadData];
NSLog(#"Array-- %#",listArray);
NSLog(#"Array Count-- %lu",(unsigned long)listArray.count);
NSLog(#"Text-- %#",textView.text);
}
#end
Use listArray to show your data on tableView.
You can create an array with the text of textview using the following method :
NSString* string;
NSArray* array = [string componentsSeparatedByString:(nonnull NSString*)]
now you can create your tableview using the above array. whenever you want to update the table, you can call the following method :
[tableView reloadData];
If you just want to look for new lines you can do something like this:
NSArray <NSString*> *components = [self.textView.text componentsSeparatedByString:#"\n"];
If you implement the delegate methods of UITextView specifically to get notifications when the text content changes you can then update an array that feeds into your table view.
Also here's the code in Swift just because we should be thinking about it now.
let components: [String] = textView.text.componentsSeparatedByString("\n")

Adding Table View Cell not working in iOS?

I am trying to create a shopping list app. I am very new to Objective-C. Somehow this block of code is not working and I don't know what I did wrong. Whenever I type something in the textfield and click add, the text is not added to the table view.
HEADER FILE:
#interface NotesViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) NSMutableArray *notes;
#property (nonatomic, strong) IBOutlet UITextField *noteTitleText;
#property (nonatomic, strong) IBOutlet UITableView *noteBlockTableView;
#end
IMPLEMENTATION FILE:
#implementation NotesViewController
#synthesize notes; #synthesize noteTitleText; #synthesize noteBlockTableView;
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [notes count]; }
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *tableViewTitle;
tableViewTitle = [notes objectAtIndex:[indexPath row]];
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:nil];
[[cell textLabel] setText:[tableViewTitle objectForKey:#"cellTitle"]];
return cell;
}
-(IBAction)addNote {
NSDictionary *tableViewTitle;
tableViewTitle = [[NSDictionary alloc] initWithObjectsAndKeys:[noteTitleText text], #"cellTitle", nil];
[notes addObject:tableViewTitle];
[noteBlockTableView reloadData];
noteTitleText.text = #"";
}
Maybe you should override numberOfSectionsInTableView function and return 1
Welcome to Objective-C!
Before using NSMutableArray, you should initialize it first, like this:
# NotesViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
notes = [[NSMutableArray alloc]init];
}
It should work.
First initialise the array notes, then you should allocate cell like this in cellForRowAtIndexPath method
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *tableViewTitle;
tableViewTitle = [notes objectAtIndex:[indexPath row]];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.textLabel.text = [tableViewTitle objectForKey:#"cellTitle"];
return cell;
}

iOS 8 custom table view cell selection

I have some problems with my custom cells. I created New custom TableViewCell with its own xib file. The table loads and data is being populated in all the cells - that is all ok. But when i run my app in devices and simulators with iOS 8 and above the select method never fires. This problem does not happen when i run the application on devices and simulators with iOS 7.x. Here is the code for the CustomCell.m file
- (void)awakeFromNib {
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
Here is mu CustomCell.h file
#interface CustomCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UIImageView *directionImage;
#property (weak, nonatomic) IBOutlet UILabel *distanceLbl;
#property (weak, nonatomic) IBOutlet UILabel *pathDescriptionLbl;
And here is the code from the ViewController
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"row selected");
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [steps.stepsData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *cellIdentifier = #"directionsCell";
DirectionsTableViewCell *cell = (DirectionsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell == nil){
NSString *cellNib = [Utilities getDirectionCellNib];
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:cellNib owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
if(indexPath.row == 0 || (indexPath.row % 2 == 0)){
cell.backgroundColor = [UIColor colorWithRed:242.0/255.0 green:242.0/255.0 blue:242.0/255.0 alpha:1.0];
}else{
cell.backgroundColor = [UIColor colorWithRed:230.0/255.0 green:230.0/255.0 blue:230.0/255.0 alpha:1.0];
}
cell.directionImage.image = nil;
cell.distanceLbl.text = #"";
cell.pathDescriptionLbl.text = #"";
if(indexPath.row != 0){
UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, cell.frame.size.width, 1)];
separatorLineView.backgroundColor = [UIColor colorWithRed:200.0/255.0 green:200.0/255.0 blue:200.0/255.0 alpha:1.0];
[cell.contentView addSubview:separatorLineView];
}
cell.pathDescriptionLbl.text = #"main text here";
Step *stp = [steps.stepsData objectAtIndex:indexPath.row];
NSString *txtDetails = #"Details text here";
cell.distanceLbl.text = #"Distance here";
return cell;
}
What i find weird here is that the row selection works perfectly on iOS 7 but NOT on iOS 8. The data is being populated in both cases.
Am i doing something wrong here or am i missing something.
Thanks in advance for the help folks.

Collapsable Cell

I have a UITableView with two different custom table cells. The first cell appears normal after I start the app. The second cell will appear when you click on them.
Can anybody help me or has an idea?
Thanks a lot.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *MyIdentifier = #"customCell2";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if(cell == nil){
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.backgroundColor = [UIColor clearColor];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.textLabel.textColor = [UIColor grayColor];
cell.textLabel.font = [UIFont fontWithName:#"STHeitiSC-Light" size:9.0];
}
return cell;
}
Having done custom UITableViewCell in the past I usually handle the nib loading in the custom class itself.
The basic header for the custom cell.
#interface RequestsTableViewCell : UITableViewCell {
// Ivars.
}
// Properties.
- (id) initWithRequestModel: (RequestModel *) model style:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier forQueryType:(int) requestType;
// Other methods, etc.
#end
The custom cell with a designated initializer.
#implementation RequestsTableViewCell
- (id) initWithRequestModel: (RequestModel *) model style:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier forQueryType:(int) requestType {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:#"RequestsTableViewCell" owner:self options:nil];
self = [nibArray objectAtIndex:0];
requestModel = model;
queryType = requestType;
[self setRequestThumbnail];
[self setRequestCategory];
[self setRequestAddress];
[self setRequestStatusDate];
[self setRequestStatus];
[self setRequestFollowed];
[self setRequestComment];
[self setAppearance];
}
return self;
}
There would also be a custom xib for the custom UITableViewCell that corresponds and has the custom class set in the identity inspector.
In the UITableViewController.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellId = #"Cell Id";
RequestModel *request = nil;
// Other code for search, etc
request = [self.serviceRequests objectAtIndex:indexPath.row];
RequestsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if(!cell) {
cell = [[RequestsTableViewCell alloc] initWithRequestModel:request style:UITableViewCellStyleDefault reuseIdentifier:cellId forQueryType:queryTypeIndicator];
}
return cell;
}
It also sounds like you have more than one custom cell type in your question? Can you elaborate on how it is all supposed to function? You say that you have to click one cell to make another appear, can you explain that interaction?
I did something similar, but made the cell 'expand', instead of adding a new cell. Of course then you don't have two cells, but you can resize your one cell, add subframes,...
You can keep a boolean in your UITableViewCell object (BOOL cellIsExpanded), and set that on tap gesture. Then in drawRect of the TableViewCell, layout your cell accordingly.
Example code, on expand, make cell height 20-->80 and add a UIButton:
In the TableViewController, overload heightForRowAtIndexPath (this will resize your cell if 'expanded'):
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
YourEntity *record = [self.fetchedResultsController objectAtIndexPath:indexPath];
if (!record.cellIsExpanded)
return 20.; // cell is smaller if collapsed
else
return 80.; // bigger cell
}
In the TableViewCell, add or remove subframes:
#interface MyTableViewCell ()
#property(nonatomic) BOOL cellIsExpanded
#property(strong, nonatomic) UITextField *myTextField;
#property(strong, nonatomic) UIButton *clickMeButton;
#end
#implementation MyTableViewCell
- (void)drawRect:(CGRect)rect {
if(!self.cellIsExpanded){
// layout your collapsed cell, for example:
self.myTextField = [[UITextField alloc] initWithFrame:self.frame];
self.myTextField.text = #"Collapsed cell";
// remove button, only present in expanded view :
self.clickMeButton=nil;
}
else{
self.myTextField.text = #"Expanded cell";
// add button below textfield
self.clickMeButton = [[UIButton alloc] initWithFrame:CGRectMake(20, 20, 10, 10)];
}
}
#end

Resources