Reputation: 77651
When you create a table view with a delegate and data source you can call reloadData on it to force it to go to the datasource and get the data and display it.
However, you don't need to do this first time around. What is the hook that it is using to first go to its datasource and start loading the data?
There isn't a viewDidAppear or anything like that on UIView. It can't be init as it doesn't have a datasource yet.
I'm trying to create my own control that works in a similar way and I'm trying to find a method that I can use to trigger the first call to the datasource.
Upvotes: 2
Views: 525
Reputation: 9354
I think for your custom table class best solution will be: 1) have state isReloading inside the class
- (void)reloadData {
_reloading = YES;
// Do someting
_reloading = NO;
}
2) at the willMoveToSuperview check that you have datasource and not reloading:
- (void)willMoveToSuperview:(UIView *)superview {
if (self.dataSource && !self.isReloading) {
[self reloadData];
}
[super willMoveToSuperview:superview];
}
3) on the setDataSource check if have superview and not reloading:
- (void)setDataSource:(id<YourProtocolDelegate>)dataSource {
_dataSource = dataSource;
if (self.superview && !self.isReloading) {
[self reloadData];
}
}
Information about function calls for UITableView:
For storyboard loading:
2014-12-19 02:46:42.264 TestObjectiveC[21574:1891199] initWithCoder:
2014-12-19 02:46:42.266 TestObjectiveC[21574:1891199] setNeedsLayout
2014-12-19 02:46:42.266 TestObjectiveC[21574:1891199] setNeedsDisplay
2014-12-19 02:46:42.269 TestObjectiveC[21574:1891199] awakeAfterUsingCoder:
2014-12-19 02:46:42.269 TestObjectiveC[21574:1891199] setDataSource:
2014-12-19 02:46:42.270 TestObjectiveC[21574:1891199] setDelegate:
2014-12-19 02:46:42.270 TestObjectiveC[21574:1891199] awakeFromNib
2014-12-19 02:46:42.271 TestObjectiveC[21574:1891199] setNeedsDisplay
2014-12-19 02:46:42.298 TestObjectiveC[21574:1891199] willMoveToSuperview:
2014-12-19 02:46:42.300 TestObjectiveC[21574:1891199] didMoveToSuperview
2014-12-19 02:46:42.304 TestObjectiveC[21574:1891199] willMoveToWindow:
2014-12-19 02:46:42.306 TestObjectiveC[21574:1891199] didMoveToWindow
2014-12-19 02:46:42.307 TestObjectiveC[21574:1891199] setNeedsLayout
2014-12-19 02:46:42.342 TestObjectiveC[21574:1891199] setNeedsLayout
2014-12-19 02:46:42.343 TestObjectiveC[21574:1891199] layoutSubviews
2014-12-19 02:46:42.344 TestObjectiveC[21574:1891199] setNeedsLayout
2014-12-19 02:46:42.345 TestObjectiveC[21574:1891199] reloadData
2014-12-19 02:46:42.348 TestObjectiveC[21574:1891199] layoutSubviews
Backtrace:
* frame #0: 0x000621bc TestObjectiveC`-[CustomTableView reloadData](self=0x7a37c400, _cmd=0x01915284) + 28 at CustomTableView.m:15
frame #1: 0x0112232e UIKit`-[UITableView _reloadDataIfNeeded] + 78
frame #2: 0x01128317 UIKit`-[UITableView layoutSubviews] + 36
frame #3: 0x000623d8 TestObjectiveC`-[CustomTableView layoutSubviews](self=0x7a37c400, _cmd=0x01915520) + 120 at CustomTableView.m:34
frame #4: 0x0109ddd1 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 608
frame #5: 0x0055d771 libobjc.A.dylib`-[NSObject performSelector:withObject:] + 70
frame #6: 0x0463d28f QuartzCore`-[CALayer layoutSublayers] + 152
frame #7: 0x04631115 QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 397
frame #8: 0x04630f70 QuartzCore`CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 26
frame #9: 0x0458f3c6 QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 284
frame #10: 0x0459078c QuartzCore`CA::Transaction::commit() + 392
frame #11: 0x04656799 QuartzCore`+[CATransaction flush] + 52
frame #12: 0x01010286 UIKit`-[UIApplication _reportMainSceneUpdateFinished:] + 39
frame #13: 0x01011201 UIKit`-[UIApplication _runWithMainScene:transitionContext:completion:] + 3163
For initWithFrame loading:
2014-12-19 02:47:55.601 TestObjectiveC[21806:1895258] initWithFrame:style:
2014-12-19 02:47:55.604 TestObjectiveC[21806:1895258] setNeedsLayout
2014-12-19 02:47:55.605 TestObjectiveC[21806:1895258] setNeedsDisplay
2014-12-19 02:47:55.606 TestObjectiveC[21806:1895258] setDelegate:
2014-12-19 02:47:55.607 TestObjectiveC[21806:1895258] setDataSource:
2014-12-19 02:47:55.608 TestObjectiveC[21806:1895258] willMoveToSuperview:
2014-12-19 02:47:55.610 TestObjectiveC[21806:1895258] didMoveToSuperview
2014-12-19 02:47:55.640 TestObjectiveC[21806:1895258] willMoveToWindow:
2014-12-19 02:47:55.641 TestObjectiveC[21806:1895258] didMoveToWindow
2014-12-19 02:47:55.642 TestObjectiveC[21806:1895258] setNeedsLayout
2014-12-19 02:47:55.680 TestObjectiveC[21806:1895258] setNeedsLayout
2014-12-19 02:47:55.683 TestObjectiveC[21806:1895258] layoutSubviews
2014-12-19 02:47:55.684 TestObjectiveC[21806:1895258] setNeedsLayout
2014-12-19 02:47:55.684 TestObjectiveC[21806:1895258] reloadData
2014-12-19 02:47:55.686 TestObjectiveC[21806:1895258] layoutSubviews
Backtrace:
* frame #0: 0x0008517c TestObjectiveC`-[CustomTableView reloadData](self=0x7ba7f400, _cmd=0x01939284) + 28 at CustomTableView.m:15
frame #1: 0x0114632e UIKit`-[UITableView _reloadDataIfNeeded] + 78
frame #2: 0x0114c317 UIKit`-[UITableView layoutSubviews] + 36
frame #3: 0x00085398 TestObjectiveC`-[CustomTableView layoutSubviews](self=0x7ba7f400, _cmd=0x01939520) + 120 at CustomTableView.m:34
frame #4: 0x010c1dd1 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 608
frame #5: 0x00581771 libobjc.A.dylib`-[NSObject performSelector:withObject:] + 70
frame #6: 0x0466128f QuartzCore`-[CALayer layoutSublayers] + 152
frame #7: 0x04655115 QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 397
frame #8: 0x04654f70 QuartzCore`CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 26
frame #9: 0x045b33c6 QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 284
frame #10: 0x045b478c QuartzCore`CA::Transaction::commit() + 392
frame #11: 0x0467a799 QuartzCore`+[CATransaction flush] + 52
frame #12: 0x01034286 UIKit`-[UIApplication _reportMainSceneUpdateFinished:] + 39
frame #13: 0x01035201 UIKit`-[UIApplication _runWithMainScene:transitionContext:completion:] + 3163
frame #14: 0x0104d7d0 UIKit`__84-[UIApplication
Update: More correct code
1) have state isReloading inside the class
- (void)reloadData {
// More correct code, due that user can trigger reloadData multiple times, and you can reload it async. So in this case it never calls few times at the same time
if (self.isReloading) return;
_reloading = YES;
// Do someting
_reloading = NO;
}
2) at the willMoveToSuperview check that you have datasource and not reloading:
- (void)willMoveToSuperview:(UIView *)superview {
if (self.dataSource) {
[self reloadData];
}
[super willMoveToSuperview:superview];
}
3) on the setDataSource check if have superview and not reloading:
- (void)setDataSource:(id<YourProtocolDelegate>)dataSource {
_dataSource = dataSource;
if (self.superview) {
[self reloadData];
}
}
Upvotes: 3
Reputation: 77651
OK, so after @rmaddy said to set a breakpoint (which is obvious really) I put one into the numberOfSection
dataSource method.
The stack trace shows that this gets started from [UIView didMoveToWindow]
which I'd actually already come across in the docs and dismissed.
It actually seems to be split into methods (very "clean") as it runs _updateRowData
and then invalidateAllSections
and then _updateNumSections
which then calls out to the dataSource
to get the number of sections.
Thanks @rmaddy doing this has given me more ideas for my own view :D
Upvotes: 0
Reputation: 11132
You can use this trick in the custom view's initializer
- (instancetype)init {
...
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self reloadData];
});
}
This will call reloadData
at the end of current run loop (NOT immediately). So if someone uses your custom view and has something like this (may be in viewDidLoad
)
...
customView = [[CustomView alloc] init];
customView.dataSource = ...
customView.delegate = ...
[view addSubView:customView];
...
The reloadData
will be called after all these lines have been executed, and the dataSource
/delegate
are properly set.
This may not be exactly what UIKit
is doing, but is it worth it to replicate the exact mechanism?
Upvotes: 0