delete UITableViewCell programmatically - objective-c

I was wondering if it's possible to remove empty cells (empty = cells with no textLabel) after all the cells are created in a UITableView.

Why do you have empty cells? Are you using a consistent technique to control both the number of cells in your table and the content of those cells?
If you're using a UITableViewController, then your controller is automatically declared as the tableview's datasource. If you're using a UIViewController, then you'll declare it as comforming to the UITableViewDataSource protocol (and connect it up in Interface Builder).
Either way, as the tableview's datasource, your controller is required to implement two methods:
– tableView:cellForRowAtIndexPath:
– tableView:numberOfRowsInSection:
Presumably you're providing the data for the tableview with an array or other means inside -tableview:cellForRowAtIndexPath:. Inside this method the cell's label will be set from an entry in your array. And inside tableView:numberOfRowsInSection: you'll be doing something like [myArray count] to return the number of cells. tableview:cellForRowAtIndexPath will be called as many times as you tell it to (dictated by what you provide in tableview:numberOfRowsInSection:). If the datasource array changes, and you'd like to reflect the changes in your tableview, then you can call
[self.tableview reloadData]; //if inside a UITableViewController
[self.myTableViewOutlet reloadData]; //if inside a UIViewController
Note that reloadData reloads the entire tableview, so in some cases this may be computationally expensive. In this case, instead of calling reloadData you can focus on individual rows with the method: deleteRowsAtIndexPaths:withRowAnimation: (see UITableView Class Reference)

As the app delegate, you are responsible for providing cells. It is your responsibility to return every cell, and the number of cells in the table. Therefore as the app delegate you should have a means (be it by NSMutableArray or otherwise) to mutate the data that you return to the table view.

Related

JSON, cellForRowAtIndexPath bug

Struggling to find where fault is with my code. On first view load, everything works and loads fine as it should, but when i revisit that view, it seems that the first two cells are empty. I logged the dictionary (dict) in viewWillAppear: and it logs the data fine, so error has to be in cellForRow method. Take a look at my method, and see where i'm going wrong, the third cell populate third piece of data, so i'm totally stumped, but the first two cells are completely blank, no data.
http://pastebin.com/Va84MG5g
First of all, why are you doing all of that insane UITableViewCell customization inside of your tableView:cellForRowAtIndexPath: method? Create a custom UITableViewCell subclass and do the set up there.
In the class's initWithStyle: method, add all of your subviews with a frame of CGRectZero, because at initialization, the table view cell doesn't know how big it is. You can set text alignments, colors, etc. here as well. Then, in layoutSubviews, go ahead and set all the frames. Override prepareForReuse and set things like your UIImageViews to nil. This will help with performance for reused cells.
As for why you're not seeing your data in your first two cells, my initial thought is that it has something to do with the way you're setting up your cells for reuse. You're asking your tableView to dequeue a regular UITableViewCell and only creating all of these subviews if the returned cell is nil. So what happens when it returns a UITableViewCell? You skip the part where you alloc/init all these subviews, and so you're basically adding nothing to the cell. I feel if you create a custom subclass and ask your UITableView to dequeue that instead, you'll get the result you're looking for.
NOTE: If you're targeting at least iOS 5, you can create your UITableViewCell's layout in a nib and register the nib with the table view. Doing so will guarantee that you always get a dequeued cell, and you never have to do your if (cell == nil) check. If you're targeting iOS 6, you can register a UITableViewCell subclass.

Receiving notification on a UICollectionViewCell's (or UITableViewCell's) removal from its parent collection or table view

Background:
I have a UICollectionViewController that shows items in one of two modes, which the user can toggle between. Each mode uses a different class of UICollectionViewCell. Let's call these modes "list view" and "grid view".
When I switch modes, I call .reloadData on the UICollectionView, which redraws the collection view using the correct cell classes. Everything works fine here.
Now: Inside the UICollectionViewCell subclass for one type of cells, I want to be notified when the collection view that contains it switches modes. Visually, a cell which was on-screen vanishes; the collection view is drawn fully with the other type of cell. When switching back, the cell is re-displayed.
Question:
How can I be notified when a UICollectionViewCell is "removed" (i.e., no longer shown; I'm not sure what's happening under the hood yet) from its parent collection view?
Notes:
prepareForReuse is not called on the cell when the collection view's updateData causes the cell to no longer be included.
willTransitionFromLayout:toLayout: (an empty layout?) is not called.
Overriding didMoveToSuperview is of no help; it is not called.
Observing .hidden or .alpha on the cell does not work.
The cell's dealloc is not called; it sticks around in the reuse queue.
Something in the cell must be changing that I can observe or hook into, what is it?
Update: UICollectionViewDelegate has this method, which from the documentation seems like it does what I am asking:
collectionView:didEndDisplayingCell:forItemAtIndexPath:
Original answer:
I got this working as desired by having the UICollectionViewController manually notify visible cells of impending doom with this method when I'm about to toggle and call reloadData:
- (void)notifyCellsWillBeHidden {
for (UICollectionViewCell *cell in self.collectionView.visibleCells) {
if ([cell respondsToSelector:#selector(willBeRemovedFromCollectionView)]) {
[cell performSelector:#selector(willBeRemovedFromCollectionView)];
}
}
}
These cells can then do what they need to do if they implement the above method.
Calling prepareForReuse may not a good idea because it will be called again before the cells are re-displayed, if this is a problem.
I'm still curious whether there is a way for a cell to receive notification that it is going to be made non-visible without an explicit call.

UITableView with NSFetchedResultsController reloadData but does not move cell

I have a UITableView backed with an NSFetchedResultsController.
When the controller goes off screen I follow suggestion to resign as fetched controller delegate.
Therefore I totally rely on context notification and reloadData.
Basically, I analyze the notification and set a flag needsReload=YES when in the inserted/updated/deleted object there's a relevant entity and property for the table.
On viewWillAppear I check for this variable and call reloadData.
However the NSFetchedResultsController has an sort ordering on NSManagedObject attribute 'pname'.
When in other view controller I update pname say from 0name to Zname, I can intercept the context did change notification and the table is correctly reloaded at next viewWillAppear.
The problem is that I would expect the cell to goes at bottom because of the sort ordering, but instead it remains updated at top, I suppose because reloadData only updates visible cell. How can I solve this ?
The fetched results controller does not track changes in the managed object context anymore if you set its delegate to nil.
Therefore, after re-assigning a delegate, you have to call
[self.fetchedResultsController performFetch:&error]
first and then
[self.tableView reloadData];

tableView:cellForRowAtIndexPath: method question

First of all I beg your pardon but I am a newbie and trying to learn Objective-C. I was studying the UITableView when I found this method:
tableView:cellForRowAtIndexPath:
I read the reference for UITableView and some examples but I don't understand one thing: what calls this method and what validates its parameters (eg. indexPath)?
This method is called by the UITableView when the table needs another cell to display. The table view calls the tableView:cellForRowAtIndexPath: method on the object pointed to with the table view's dataSource property.
So if you've got a view controller, you implement the tableView:cellForRowAtIndexPath: there, call [myTableView setDataSource:self] and the table view will call tableView:cellForRowAtIndexPath: once it needs to display a new cell for the given index path (row).
Of course, you also need to implement the other required method tableView:numberOfRowsInSection of the UITableViewDataSource protocol and maybe a few other of its methods. Otherwise the table view would even know how many sections and rows it should display.

Saving reference to UITableViewCell

I have 5 cells in a tableview that are all custom. Meaning, I've created a xib with a tableviewcell and created a corresponding cellController. The xib has two labels named name and size. The user taps a row, triggering didSelectRowAtIndexPath. From there a timer is started. At some point the timer finishes. Here I need to assign text to the selected cell's name label. How do I get the selected cell reference and keep it for assigning? Or, is there a better way to do it?
The UITableView instance method
-(UITableViewCell*) cellForRowAtIndexPath: (NSIndexPath*)indexPath
will allow you to get a pointer to the cell.
Simply store the row+section info from NSIndexPath argument of the didSelectRowAtIndexPath event. Then, when the timer finishes, build a new NSIndexPath and call cellForRowAtIndexPath. Also be prepared for it to return nil if the cell is no longer in view.