I need to enable multiple selection in my tableview and also i need to keep track of what i have selected (like save it to an array or something). My approach so far;
- (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=[arrayobject objectAtIndex:indexPath.row];
bool xx = [[allmyselectedobjects objectAtIndex:indexPath.row] containsIndex:1];
if (xx) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
}else{
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
return cell;
}
and the didSelectRowAtIndexPath method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self.cuisineTableView cellForRowAtIndexPath:indexPath];
if ([cell accessoryType] == UITableViewCellAccessoryNone) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
[self.allmyselectedobjects insertObject:1 atIndex:indexPath.row];
}
else {
[cell setAccessoryType:UITableViewCellAccessoryNone];
[self.allmyselectedobjects insertObject:0 atIndex:indexPath.row];
}
}
I could click multiple records, but when i scroll down i see other cells also ticked with the check mark (which i didn't select). I have been trying this for days now, can someone help me fix this code ?
A given cell instance is recycled and used for many rows. Store your checked indexPathes but not the cells.
Right before
Bool xx =
add this:
[cell setAccessoryType:UITableViewCellAccessoryNone];
It seems you are using an NSIndexSet to store checked cells. So just insert the index of the selected cell and test it.
// Test
BOOL xx = [allmyselectedobjects containsIndex: indexPath.row]
// Selected cell
[allmyselectedobjects addIndex: indexPath.row]
// Unselected cell
[allmyselectedobjects removeIndex: indexPath.row]
i have a problem with willDisplayCell it doesn't stop fetch Xml from the url
my code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [itemsToDisplay count] + 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] autorelease];
}
if (indexPath.row == [itemsToDisplay count]) {
cell.textLabel.text = #"Load More...";
} else {
MWFeedItem *item = [itemsToDisplay objectAtIndex:indexPath.row];
cell.textLabel.text = item.title;
}
return cell;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == [itemsToDisplay count]) {
// Parse
NSURL *feedURL = [NSURL URLWithString:#"http://gdata.youtube.com/feeds/api/users/RayWilliamJohnson/uploads?v=2&alt=rss&sort_field=added&start-index=21&max-results=20"];
feedParser = [[MWFeedParser alloc] initWithFeedURL:feedURL];
feedParser.delegate = self;
feedParser.feedParseType = ParseTypeFull; // Parse feed info and all items
feedParser.connectionType = ConnectionTypeAsynchronously;
[feedParser parse];
[self.tableView reloadData];
}
}
its look like he is in kind of loop that doesnt stop fetch xml
so how can i fix it so i will only called once?
tnx
The problem is that you have called reloadData within tableView:willDisplayCell:. reloadData will cause every UITableViewCell to get drawn again, means willDisplayCell will get called for every cell that will be visible on screen. Seems to me like you have an infinite loop there.
tableView:willDisplayCell: is definitely the wrong place to be doing that XML parsing. willDisplayCell should just be used to prepare the UI. I can't say for certain, but perhaps a better place to the XML parsing would be in your view controller's init method.
I have a segmented tableView that loads all the data in all the cells of all the sections.
There is a textField in each cell.
The tableview doesn't fit the iPad screen completely, and I can't access all the invisible cells in order to read/save data. And when I make changes in "textField", then scroll up, the scroll down, all the changes are gone.
I need to load all the cells, even invisible once, to be able to access them.
I am sorry, I just started working with tables a few days ago...
I think that this problem has something to do with reusable cells, but not sure how to resolve it.
Looking for your help, please.
initialization:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 400, 30)] ;
textField.enabled = NO;
cell.accessoryView = textField;
[textField release];
}
UITextField *textField = (UITextField*)cell.accessoryView;
if(indexPath.section == 0)
cell.textLabel.text = [idenInfo objectAtIndex:indexPath.row];
else if (indexPath.section == 1)
cell.textLabel.text = [prodInfo objectAtIndex:indexPath.row];
else if (indexPath.section == 2)
cell.textLabel.text = [visInfo objectAtIndex:indexPath.row];
if(indexPath.section == 0)
textField.text = [idenInfoRez objectAtIndex:indexPath.row];
else if (indexPath.section == 1)
textField.text = [prodInfoRez objectAtIndex:indexPath.row];
else if (indexPath.section == 2)
textField.text = [visInfoRez objectAtIndex:indexPath.row];
textField = nil;
return cell;
}
First of all : you don't have to load all the cells including the invisible ones. That's the whole point of the UITableView and MVC Pattern : separate your views from your data.
What you'll want to do is update your Data source (that is idenInfoRez, prodInfoRez and vizInfoRez in your case) when the user has changed a value inside a textField. So you'll have to set your UIViewController as the delegate of each textfield and update the values as the user types in.
[UIView beginAnimations:#"ShiftUp" context:nil];
[UIView setAnimationDuration:0.0001];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger section = [indexPath section];
static NSString *CellIdentifier = #"Cell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
cell = objCustCell;
cell.selectionStyle = UITableViewCellSelectionStyleNone ;
}
if (section == 0) {
switch (indexPath.row) {
case 0:{
cell.lable.text = #"Date of Birth";
cell.field.placeholder = #"Birth Name";
break;
}
case 1:{
cell.lable.text = #"Enter Your Name";
cell.field.placeholder = #"Full Name";
break;
}
default:
break;
}
}
[UIView beginAnimations:#"ShiftUp" context:nil];
[UIView setAnimationDuration:0.0001];
// [UIView beginAnimations: #"ShiftUp" context:nil];
NSLog(#"Load cellfor raw at index ");
// Configure the cell.
return cell;
}
Note : UIView animation will not allow text field to move away data or any UIcontroller will remain same in its old state !!
Don't Commit animation otherwise it will not working !!
What you can do is this: in the Editing Changed event of each of the TextField store the value contain in the text field in an NSMutableArray whose number equal the number of cells. i.e.
-(IBAction) EditingChanged: (id) sender
{
UITextField *txt =(UITextField*)sender;
NSString* str =[[NSString alloc] initWithString: txt.text];
//get current text string
NSInteger path =[tableView indexPathForSelectedRow].row;
// get currently selected row, this could be a bit different depending on the number of sections
[yourMutableArray insertObject: str atIndex: path];
[str release]
}
You can then populate the TextField with the values from the NSMutableArray anytime the cells are recreated i.e.
(UITableViewCell *) tableView: (UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath
{
...... // create the cells here and use viewTag to get the textFields
textField.text= [yourMutableArray objectAtIndex:indexPath.row];
//This may be a bit different depending on the number of sections.
}
Also, note that it might be advisable to initialize yourMutable array to the capacity of the number of cells.
I am sorry if the codes are not well formatted as this is my first post on stackoverflow - also there might be some typos in the code. Hope this helps someone.
every time we allocate the cell to different data,the data will not reloading the cell,every time the data override previous data, before allocate the cell to clear cell,
like as cell=nil
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell=nil;
//it clear data in the cell
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 400, 30)] ;
textField.enabled = NO;
cell.accessoryView = textField;
[textField release];
}
You're right, the problem is the cells will be reused. There are two solutions to the problem, the quick and dirty one would be to not use reusable cells:
Remove this:
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
And just leave this:
UITableViewCell * cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 400, 30)] ;
textField.enabled = NO;
cell.accessoryView = textField;
[textField release];
That should be ok, if you have only a small number of cells in your tableview (about fewer than 50).
The better solution would be to leave cell reuse on, and fill their textfields as they are requested. The approach differs from app to app, but you basically never should access the cells directly, and store the data of the cell somewhere else, e.g. an NSArray of NSStrings. You could then manipulate the NSArray. Your cellForRowAtIndexPath method would look something like this:
textField.text = [arrData objectAtIndex:indexPath.row];
I'm aware that to preserve memory usage, UITableViewCells are reused when scrolling. I have some custom UITableViewCells that have UITextFields in them. After text is inputted to the UITextField, and I scroll, that text is lost because of the cell reuse.
How can I make this text persist through scrolls? I'm thinking I can store each cell's text in its own index of an NSMutableArray. Then, when the cell is reused, I can repopulate it with the array data.
How would I go about doing this? Would someone be so kind as to post a code sample?
sample.h
#interface sample : UIViewController <UITableViewDataSource,UITableViewDelegate,UITextFieldDelegate>
{
}
#end
sample.m
-(void)viewWillAppear:(BOOL)animated
{
arrData = [[NSMutableArray alloc]init];
for (int i=0; i<10; i++) // 10- number of fields
[arrData addObject:#""];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [arrData count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UITextField *txt = [[UITextField alloc]initWithFrame:frm];
txt.autocorrectionType = UITextAutocorrectionTypeNo;
txt.tag = indexPath.row;
txt.delegate = self;
txt.text = [arrData objectAtIndex:indexPath.row];
[cell addSubview:txt];
[txt release];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[arrData replaceObjectAtIndex:[textField tag] withObject:textField.text];
}
I have an array of URL Links that I'm trying to load into a Grouped UITableView. The goal being that I have numberOfSectionsInTableView return [url count] so I can have number of sections equal to the number of url links. Then in numberOfRowsInSection returns 1 so I only populate 1 URL for each section.
The trouble I'm having is to ensure that cellForRowAtIndexPath won't keep grabbing the first url link. I suspect it's because it's always grabbing the first url because the rowIndex is always zero.
Any ideas how to ensure that each cell in my UITableView is populated with a different url link?
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [newsItems count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease];
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.numberOfLines = 5;
}
// Configure the cell. Get the title of the news item that was parsed out
int newsItemIndex = [indexPath indexAtPosition: [indexPath length] - 1];
[cell.textLabel setText:[[newsItems objectAtIndex: newsItemIndex] objectForKey: #"link"]];
return cell;
}
From what i see here you are making many sections with 1 row each...im not sure that ayou are getting the index correctly you can do something like this
int newsIntemIndex=indexPath.section
that should do it for you