Getting the header view height of a section - objective-c

I've implemented the
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
delegate method and within that I implement this piece of code
UITableViewHeaderFooterView *header = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:#"paymentFormHeader"];
header = (UITableViewHeaderFooterView *)view;
Then I try the and assign a UIView from the header with
UIView *header = [self.tableView dequeueReusableHeaderFooterViewWithIdentifier:#"paymentFormHeader"];
and get a null value in return. This is my first time using this method so I'm probably not understanding it correctly and I noticed that it didn't ask for an indexPath. Any help with this would be greatly appreciated. Thanks.

There are a few issues here. The first is that you're not using the right method to set up the header. The method you're using (..willDisplayHeaderView..) is there to let you know when a header you've already set up is about to be displayed so you can do any additional setup or tracking after that point.
You will want to implement 2 methods to get this working:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
and
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
Your next issue is how you are trying to dequeue the view. You either need to check for a nonexistent dequeued view and initialize one manually with that reuse identifier, or just register the appropriate class in advance. I recommend registering it in advance. So to fix this, in viewDidLoad or at some point after your UITableView has been initialized, register the class like this:
[myTableView registerClass:[UITableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:#"paymentFormHeader"];
That will make sure you will always get a valid initialized view of that type for that reuse identifier when you try to dequeue it.

Related

Couldn't set values in Custom Cell in UITableView from NSMutableArray

Help me to get rid of with this dilemma that occurred yet when I tried to dequeued the cell (Custom Cell).Below are some steps and Indents that I did with my Project.
The very first is I drag and drop a UITableView in my ViewController and add the ViewController.h doing after this
#interface ViewController : UIViewController <UITableViewDataSource,UITableViewDelegate>
Then I made a Custom Cell with 3 UILabels and change the height of the Cell to 65.
After that I made a property in ViewController.m
#property (nonatomic,strong) NSMutableArray *myTodoTitles;
Then in method(ViewDidLoad) I did.
myTodoTitles = [NSMutableArray arrayWithCapacity:10];
[myTodoTitles addObject:#"Go for ride"];
[myTodoTitles addObject:#"Do University Assignments"];
[myTodoTitles addObject:#"Watch Show"];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[self.myTodoTitles count]-1 inSection:1];
[self tableView:self.myTodoTable cellForRowAtIndexPath:indexPath];
After that I just did these things in my ViewController.m
#pragma mark - Table view data source
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *myIdentifier = #"TodoCell";
TodoCell *todoCell = (TodoCell*)[tableView dequeueReusableCellWithIdentifier:myIdentifier];
todoCell.todoTitleLabel.text = [self.myTodoTitles objectAtIndex:indexPath.row];
return todoCell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [myTodoTitles count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
But when I run the project it dequeued nothing.
Please help
Most likely that you have not connected your viewController to be the dataSource of your tableView. This could be done from Interface Builder or from the code. You can easily check it by adding self.myTodoTable.dataSource = self; at the very first of viewDidLoad method.
And also: what did you mean by `
[self tableView:self.myTodoTable cellForRowAtIndexPath:indexPath];`
in viewDidLoad ? Seems like you wanted to do
[self.myTodoTable reloadData];
There are to UITableView methods with similar name:
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier
and
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier
forIndexPath:(NSIndexPath *)indexPath
The first one will try to dequeue a reusable cell. If it returns nil you are responsible to create appropriate cell.
The latter one will always return a valid cell: you will have to register a certain class or NIB with that tableview beforehand though. Docs.
EDIT:
As ReDetection pointed out: first method will also return a valid cell as long as you had registered a proper class (or nib) with that tableview.
In your case that means that you should register TodoCell in viewDidLoad with your tableView.
If TodoCell is made without .xib:
[self.tableView registerClass:[ToDoCell class]
forCellReuseIdentifier:#"TodoCell"];
Or if it is made with .xib.
[self.tableView registerNib:[UINib nibWithNibName:#"TodoCell"
bundle:nil]
forCellReuseIdentifier:#"TodoCell"];
EDIT2:
Your code also seems to be missing the dataSource setting. Something like:
self.tableView.dataSource = self;
This will trigger initial reload.
You'd probably want to set a delegate (since your controller claims to adopt that protocol) in the same manner.

*** Illegal NSTableView data source (<NSView: 0x102535290>). Must implement numberOfRowsInTableView: and tableView:objectValueForTableColumn:row:

OK, this is driving me crazy, i have an Xcode OSX App that i have been working on. I made some changes recently and i have started getting the following error at compile time:
iModerate Desktop[72478:303] *** Illegal NSTableView data source (<NSView: 0x102535290>).
Must implement numberOfRowsInTableView: and tableView:objectValueForTableColumn:row:
I cannot workout where this is coming from, i have implemented both these methods in my appDelegate:
- (NSView *)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{
// The return value is typed as (id) because it will return a string in most cases.
id returnValue=nil;
// The column identifier string is the easiest way to identify a table column.
NSString *columnIdentifer = [tableColumn identifier];
// Get the name at the specified row in namesArray
NSString *theName = [[self.twitterClientsController arrangedObjects] objectAtIndex:row];
// Compare each column identifier and set the return value to
// the Person field value appropriate for the column.
if ([columnIdentifer isEqualToString:#"name"]) {
returnValue = theName;
}
return returnValue;
}
and this
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return[[self.twitterClientsController arrangedObjects] count];
}
And app delegate is set as NSTableViewDelegate
Now the extra weird/frustrating thing, is that i have no NSTableView in the xib, i did, but i have deleted them all. I have event opened the XIB in BBedit and searched for NSTableView and there is 100% not one in there!
So, help please! If i could work out what NSView: 0x102535290 is i could maybe track this down.
Help to save my sanity greatly appreciated!
Gareth
it is solved with me that way :
remove the datasource and the delegate connections from the interfaceBuilder.
make an outlet property for the your tableview in the .h file
in the .m file in applicationDidFinishLaunching method set the delegate and datasource manually for your tableview
[self.tableView setDelegate:self];
[self.tableView setDataSource:self];

cellForRowAtIndexPath is called when there is no row

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
if ([BGSearchParameter defaultSearchParameters].fetchedResults.count==0)
{
PO(#([self.tableView numberOfRowsInSection:0]));
PO(#([self tableView:nil numberOfRowsInSection:0]));
PO(#(indexPath.row));
while (false);
}
This is the result
self.tableView numberOfRowsInSection:0]): 20
#([self tableView:nil numberOfRowsInSection:0]): 0
Now, I do not know who call that cellForRowAtIndexPath.
Here is the screenshot
The debuggin windows shows that the main thread somehow call cellForRowAtIndexPath.
I usually fix this issue by returning some random UITableViewCell that's never displayed. Howerver, I think it's a bug.
What functions can call cellForRowAtIndexPath anyway besides tableReload and why it doesn't call
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
first?
It seems that my tableView still think there are 20 rows even though there are only 0 rows.
The issue seems to be your tableview is not refreshing. Please include this line in your code so that it will refersh each time:-
[yourTableView reloadData];
You can use the parameter "tableView" of this method to check whether the right instance of "UITableView" is called. For example, in the delegate method" - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section" add these code:
if(tableView== youwanttocheckTableView) {
//do what you want to do
}
You can also check which TableView instance have set its delegate equals "self" in this class.

Cannot make table re-order to work

From the UITableViewCell showsReorderControl docs:
For the reordering control to appear, you must not only set this property but implement the UITableViewDataSource method tableView:moveRowAtIndexPath:toIndexPath:. In addition, if the data source implements tableView:canMoveRowAtIndexPath: to return NO, the reordering control does not appear in that designated row.
I've got the both in my tableviewController :
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
NSLog(#"move from:%d to:%d", fromIndexPath.row, toIndexPath.row);
//just for test
}
My cell properties including re-order controls :
And yet I can't see the re-order control, what am I missing?
Have you put your UITableView into editing mode via
[tableView setEditing:YES animated:YES];
?
The first method you posted is needless, by the way, as that is the default behavior.
I think you need to actually get into edit mode for the table. Either try it in code when your view appears or create a button that will do it.
[tableView setEditing:YES animated:YES];

When reordering a UITableView, NSFetchedResultsController doesn't have latest state

I have a UITableView powered by an NSFetchedResultsController and am trying to properly support reordering.
Inside moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath I respond to the reordering by updating an order value on the NSManagedObjects and save the context like this:
[self.fetchedResultsController.managedObjectContext save:nil];
So now all objects have the correct order value and the results controller's NSFetchRequest sorts by that value correctly.
This does appear to work, however when I scroll up and down in the table view, the old values are being displayed. So it looks like when I use objectAtIndexPath on the NSFetchedResultsController, it doesn't return the latest object.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// ... cell generation code ...
NSManagedObject *obj = [self.fetchedResultsController objectAtIndexPath:indexPath];
[cell.textLabel setText:sideEffect.name];
}
If I navigate away and then return, the cells are in the correct order.
After my call to save, do I need to:
Refresh the NSFetchedResultsController
Invalidate a cache
Refresh/reset something on the UITableView?
The solution was to reinitialise the fetch controller after the move modifications had taken place. Since I had a special getter method generating the controller (and performing the first fetch), I could just set the instance variable to nil to cause it to be regenerated next time it was needed.