UITableView/UITableView Cell Index Issue - ios

I am making a bookmarks page for my web browser and the problem is that everytime I add a new object, I have to set the properties since I created a custom cell (I must set the text of two labels) and so I need a way to only edit the newly added object...I'm familiar with indexes but not able to come up with any solutions to this problem...For example when I bookmark the first page its fine, but once I bookmark 2 pages the 2 cells are the exact same...Any Ideas?
Heres My Code:
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CustomCell";
CustomCell *cell = (CustomCell*)
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:nil options:nil];
cell = (CustomCell *) [nib objectAtIndex:0];
}
// Set up the cell...
NSString *theTitle=[webView stringByEvaluatingJavaScriptFromString:#"document.title"];
NSString *currentURL = webView.request.URL.absoluteString;
cell.websiteTitle.text = theTitle;
cell.websiteURL.text = currentURL;
universalURL = currentURL;
return cell;
}
When setting up the cell I need to point to the newest cell!
Thank You In Advance!

Your approach cannot work. You cannot use the cells as the store for the titles and URLs, because cells are reused (and because it is bad design). A table view allocates only cells for the visible rows and reuses a cell for a different row when you scroll the table view.
Instead you should store the titles and URLs in a separated data source, for example an NSMutableArray *bookmarks where each item in the array is a NSDictionary with "title" and "URL" keys.
To add a bookmark to your table, you just append a new entry to the array and call reloadData on the table view.
The tableView:cellForRowAtIndexPath: method can then use the bookmarks array with the row number indexPath.row to fill all elements of the cell.

Related

hold data on tableview cell ios

I'm newbie in IOS and again i face another issue. How can i prevent data vanish from a table cell when i scroll a tableview.
I'm using the code below to load data on the table...Works fine but the data disappear when table cell go in not visible to the screen.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
list = [self.listas objectAtIndex:[indexPath row]];
static NSString *CellIdentifier = #"drop";
item_drop *cell = (item_drop*) [tabela_listas dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"item_drop" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.texto_drop.text = list.nome_lista;
return cell;
}
In android i used a holder to do it. There is anything similiar on IOS?
Since you are using reusable cells of a custom subclass of UITableViewCell, make sure you register the cell identifier in the UITableView, associating it to your custom cell type. i.e:
[yourTableView registerClass:[item_drop class] forCellReuseIdentifier:#"drop"];
You typically do this when you configure subviews in the UIViewController that controls the view your UITableView is a part of, in viewDidLoad.
With that in place, you should never hit the code inside if (cell == nil).

UITableView Disable the row where not visible to user

I have a custom UITableView with (990x580 pixels), where within each cell of the table there is a text field, the text fields are differentiated by the tag:
cell.myTextField.tag = indexPath.row;
Assuming I have 20 rows in my table, causing me to see all rows of the table will have to use the scroll (since the table only has 990x598 pixels)
Assuming that we are looking to line number 20 of the table, and the line number 1 is no longer visible (unless if I use scroll to go up), I would like to know why when I try to pick up existing information within the text field whose tag is equal to 1 the application does not return me anything?
I realized that when this text field not visible to the User, it seems to become disabled, would like to find a way for it to not turn over the lines in which are not available to the User, this my Tableview below:
- (UITableViewCell *)tableView:(UITableView *)tableView2 cellForRowAtIndexPath:(NSIndexPath *)indexPath
{//Ja explicado anteriormente
static NSString *simpleTableIdentifier = #"ComissoesTableViewCell";//Ja explicado anteriormente
ComissoesTableViewCell *cell = (ComissoesTableViewCell *)[tableView2 dequeueReusableCellWithIdentifier:simpleTableIdentifier];//Ja explicado anteriormente
if (cell == nil){//Ja explicado anteriormente
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ComissoesTableViewCell" owner:self options:nil];//Ja explicado anteriormente
cell = [nib objectAtIndex:0];//Ja explicado anteriormente
}
cell.data.tag = indexPath.row;
return cell:
}
UITableView works by automatically reusing cells when they scroll out of the visible part of your table. That makes the cell information to reset as you configure the reused cell again.
You need to store your persistent information at the viewController level (e.g., in a NSArray or a NSDictionary). Consider using an NSDictionary and storing your cell content NSStrings indexed by the cell's indexPath.
Also note that the following
if (cell == nil){//Ja explicado anteriormente
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ComissoesTableViewCell" owner:self options:nil];//Ja explicado anteriormente
cell = [nib objectAtIndex:0];//Ja explicado anteriormente
}
is no longer recommended.
If you register a nib or class for your simpleTableIdentifier (e.g., using - (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier) it's guaranteed that the deque method won't ever return nil, as it will automatically create new cells as it needs them.

List Songs in UITableViewController on iPhone? Works in Storyboard, NOT without it

I am NOT using Storyboards. I have a UITableViewController and I would like to display a list of songs from user's library.
This is my code so far:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
MPMediaQuery *songsQuery = [MPMediaQuery songsQuery];
NSArray *songs = [songsQuery items];
return [songs count];
}
But for this block, I do not know what to do. I found a tutorial for storyboards, but it is not valid here:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
MPMediaQuery *songsQuery = [MPMediaQuery songsQuery];
NSArray *songs = [songsQuery items];
MPMediaItem *rowItem = [songs objectAtIndex:indexPath.row];
cell.textLabel.text = [rowItem valueForProperty:MPMediaItemPropertyTitle];
cell.detailTextLabel.text = [rowItem valueForProperty:MPMediaItemPropertyArtist];
return cell;
}
This only works in Storyboard because I can click the cell in the storyboard and rename its identifier to 'Cell'. In the .xib/nib file in my project, all I see is a view filled with country's names. I cannot click a single cell, I can only edit the whole table.
My question is, what code must I put in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath in order to display this list?
Thanks!
The basic problem you're encountering is that, when used in conjunction with a properly configured storyboard, dequeueReusableCell... will create a cell of the appropriate type if none is available to dequeue.
If you are using a standard UITableViewCell, you can use the following block to dequeue and/or create an appropriate cell:
static NSString* reuseIdentifier = #"Cell";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
if(!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
}
If, on the other hand, you're loading your cells from a nib file, you can just add:
[self.tableView registerNib:[UINib nibWithNibName:nibName bundle:[NSBundle mainBundle]] reuseIdentifier:reuseIdentifier];
to your viewDidLoad.
Alternatively you can use registerClass:forCellReuseIdentifier: if you have a custom cell class that sets up it's own subviews.
First off, check if the cell being dequeued is nil or not.
The next thing I can see a problem with is the fact that you aren't really loading anything in cellForRowAtIndexPath:. Basically what this method does is dequeue some cell which has been marked for reuse in an attempt to save memory, and if you haven't set the proper Restoration Identifier in the Interface Builder, then there is no way to know which Nib you want initialized to use here.
What used to happen (or at least my understanding of it) is that in cellForRowAtIndexPath: you would have to check if the cell returned from dequeueReusableCellWithIdentifier: was nil, and if so, you'd have to create the cell from scratch using something like this:
SomeCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
{
cell = [[[NSBundle mainBundle] loadNibNamed:#"SomeCellNib" owner:self options:nil] objectAtIndex:0];
}
and this would ensure that if no cell was dequeued that you would load up a fresh one from scratch, although I believe that Apple actually changed how dequeueReusableCellWithIdentifier: works, and as long as you've registered the Identifier, it will create a new cell for you.
For this reason I'm not sure what the problem is if you've set the Identifier properly, and all I can suggest is to try and manually load the cell.
EDIT: I forgot to mention where Restoration Identifiers can be set. The Restoration Identifer field is in the Identity tab, or the third tab in the Interface Builder:
To create a prototype cell inside a .nib, drag a UITableCellView out from the right sidebar. From there you can create your cell prototype, as well as set the cell reuse identifier.

How do I use two different custom UITableViewCell subclasses in a single table?

How to I properly display to different UITableViewCell subclasses within the same UITableView?
I am using the storyboard for this question. I am trying to use two different subclasses of UITableView cell in a single table. The idea that TTTextFieldCells know how to show a text box and TTPickerCells know how to present a UIPicker to the user. There the protocol TTTableViewCell specifies a single selector: [setCellDetails (NSDictionary*) cellDetails] Each UITableViewCell subclass knows what to do with the cellDetails Dictionary to setup the cell.
-(NSArray *)tableData {
if (!_tableData) {
 _tableData =
 #[ // Sections
#{ // Section Details
 kSectionName:#"Scout Information"
 ,kRows:#[ // Rows
#{// Cell Details
 kBoundProperty:self.scoutName
 ,kReuseIdentifier:kTextFieldCell
 ,kLabel:#"Name"
 ,kPlaceholderValue:#"Scout's Name"
 }
,#{
 kReuseIdentifier:#"TTPickerCell"
 ,kLabel:#"Type"
 ,kPlaceholderValue:#"Cadet, Junior, etc..."
 }
,#{
 kBoundProperty:self.yearsScouting
 ,kReuseIdentifier:kTextFieldCell
 ,kLabel:#"Years"
 ,kPlaceholderValue:#"Years of Experience"
 ,kKeyboardStyle:#(UIKeyboardTypeNumberPad)
 }
]
 }
,#{ // Section Details
 kSectionName:#"Parent Information"
 ,kRows:#[
#{
 kBoundProperty:self.parentName
 ,kReuseIdentifier:kTextFieldCell
 ,kLabel:#"Name"
 ,kPlaceholderValue:#"Parents's Name"
 }
]
 }
];
}
return _tableData;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
// Line A
[self.tableView registerClass:[TTTextFieldCell class] forCellReuseIdentifier:#"TTTextFieldCell"];
// Line B
[self.tableView registerClass:[TTPickerCell class] forCellReuseIdentifier:#"TTPickerCell"];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary* cellDetails = self.tableData[indexPath.section][kRows][indexPath.row];
NSString* reuseIdentifier = cellDetails[kReuseIdentifier];
// Line C
UITableViewCell<TTTableViewCell> *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
[cell setCellDetails:cellDetails];
return cell;
}
Now, here is the question. If I comment out line A and B, then the TTTextFieldCells are displayed correctly. But Line C will fail because it is attempting to call the TTTextFieldCell init with a TTPickerCell object, and failing because the TTPickerCell object doesn't have the same properties. If I uncomment Line A and B then the cell styles default to UITableViewCellStyleDefault and they don't display the custom controls. Oddly, if I comment out Line A, and uncomment line B, then the TTTextFieldCells look great, but the TTPickerCells default to UITableViewCellStyleDefault.
It seems that if I do not register a class, dequeue will return an instance of the first prototype cell class. If I register the class then the cell defaults to UITableViewCellStyleDefault.
Also of note, the initWithStyle:reuseIdentifier: selectors only get called if the class is registered.
So, how to I properly display to different UITableViewCell subclasses within the same UITableView? Do I have to forgo using the storyboard to design the cell?
Thank you in advance.
You do not want to be calling tableView registerClass:... inside of cellForRowAtIndexPath. Instead, you should be registering your classes/nibs a single time. This is often done in the controller's viewDidLoad method. Your cellForRowAtIndexPath implementation can then look something like this:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary* cellDetails = self.tableData[indexPath.section][kRows][indexPath.row];
NSString *reuseIdentifier = (/*some condition*/ ? #"TTTextFieldCell" : #"TTPickerCell");
UITableViewCell<TTTableViewCell> *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
[cell setCellDetails:cellDetails];
return cell;
}
EDIT: I should mention dequeueReusableCellWithIdentifier always returns a cell from iOS 6 on. If you are targeting an earlier version of iOS you need to account for creating cells in the even this method returns nil.
Ok, this is what I found to be the answer.
Do not register the class for the reuse identifier. Comment out lines A and B.
Do not copy and paste prototype cells, unless you take great care to review the IBOutlets. The pasted prototype cell doesn't care what UITableViewCell subclass you assign it too, it doesn't validate the IBOutlets are present.
Fixed up #2 and all was well.
Doh!
I used 2 types of cells loaded from NIB and NSMutable array with my objects, objects have texts, titles and imagens that i want to use in cells. In method cellForRowAtIndexPath... u put content from objects to cell. U can init without nib.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (your condition){
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CellClass1" owner:self options:nil];
CellClass1 *cell = (CellClass1 *)[topLevelObjects objectAtIndex:0];
}else{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CellClass2" owner:self options:nil];
CellClass2 *cell = (CellClass2 *)[topLevelObjects objectAtIndex:0];}
//get your content for cell at array or your own estructure
Content *content = [contents objectAtIndex:indexPath.row];
cell.description.text = content.description;
return cell;
}

UITableViewCells not appearing initially

I have three UITableViews that should look identical. Each is placed inside a different subview of a UIScrollView. As I scroll, I can see each table. The first table appears perfectly. However, only the background color shows for the second and third tables.
tableView:cellForRowAtIndexPath: is being called for every row for each table, where I insert a subview into the cell's contentView. The subview has already been created before this method is called and is reused across the three tables for a given row (in an attempt to make tables look identical).
I made two interesting discoveries:
Although the cell doesn't show initially, it will appear after scrolling to hide the row and then show it again.
When the cell appears after scrolling, it has been moved from another table. It no longer appears in the table where it had been showing.
Here's my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"PlotCellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"PlotCell" owner:self options:nil];
if ([nib count] > 0)
cell = self.plotCell;
else
NSLog(#"Failed to load AlertCell nib!");
}
// Set up the cell...
NSUInteger row = [indexPath row];
AppDelegate *del = (AppDelegate *)[[UIApplication sharedApplication] delegate];
ResultSet *rs = del.resultPlots;
CPTGraphHostingView *cellPlotView = [rs.hostingViews objectAtIndex:row];
cellPlotView.frame = cell.contentView.bounds;
cellPlotView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[cell.contentView insertSubview:cellPlotView atIndex:0];
return cell;
}
cellPlotView refers to the subview already created.
Any idea how to fix this so I can see all my tables correctly showing as I scroll? It's as if the cells can't reuse content. Thanks.
View can have only one superview. So create 3 identical CPTGraphHostingView views.

Resources