UITableView delegate method called twice - objective-c

Today my question is about UITableViewController-s
In particular I have noticed that the datasource delegate method
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
is called twice (even if for instance I just create a navigation based application and without adding a line of code.. well adding an NSLog to track it).
Now, since in my application I need to determine the number of sections basing the choice on the documents in the file system, I need to call some methods to do so. I have put these methods in the above mentioned method, so they will be called twice, which is something I don't need.
The questions are why is it called twice, can I have it called once?
I hope that in the official documentation this is not clearly stated (which would mean that I didn't read it at all :) ). By the way I could see others posting similar questions, but I couldn't find a fully satisfying answer.
Thank you.

I was experiencing the same problem, only with the call to numberOfRowsInSection:
The answered laid in the stack trace for each call I received.
The first call was due to a change in the table header view I was making in the viewDidLoad: of my viewcontroller.
thumbView.tableHeaderView = nil;
thumbView.tableFooterView = nil;
This resulted in internal call to _updateContentSize: which called heightForTable: which eventually called numberOfRowsInSection:. This was something I triggered, and could be easily avoided by not doing the above code :)
The second call was the legitimate one in order to reloadData. This is triggered by a layout event somewhere and most likely you can't skip it.
I'm sure you can observe something similar for the numberOfSections: method
So, my conclusion is that due to the the implementation of UITableView there are many situations where certain delegate methods will get called twice or more because the table view has to refresh something. I try to design my code around this bug/feature/etc.
Hope it helps

If your tableview is contained by a child view controller,
Try this at your parent ViewController
[parentViewController addChildViewController:childViewController];
before [parentViewController.view addSubview:childViewController.view]

Please check your code, after adding TableView you may again called realodData method of table in mey be ViewWillAppear method

This can happen if you'r table view's frame gets changed by mistake in the story board.Say you clicked on the storyboard where you have added the table view as a subview and now your table may not be having the proper frame which you have set in the beginning.

Related

Ongoing NSTableView problems

I am writing my first Cocoa/OSX app. I have been having problems with an NSTableView derived class. The problems is that there is no table in the containing NSView - the table is not visible.
I previously pasted my code at NSTableView is not being displayed
If you know NSTableView well and it could assist, it would greatly help. I have spent a couple of days on this, with no luck.
Additional details:
NSLog shows that NSTableView subclass init() is called once. This is probably good. The method numberOfRowsInTableView() is called multiple times. I don't know whether this good or bad. The method tableView:objectValueForTableColumn:row: is never invoked. The method drawRect() of NSView is called after initialization of TableView. Yet, commenting out [super drawRect:dirtyRect]; line changes nothing.
Please note that I use the same NSTableView subclass as [also] a NSTableViewDataSource. I understand that this is not the common "pattern," yet I don't see why this cannot work. If there is a logical explanation, please advise my approach is not workable.
I do not use and do not want to use InterfaceBuilder.
Thank you for taking time to read my question.
I managed to come up with the solution. See the referred page for more information, if interested. Thanks.
BTW, the best NSTableView tutorial which I have seen - one that allowed me do what I needed is at: http://www.knowstack.com/nstableview_fromcode/

Putting stuff in my view controller's viewDidUnload doesn't have any effect

There's a UIViewController method -(void)viewDidUnload. I tried putting NSLog("unloaded"); in there to see when the view is unloaded, but nothing was printed to the console.
Where do I put my code, so that before a view unloads I can perform an action?
If you read the viewDidUnload documentation, you see that it's related to low memory conditions and may be called to help with that. There is also a viewWillUnload that get's called before the view is released. It's also related to low memory.
If you're only interested in when the view is no longer seen, there are will/did disappear methods.
Are you using storyboard or not?
Have you tried any of this methods
-(void) viewWillUnload{}
or
-(void)viewWillDisappear:(BOOL)animated{}
If you are using storyboards the one that will that usually performs is viewWillDisappear.

Duplicate NSLog entries

I don't know if it's possible for me to include code here that's relevant as my project is so large but are there any typical reasons why NSLog would repeat some warnings and calls to it at occasions where only one call/error is occuring?
As an example, I have a subclass of NSBox that inits an instance of another class on awakeFromNib:
- (void) awakeFromNib {
burbControllerInstance = [[BurbController alloc] init];
if (burbControllerInstance) {
NSLog(#"init ok");
}
}
I get NSLog printing "init ok" twice. I don't see why this subclass would be 'awoken' twice anywhere in my project. This is part of a larger problem where I can't get variables to return anything but nil from the class I'm creating an instance of. I'm wondering if perhaps the double values are something to do with it.
This post could be helpful, i. e. one comment:
Also important: awakeFromNib can be
called multiple times on the
controller if you use the same
controller for several nibs – say,
you’re using the app delegate as the
owner of both the app’s About Box and
preferences dialog. So you’ll need an
extra guard test if you use
awakeFromNib for anything but
initializing the nib objects
Update: Much more interesting could also be this, where the author mentions that awakeFromNib gets called twice. Unfortunately there is no real answer for this particular problem but maybe some basic ideas.
Update #2: Another potential solution from stackoverflow.com: View Controller calls awakeFromNib twice.

super viewDidUnload in Cocoa

In the function viewDidUnload it is initially empty. However, I'm following a tutorial where at the end of the function they write [super viewDidUnload]. I noticed that in the dealloc function, [super dealloc] is automatically written at the end. Why isn't it automatically written at the end of viewDidUnload? Does it make a difference? What does it do?
Also, is this a Cocoa question, or an Objective-C question?
This link may help: iPhone: [super viewDidUnload] calling order
Basically, if the superclass is just UIViewController, [UIViewController viewDidUnload] does nothing, so that's why it's not automatically added.
Call it at the end of the function.
I've had a lot of miscellaneous errors when i called at the beginning. I found a lot of places on the web discuss the topic, some say beginning, some say at the end. Before i researched, i figured it should be called at the end due to similar patterns of the structure and nature of the language (such as how touch events are handled).
My logic suggests that if i'm going to call the super, or parent of an object in question, i have to also think that the parent or super wouldn't know of the existence of the child object in its default implementation, and who knows what it might do. So when over-riding this method it would be logical to think that when setting outlets and properties to nil, that the super's unload method might do something like unload the view in a view controller while those outlets still exist.
Due to all the questions and answers i found, there is no clear cut solution. Apple doesn't give the immediate answer, but they provide an understanding of how the loading and unloading of views occurs. I quit looking for examples on this one and i'm sticking to the logic behind the call to super at the end of this function.
What i wouldn't do is assume I can guess what code is being run in private API's and that anyone other than an apple doc or an apple developer will have the right answer. nevertheless, this is my suggestion based on what i've experienced, perhaps the correct answer is that it should be either/or depending on what your doing in the method. Open to more suggestions.

NSTableView -setDataSource not working when triggered by FSEvents

So here's what I've got:
An NSTableView with an NSMutableArray data source
FSEvents monitoring a folder that contains the file that contains the data for the table view (Using SCEvents for Objective-C abstraction goodness)
The FSEvents triggers the same function that a reload button in the UI does. This function refreshes the table view with a new data source based on the contents of said file via setDataSource:.
And here's what happens:
If I make a change to the file, the FSEvent gets triggered and the refresh method gets called.
The array that the table view should be accepting does indeed include the changes that triggered the FSEvent.
setDataSource: gets sent to the NSTableView with the correct data source.
The changes do not appear in the table view!
But then:
If I hit the refresh button, which triggers the exact same method as the FSEvent, the table view gets updated with the new data.
I also tried replacing the FSEvent with an NSNotification (NSApplicationDidBecomeActiveNotification), but the same thing happens.
Anyone have any idea why this is happening?
Edit: For clarification, the jist of my question is this: Why does my NSTableView reload as it should when triggered by a button press, but not when triggered by an FSEvent or an NSNotification?
Edit: Thanks to diciu, I've figured out that in fact all of my UI references point to 0x0 when triggered by the event, but then have valid addresses when triggered by the button click. These objects are all declared in IB, so there's no instantiation or allocation for them going on in my code. So my question is now: what can I do to stop these pointers from pointing to nil?
We call reloadData on NSTableView when we have new data to add/remove to the table.
This might help, to force the NSTableView to redraw.
I'm not really sure if this is what your asking though. The wording of your question is kind of confusing, you state a series of events, but never a true question.
sounds like when you register for the event/notification, you're passing in a different instance of your controller class.
Have you tried calling your method from your FSEvent on a second pass of the run-loop?
[myObject performSelector:#selector(reloadAction:) withObject:nil afterDelay:0.0];
You're setting an NSArray directly as the data source of the table view?
That's not how NSTableView works. The data source must be an object that conforms to NSTableDataSource. NSArray doesn't. You write the data source yourself; it will probably be the same object that you currently have calling setDataSource:.
The other way would be to use Bindings.
Could it be that reference to table view within the scope of your refresh method is not valid?
I.e. are you sure you're not calling [nil reloadData] which does not yield any errors?
Your reference to your table view might be nil in the refresh code if you're set it before awakeFromNib or in some other circumstances.