views:

837

answers:

2

Anyone care to shed some light on why UITableView makes so many repeat calls to its delegate & datasource as it's being setup? Just looking at one I'm working on now I see that numberOfSectionsInTableView is called 3 times and then viewForHeaderInSection cycles through 3 more times for each section (I have 2 sections so total of 6 times before being displayed for first time)...all before the first screen is even rendered.

I realize that the API is private but wondering if someone might be willing to offer up some insight into this design pattern and what might be going on behind the scenes so I might learn a thing or two about why so much repetition is considered acceptable (or even advantageous) in this case...or, more likely, how I've managed to foul up applying it.

Edit: Added stack traces before RootViewController tableView is shown for first time

1st time calling viewForHeaderInSection:

#0  0x000086cc in -[RootViewController tableView:viewForHeaderInSection:] at RootViewController.m:444
#1  0x30c901a8 in -[UITableView(UITableViewInternal) _delegateWantsHeaderForSection:]
#2  0x30c8f6f4 in -[UISectionRowData refreshWithSection:tableView:tableViewRowData:]
#3  0x30c8f5a8 in -[UITableViewRowData rectForFooterInSection:]
#4  0x30c3d430 in -[UITableViewRowData heightForTable]
#5  0x30c05430 in -[UITableView(_UITableViewPrivate) _updateContentSize]
#6  0x30c3ce0c in -[UITableView noteNumberOfRowsChanged]
#7  0x30c3c7c0 in -[UITableView reloadData]
#8  0x30e50e60 in -[UITableViewController viewWillAppear:]
#9  0x30c78810 in -[UINavigationController _startTransition:fromViewController:toViewController:]
#10 0x30c783b0 in -[UINavigationController _startDeferredTransitionIfNeeded]
#11 0x30c782a0 in -[UINavigationController viewWillLayoutSubviews]
#12 0x30c5c874 in -[UILayoutContainerView layoutSubviews]
#13 0x30c382d8 in -[UIView(CALayerDelegate) _layoutSublayersOfLayer:]
#14 0x33e871c0 in -[CALayer layoutSublayers]
#15 0x33e86edc in CALayerLayoutIfNeeded
#16 0x33e86844 in CA::Context::commit_transaction
#17 0x33e86474 in CA::Transaction::commit
#18 0x33e8e5dc in CA::Transaction::observer_callback
#19 0x32d5c830 in __CFRunLoopDoObservers
#20 0x32da4346 in CFRunLoopRunSpecific
#21 0x32da3c1e in CFRunLoopRunInMode
#22 0x31bb9374 in GSEventRunModal
#23 0x30bf3c30 in -[UIApplication _run]
#24 0x30bf2230 in UIApplicationMain
#25 0x00002260 in main at main.m:14

2nd call:

#0  0x000086cc in -[RootViewController tableView:viewForHeaderInSection:] at RootViewController.m:444
#1  0x30c901a8 in -[UITableView(UITableViewInternal) _delegateWantsHeaderForSection:]
#2  0x30c8f6f4 in -[UISectionRowData refreshWithSection:tableView:tableViewRowData:]
#3  0x30c90628 in -[UITableViewRowData(UITableViewRowDataPrivate) _ensureSectionOffsetIsValidForSection:]
#4  0x30c8f5d0 in -[UITableViewRowData rectForFooterInSection:]
#5  0x30c3d430 in -[UITableViewRowData heightForTable]
#6  0x30c05430 in -[UITableView(_UITableViewPrivate) _updateContentSize]
#7  0x30c3ce0c in -[UITableView noteNumberOfRowsChanged]
#8  0x30c3c7c0 in -[UITableView reloadData]
#9  0x30e50e60 in -[UITableViewController viewWillAppear:]
#10 0x30c78810 in -[UINavigationController _startTransition:fromViewController:toViewController:]
#11 0x30c783b0 in -[UINavigationController _startDeferredTransitionIfNeeded]
#12 0x30c782a0 in -[UINavigationController viewWillLayoutSubviews]
#13 0x30c5c874 in -[UILayoutContainerView layoutSubviews]
#14 0x30c382d8 in -[UIView(CALayerDelegate) _layoutSublayersOfLayer:]
#15 0x33e871c0 in -[CALayer layoutSublayers]
#16 0x33e86edc in CALayerLayoutIfNeeded
#17 0x33e86844 in CA::Context::commit_transaction
#18 0x33e86474 in CA::Transaction::commit
#19 0x33e8e5dc in CA::Transaction::observer_callback
#20 0x32d5c830 in __CFRunLoopDoObservers
#21 0x32da4346 in CFRunLoopRunSpecific
#22 0x32da3c1e in CFRunLoopRunInMode
#23 0x31bb9374 in GSEventRunModal
#24 0x30bf3c30 in -[UIApplication _run]
#25 0x30bf2230 in UIApplicationMain
#26 0x00002260 in main at main.m:14

3rd call:

#0  0x000086cc in -[RootViewController tableView:viewForHeaderInSection:] at RootViewController.m:444
#1  0x30c901a8 in -[UITableView(UITableViewInternal) _delegateWantsHeaderForSection:]
#2  0x30c3eebc in -[UITableView(_UITableViewPrivate) _updateVisibleHeadersAndFootersNow]
#3  0x30c3e578 in -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow]
#4  0x30c3c514 in -[UITableView layoutSubviews]
#5  0x30c382d8 in -[UIView(CALayerDelegate) _layoutSublayersOfLayer:]
#6  0x33e871c0 in -[CALayer layoutSublayers]
#7  0x33e86edc in CALayerLayoutIfNeeded
#8  0x33e86844 in CA::Context::commit_transaction
#9  0x33e86474 in CA::Transaction::commit
#10 0x33e8e5dc in CA::Transaction::observer_callback
#11 0x32d5c830 in __CFRunLoopDoObservers
#12 0x32da4346 in CFRunLoopRunSpecific
#13 0x32da3c1e in CFRunLoopRunInMode
#14 0x31bb9374 in GSEventRunModal
#15 0x30bf3c30 in -[UIApplication _run]
#16 0x30bf2230 in UIApplicationMain
#17 0x00002260 in main at main.m:14

4th call:

#0  0x000086cc in -[RootViewController tableView:viewForHeaderInSection:] at RootViewController.m:444
#1  0x30c9712c in -[UITableView(UITableViewInternal) _sectionHeaderViewWithFrame:forSection:opaque:reuseViewIfPossible:]
#2  0x30c3f0b4 in -[UITableView(_UITableViewPrivate) _updateVisibleHeadersAndFootersNow]
#3  0x30c3e578 in -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow]
#4  0x30c3c514 in -[UITableView layoutSubviews]
#5  0x30c382d8 in -[UIView(CALayerDelegate) _layoutSublayersOfLayer:]
#6  0x33e871c0 in -[CALayer layoutSublayers]
#7  0x33e86edc in CALayerLayoutIfNeeded
#8  0x33e86844 in CA::Context::commit_transaction
#9  0x33e86474 in CA::Transaction::commit
#10 0x33e8e5dc in CA::Transaction::observer_callback
#11 0x32d5c830 in __CFRunLoopDoObservers
#12 0x32da4346 in CFRunLoopRunSpecific
#13 0x32da3c1e in CFRunLoopRunInMode
#14 0x31bb9374 in GSEventRunModal
#15 0x30bf3c30 in -[UIApplication _run]
#16 0x30bf2230 in UIApplicationMain
#17 0x00002260 in main at main.m:14

5th call:

#0  0x000086cc in -[RootViewController tableView:viewForHeaderInSection:] at RootViewController.m:444
#1  0x30c901a8 in -[UITableView(UITableViewInternal) _delegateWantsHeaderForSection:]
#2  0x30c3eebc in -[UITableView(_UITableViewPrivate) _updateVisibleHeadersAndFootersNow]
#3  0x30c3e578 in -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow]
#4  0x30c3c514 in -[UITableView layoutSubviews]
#5  0x30c382d8 in -[UIView(CALayerDelegate) _layoutSublayersOfLayer:]
#6  0x33e871c0 in -[CALayer layoutSublayers]
#7  0x33e86edc in CALayerLayoutIfNeeded
#8  0x33e86844 in CA::Context::commit_transaction
#9  0x33e86474 in CA::Transaction::commit
#10 0x33e8e5dc in CA::Transaction::observer_callback
#11 0x32d5c830 in __CFRunLoopDoObservers
#12 0x32da4346 in CFRunLoopRunSpecific
#13 0x32da3c1e in CFRunLoopRunInMode
#14 0x31bb9374 in GSEventRunModal
#15 0x30bf3c30 in -[UIApplication _run]
#16 0x30bf2230 in UIApplicationMain
#17 0x00002260 in main at main.m:14

6th call:

#0  0x000086cc in -[RootViewController tableView:viewForHeaderInSection:] at RootViewController.m:444
#1  0x30c9712c in -[UITableView(UITableViewInternal) _sectionHeaderViewWithFrame:forSection:opaque:reuseViewIfPossible:]
#2  0x30c3f0b4 in -[UITableView(_UITableViewPrivate) _updateVisibleHeadersAndFootersNow]
#3  0x30c3e578 in -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow]
#4  0x30c3c514 in -[UITableView layoutSubviews]
#5  0x30c382d8 in -[UIView(CALayerDelegate) _layoutSublayersOfLayer:]
#6  0x33e871c0 in -[CALayer layoutSublayers]
#7  0x33e86edc in CALayerLayoutIfNeeded
#8  0x33e86844 in CA::Context::commit_transaction
#9  0x33e86474 in CA::Transaction::commit
#10 0x33e8e5dc in CA::Transaction::observer_callback
#11 0x32d5c830 in __CFRunLoopDoObservers
#12 0x32da4346 in CFRunLoopRunSpecific
#13 0x32da3c1e in CFRunLoopRunInMode
#14 0x31bb9374 in GSEventRunModal
#15 0x30bf3c30 in -[UIApplication _run]
#16 0x30bf2230 in UIApplicationMain
#17 0x00002260 in main at main.m:14
+1  A: 

In my code numberOfSectionsInTableView is only called once, in response to a reloadData call.

You can set a breakpoint in numberOfSectionsInTableView and look at the call stack to see how and why it's being called.

Darren
How many sections do you have?
Meltemi
Seven sections.
Darren
In my experience UITableView is decently good about not duplicating calls. Check the callstacks on the duplicate calls and see what's happening. It may be your bug -- I've definitely seen this happen before.
Colin Barrett
Even Apple's samples call these methods repeatedly. add an NSLog line to numberOfSectionsInTableView in 's SimpleSectionedTableView and you should see multiple calls (2 in this case)..unless my setup is whacked!?!
Meltemi
What does the callstack look like when numberOfSectionsInTableView is called?
Darren
A: 
corprew