Objective c- Show Loading Screen before main thread gets blocked completely - ios

In my app I have two methods to hide and show a subview of a view controller called
-(void)hideCurrentView
-(void)showCurrentView
They are always called together. When calling hideCurrentView I want to start showing a loading screen and then hide this loading screen when showCurrentView has shown all necessary ui elements. My loading screen is a view with an activity indicator as a subview. The problem is that I have to do all the actions that happen in hideCurrentView and showCurrentView on the main thread. That is why my loading screen will never show up. :-(
I tried to put the show loading screen method to a background thread:
-(void)hideCurrentView {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, (unsigned long)NULL), ^(void) {
[self showLoadingScreen];
});
[self performSelectorOnMainThread:#selector(hideCurrentViewOnMainThread) withObject:nil waitUntilDone:YES];
}
-(void)showCurrentView {
[self performSelectorOnMainThread:#selector(showCurrentViewOnMainThread) withObject:nil waitUntilDone:YES];
}
That does not work. The loading screen never shows up because the main thread is blocked. I also tried showing the loading screen directly on the main thread but it doesn´t work too.
Can anyone tell me hoew to show the loading screen before doing the ui actions and then hide it again when all ui actions have finished?
Thanks for your help!

You should not call showLoadingScreen in a background thread if you are just adding a subview. (or more generally manipulating the UI)
I'm guessing you have something in your hideCurrentViewOnMainThread that is not UI related and blocks the main thread and it's that part of the code that should be run in another thread.

Related

UITableview cells don't show up until you scroll. also with in main queue

I have tried:
[self.tableView reloadData];
and this:
dispatch_async(dispatch_get_main_queue(),^{
[self.tableView reloadData];
});
but it doesn't help. Could anyone fix this?
Sooo, in first pic we can see 1,2,3,4,6 lines, but when I scrool down, when they can't see, go to another page, coming back, and scrolling up, they aren't there.(pic 2) pic1
pic2
This is usually caused by UI updates on a background thread. In each method or block that updates the UI assert that it's on the main thread:
NSAssert([NSThread isMainThread], #"UI updates should be on the main thread");
to catch it.

Scroll and add Search Bar asynchronously

I have this application in which I have a right bar button item which adds the search bar as title view. This works fine but when the table view is scrolling, this doesn't happen. It only adds when the table view has stopped scrolling.
Any way to handle this?
The main thread does not responds to events if its busy, use GCD to add this to Queue
Check if this function is called while scrolling. If yes , then simply using GCD will solve your problem.
-(void)userTapOnRightBarButton{
NSLog(#"Main thread response to touch during scrolling"):
dispatch_async(dispatch_get_main_queue(), ^{
[self addSearchBar];
});
}

UIView not removing from sight, but removing from "click ability"

I have a UIview that is just a semi-transparent screen cover with the word "Loading" on it. and one of those spinning activity icons.
After loading, I need to remove the loading view from the UI, but for whatever reason, this is not happening. Here's the method in question.
- (void) readyForRoomDisplay
{
[_loadingIcon stopAnimating]; //_loadingIcon is the activity spinner
[self.view sendSubviewToBack:_loadingView]; // an attempt to hide
[_loadingView setHidden:YES]; // an attempt to hide
[_loadingView removeFromSuperview];// an attempt to hide
[self nextRoom:_roomImageButton];//should refresh the whole view
[self.view setNeedsLayout];
[self.view setNeedsDisplay];
}
The kicker is, after this happens, the contents of the VC's main view (while obscured) are clickable!!!
Some screenshots:
Normal Loading Image before AND after it should be destroyed
Somehow, I'm able to click THROUGH the loading screen!
This is the normal app main screen and appears when the button is clicked to swap calendars (refreshing the screen)
I feel like I've done everything that one can possibly do to get this out of here. It appears that the view is not updating after getting these commands. Is there anything else I can do?
looked here: Async UIView content not showing up when coming back to main thread
Apparently this update was not happening on the main thread, I just needed to push it back to the main thread an all was saved! Huzzah!

ios activity indicator is visible once, and then will not show until I try again a minute later

Ok, so I have this piece of code:
- (void) searchBarSearchButtonClicked:(UISearchBar *)aSearchBar
{
[_activity startAnimating];
[self.searchBar bringSubviewToFront:_activity];
[self.searchBar resignFirstResponder];
if([_activity isAnimating]){
NSLog(#"its animating!");
}
dispatch_queue_t background = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(background, ^{
[self performSelectorOnMainThread:#selector(filter:) withObject:aSearchBar.text waitUntilDone:YES];
dispatch_async(dispatch_get_main_queue(), ^{
[_activity stopAnimating];
if(![_activity isAnimating]){
NSLog(#"its not animating anymore!");
}
[self.tableView reloadData];
});
});
}
what i'm trying to do is start an activity indicator which I added as a subview to the search bar. In this code, I start the animation (logging for test) on the main thread, then set up a background asynchronous thread which runs the method that generates the new data set which will reload the tableview. I wait for this to return, and which point, I stop animation and reload the tableview on the main thread.
the result is this...when the application runs, I go to the table view, and I type a word in the search bar. When I hit enter, the activity indicator shows up, the table loads, and the activity indicator stops. This is great.
Then, I click on the search bar again, start a new search, only this time, the activity indicator does not show itself, but the NSLog shows that it IS animating. The tableview reloads as expected, but no activity indicator on the UI, but based on the NSLog, it seems to working.
Finally, if I wait about a minute, and search again, it works fine. What I'm suspecting is that that the background thread is not completing maybe, and the main thread continues doing what it needs to do.
Honestly, I've been beating my head for two days now, can someone explain what I'm doing wrong?
There's a chance that this has something to do with the view hierarchy, depending on where you added the UIActivityIndicatorView to. If you added it directly to the search bar, it might reorganize the subviews in a way you don't expect (and move the activity indicator behind some of them, blocking it from being visible, even though it's animating.)
A good option might be to embed the search bar within a toolbar, and then have the activity indicator on the left (or right) with flexible space separating it from the search bar.

iOS: Presenting a spinning wheel while NSFetchResultsController is performing a fetch

I am using a NSFetchedResultsController to populate a UITableView. The fetch take some time so I would like to present a spinning wheel to the user while the fetch is under way.
How would I do that?
You should start your spinner in the Main thread and push the "heavy work" for a secondary thread. When the work is done, stop the spinner. You can achieve that with something like this:
// Start the spinning here.
[mySpinner startAnimating];
// Declare the queue
dispatch_queue_t workingQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// it's not, so we will start a background process to calculate it and not block the UI
dispatch_async(workingQueue,
^{
// Some heavy work here.
dispatch_async(dispatch_get_main_queue(), ^{
// stop the spinner here
[mySpinner stopAnimating];
});
});
Doing the following in the Main thread wont make you accomplish what you want:
Start Spinner => Heavy work => Stop Spinner
When the Heavy work begins, it will block your UI thread, so you won't actually see the UIActivityMonitor animating.
To finish I would advise you using this as spinner.
You have several way to do that :
had a UIBarItem if you use UINavigationBar and set customView to UIActivityIndicator at the beginning of your function and hide it a the end.
Create a "modal" view with a UIActivityIndicator at the center of the view, and add this subview to your table view and remove it a the end of your function.
formally just you can use the UIActivityIndicatorView to present the wheel and for some good and delicate way use the MBHoods from here download the demo app here

Resources