Xcode Table View erased after assigning custom class to controller - objective-c

I am using XCode 5, and I am having an issue with assigning class to a TableViewController
I made a form using tableViews within a TableViewController. The TableView has static cells that are the ones containing the textBoxes for user input.
The problem is that after designing the tableView, I added a custom class to it. When I run the program, the view is an empty table view, but in the storyboard looks like I design it.
So maybe after assigning the custom class (which is a new empty class UITableViewController) everything is either not being load or being re-instanced?
Added:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
return cell;
}
This is the default method.

You need to create custom class for UITableViewCell, instead of creating it for UITableView, as table view contains tableViewCell, as the default ones, but your cell contains textFields which is not by default. Let me know if you need more clarity here

None of the above helped me. This is what solved the problem:
What was going on? the problem was that even with Static Cells instead of Prototypes, the TableViews was trying to use his datasource to get the cells to display (The class that i assigned to its controller). It was easy then, i just had to erase the methods in the TableViewController Class.
Maybe because the class had an function that weren't suppose to be there, or because the TableView had the DataSource linked to it.
The result was a TableViewController with a static table.

Related

Reusing custom UITableViewCells, see old UIView pictures briefly before new pictures load

I have a custom UITableViewCell that contains a UIView, in which I display a couple of pictures.
In my tableView:cellForRowAtIndexPath: function, I call dequeueReusableCellWithIdentifier: to reuse old custom cells, and then I update them with new pictures.
The problem is that when I scroll quickly on my screen, I see flickers of the old pictures before the new ones are loaded, which is unattractive.
I've tried to fix this by:
implementing prepareForReuse in the custom TableViewCell implementation file; this led to the same three UIViews appearing over and over again, and in this case the new pictures stopped loading altogether
clearing the UIView right after calling dequeueReusableCellWithIdentifier by using a for loop to remove all subviews; the app now takes a really long time to load pictures.
What is the best way to fix this, and why do the above errors in my attempted fixes occur? Here is my current code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"Blah";
blahCell *someCell = (blahCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!someCell) {
//initialize cell
} else {
someCell.imageContainerView = nil;
}
... (other code here)
}
I'd try setting the cell's imageView property to nil as the first step in your table view data source method cellForRowAtIndexPath.
You can use this UIImageView Category by AFNetworking.
Whenever you have to set a new image you just need to call
[someCell.imageContainerView setImageWithURL:url placeholderImage:placeholderImage];
Now, whenever you scroll, if the image is not loaded you will see a placeholder image instead of seeing previous cell images.

Registered NIB, still getting assertion error when I use dequeueReusableCellWithIdentifier

I have a custom UITableViewCell class that I want to use to create custom table cells. I created the custom table cell's xib as well as its header and implementation files, all called RTRepairOrderTableCell.m/.h/.xib.
My issue is that even though I set the reuse identifier of the table cell to RTRepairOrderTableCell inside of the .xib file and registered the xib inside of my table view controller, I am still getting assertion errors when it tries to dequeue or create a new cell for use.
Inside of my view (table) controller I have the following:
- (void)viewDidLoad
{
[super viewDidLoad];
//Load the nib file
UINib *nib = [UINib nibWithNibName:#"RTRepairOrderTableCell"
bundle:nil];
// Register this Nib, which contains the cell
[self.tableView registerNib:nib
forCellReuseIdentifier:#"RTRepairOrderTableCell"];
}
There are no errors here and it finishes viewDidLoad just fine.
Inside of my cellForRowAtIndexPath I have the following:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
RTRepairOrderTableCell *cell = [tableView dequeueReusableCellWithIdentifier:#"RTRepairOrderTableCell" forIndexPath:indexPath];
return cell;
}
According to every tutorial I've seen, this should work so long as I have the reuse identifier set properly inside the xib file and I register that xib inside of viewDidLoad in the view controller class that will display the table cells, so I am at a loss as to why I am getting
*** Assertion failure in -[UITableView _dequeueReusableViewOfType:withIdentifier:], /SourceCache/UIKit/UIKit-2935.138/UITableView.m:5413
Turns out I had a few orphaned UIImage objects inside the nib file but outside of the UITableViewCell area, so it was throwing errors saying that the UITableViewCell needed to be the topmost view.
I faced this and it was driving me crazy. But it was my fault. I had set identifier #"Abc" in Nib file and I was registering the same nib file with some other identifie #"Xyz". Removed the identifier from nib, left that part blank and it worked like a champ. :)
This might be a rare case, but due to some sloppy copy pasta two different UITableViewCell custom classes used in my table had the exact same Identifier specified in the Xib.
Switching one of these cells to have a different Identifier in the Attributes Inspector fixed my Assertion failures.
Check if in your .xib there are no UI component outside main layout:
Label is not accepted
In this example, Label is not accepted and cause the exception

UITableViewCell as Header or Footer View

I know about UITableView reusable header and footer view
but in my case, i have UITableView Cells, which i need to place also in section headers and also in normal rows
if i use
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
MyCell * cell = [tableView dequeueReusableCellWithIdentifier:#"MyCell"];
// ...
return cell;
}
How does it work out with the reusing? (is the message to be available for reuse even than passed), or does this disable the cell reuse
The cells get dealloc'ed when they go off-screen. So they don't get reused. An easy way to verify this is to subclass UITableViewCell with the following
- (void)dealloc
{
NSLog(#"I got dealloc'ed");
}
and observe the console output as you scroll.
These has always worked fine. You first should create a prototype with that name, or register a custom nib with your custom section identifier. HOWEVER , I noticed this breaks in iOS 7 when you add new sections to the table dynamically. Reverting to a plain non-reusing UIView works. Really a shame!

Why can't I define IBOutlets when using custom "prototype tableviewcells"

I have my own table view cell which is defined in my storyboard. I have also defined a custom UITableViewCell class for this special cell. So when I want to create an Outlet for my custom prototype cell I get an error that the Outlet cant be created.
Since this is not possible I have to do some ugly workarounds and use the tags in IB to reference the individual labels and buttons later on in my code.
I don't really see why this is not possible and I wonder if working with tags and [myCell viewWithTag:] is the best possible way to go here?
Because the outlet is a one-to-one connection between your controller and a specific item within the view. In the case of a prototype cell, it is simply a description of a cell that can have an arbitrary number of different items (i.e. rows in your table view). How would the controller know which item you are referring to (e.g. row 5 or 500)? That is why you are receiving the error message.
Lucas provided one method to refer to your connection via tags which works perfectly well.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentInIB"];
UIImageView *img = (UIImageView*) [cell.contentView viewWithTag:1];
//img.image = ...
//Access you prototype cell here to alter its style, example:
[[cell layer] setCornerRadius:10];
[cell setClipsToBounds:YES];
return cell;}
I assume you are using dynamic prototypes - in the attribute inspector of the tableview in the storyboard there is an option to select "static cells" or "dynamic prototypes". You can do what you are trying to do if you select "static cells" as there is only one cell in your tableview at run time for each cell in the storyboard. Using this approach you will only be able to use the cells you create in storyboard i.e. you will not be able to select the number of cells in your code.

Search result of UISearchDisplayController has other cell layout and behaviour than searched table

I am using storyboarding. I have an UITableView with one prototype cell. This cell is of style "subtitle". I have added a segue from the cell to the detailed view. So when the user taps a cell it will open the corresponding editor... That all works great.
Now I added a UISearchDisplayController an a UISearchBar, implemented the delegates. That works very well.
But in the search result table the cells are of style "default" and are not tapable. What do I have to do to get a result table looking and behaving like the "unsearched" table?
I would like to contribute for answer #1 this is what I did and it worked for me
in the method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
instead of assigning the cell from the parameter tableView
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
assign it directly from the TableView on the view so you have to replace this
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
with this
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
Found the problem...
The method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
pulled the cell from the tableView, which is in the result case not the tableView from the storyboard but the resultTableView from the SearchDisplayController.
I now get the cell to display in both cases from the table view in the storyboard and now it works.
I've been using ios 7.0 and Xcode 5.0. I found that search display controller is using the same tableview layout as the delegate view controller. All you have to do is judge if the current tableview is the delegate view controller's tableview, or the search display controller's tableview. But remember to add the sentence
tableView.rowHeight = self.tableView.rowHeight;
in the following code snippet:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if (tableView == self.searchDisplayController.searchResultsTableView)
{
tableView.rowHeight = self.tableView.rowHeight;//very important!
return [self.searchResults count];
}
else
{
...
return ...;
}
}
if you forget to implement that sentence, then the row of the table view of search display is only as high as a default row, which makes you think it doesn't look like the "unsearched" table.
There is a possible answer to this here. It may not work entirely for you, but as I explained, the UISearchDisplayController creates the table view.
Check the documentation and you can get a better understanding of it, but it states:
You initialize a search display controller with a search bar and a
view controller responsible for managing the original content to be
searched. When the user starts a search, the search display controller
is responsible for superimposing the search interface over the
original view controller’s view and showing the search results. The
results are displayed in a table view that’s created by the search
display controller. In addition to the original view controller, there
are logically four other roles. These are typically all played by the
same object, often the original view controller itself.
In my case UISearchDisplayController was using right cell type (custom) but height of cell was wrong so I had to use
(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
method to fix it.