Reputation: 110
I have the following code :
@property (weak, nonatomic) IBOutlet UIView *loadingView;
-(void) hideLoadingScreen{
self.loadingViewRect = self.loadingView.frame;
[self.loadingView setHidden:YES];
[self.loadingView setFrame:CGRectMake(0,0,0,0)];
}
- (void)viewDidAppear:(BOOL)animated{
[self.apiClient checkLoggedInWithCallback:^(int status){
if(status == ONLINE_LOGGED_IN){
[self.dbAPI isPullSynchronized:^(BOOL isPullSynced){
if(isPullSynced){
self.data = [self.dbAPI getTodayVisits];
[[self tableView] reloadData];
[self hideLoadingScreen];
} else {
[self.apiClient getTodayVisits:^(NSArray* visits){
[self.dbAPI insertTodayVisits:visits withCallback:^(int status){
self.data = [self.dbAPI getTodayVisits];
[[self tableView] reloadData];
}];
}];
}
}];
} else if(status == ONLINE_NOT_LOGGED_IN || status == ONLINE_INVALID_TOKEN || status == OFFLINE_NOT_LOGGED_IN) {
//Redirect to login
} else {
//Get from Local DB
self.data = [self.dbAPI getTodayVisits];
[[self tableView] reloadData];
}
}];
}
The hideLoadingScreen method won't execute (I mean it gets executed, but the UI doesn't update).
I tried all things to make it work (including dispatching [self hideLoadingScreen] to the main thread via GCD and performSelectorOnMainThread / making a __block BOOL variable isLoading and sleeping on the main thread till that variable was changed etc.). I also called the hideLoadingView method on the viewDidAppear method and it works, but I want it to hide when the callback is executed. Unfortunately, I couldn't find a solution by searching on stackoverflow, neither on google (I must say I tried all the solutions I found).
L.E. I logged self.loadingView as Rob Napier suggested
New code:
-(void) hideLoadingScreen{
self.loadingViewRect = self.loadingView.frame;
NSLog(@"hideLoadingScreen before: %@",self.loadingView);
[self.loadingView setHidden:YES];
[self.loadingView setFrame:CGRectMake(0,0,0,0)];
NSLog(@"hideLoadingScreen after: %@",self.loadingView);
}
- (void)viewDidAppear:(BOOL)animated{
NSLog(@"%@",self.loadingView);
[self.apiClient checkLoggedInWithCallback:^(int status){
if(status == ONLINE_LOGGED_IN){
[self.dbAPI isPullSynchronized:^(BOOL isPullSynced){
if(isPullSynced){
dispatch_async(dispatch_get_main_queue(), ^{
self.data = [self.dbAPI getTodayVisits];
[[self tableView] reloadData];
NSLog(@"async before: %@",self.loadingView);
[self hideLoadingScreen];
NSLog(@"async after: %@",self.loadingView);
});
} else {
[self.apiClient getTodayVisits:^(NSArray* visits){
[self.dbAPI insertTodayVisits:visits withCallback:^(int status){
self.data = [self.dbAPI getTodayVisits];
[[self tableView] reloadData];
}];
}];
}
}];
} else if(status == ONLINE_NOT_LOGGED_IN || status == ONLINE_INVALID_TOKEN || status == OFFLINE_NOT_LOGGED_IN) {
//Redirect to login
} else {
//Get from Local DB
self.data = [self.dbAPI getTodayVisits];
[[self tableView] reloadData];
}
}];
}
Logs:
2016-01-08 16:22:25.973 sunwaves.reporting[4566:282042] async before: <UIView: 0x7fa681e745d0; frame = (0 0; 1024 650); autoresize = RM+H+BM; layer = <CALayer: 0x7fa681e291c0>>
2016-01-08 16:22:25.973 sunwaves.reporting[4566:282042] hideLoadingScreen before: <UIView: 0x7fa681e745d0; frame = (0 0; 1024 650); autoresize = RM+H+BM; layer = <CALayer: 0x7fa681e291c0>>
2016-01-08 16:22:25.974 sunwaves.reporting[4566:282042] hideLoadingScreen after: <UIView: 0x7fa681e745d0; frame = (0 0; 0 0); hidden = YES; autoresize = RM+H+BM; layer = <CALayer: 0x7fa681e291c0>>
2016-01-08 16:22:25.974 sunwaves.reporting[4566:282042] async after: <UIView: 0x7fa681e745d0; frame = (0 0; 0 0); hidden = YES; autoresize = RM+H+BM; layer = <CALayer: 0x7fa681e291c0>>
Upvotes: 0
Views: 80
Reputation: 299275
The majority of UIKit calls must be made on the main queue. You should use dispatch_async(dispatch_get_main_queue(),...
to do this.
This includes your calls to reloadData
at a minimum.
You assignments to self.data
are also likely not thread-safe (unless you've done something special in the setter). So those need to be on the main queue.
And of course your calls to hideLoadingScreen
.
I assume that most of these blocks execute off the main queue, so that means putting in dispatch_async
in several places.
- (void)viewDidAppear:(BOOL)animated{
[self.apiClient checkLoggedInWithCallback:^(int status){
if(status == ONLINE_LOGGED_IN){
[self.dbAPI isPullSynchronized:^(BOOL isPullSynced){
if(isPullSynced){
dispatch_async(dispatch_get_main_queue(), ^{
self.data = [self.dbAPI getTodayVisits];
[[self tableView] reloadData];
[self hideLoadingScreen];
});
} else {
[self.apiClient getTodayVisits:^(NSArray* visits){
[self.dbAPI insertTodayVisits:visits withCallback:^(int status){
dispatch_async(dispatch_get_main_queue(), ^{
self.data = [self.dbAPI getTodayVisits];
[[self tableView] reloadData];
});
}];
}];
}
}];
} else if(status == ONLINE_NOT_LOGGED_IN || status == ONLINE_INVALID_TOKEN || status == OFFLINE_NOT_LOGGED_IN) {
//Redirect to login
} else {
//Get from Local DB
dispatch_async(dispatch_get_main_queue(), ^{
self.data = [self.dbAPI getTodayVisits];
[[self tableView] reloadData];
});
}
}];
}
Upvotes: 2