I'm adding 'pull to load more' to a UITableView. I've got the reloading working and I can add more data, but I'm trying to display a UIActivityIndicatorView when the data loads. I've managed to get the current accessory to disappear, but I can't make the actitity indicator draw itself.
This is the code I have in my UITableViewCell subclass:
-(void) toggleLoading:(bool)showLoading {
if(showLoading) {
[self.accessoryView setHidden:true];
isLoading = false;
} else {
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
spinner.frame = CGRectMake(0, 0, 24, 24);
self.accessoryView = spinner;
[spinner startAnimating];
[spinner release];
isLoading = true;
[self.backgroundView setNeedsDisplay];
}
}
The method is called and when the data finishes loading, the correct accessory is shown again. Is there an extra step I need?
Shouldn't you be drawing the spinner in didSelectRowAtIndexPath?
btw I would use:
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
Turned out I was trying to call this from a separate thread (using GCD), hence the lag in updating the UI. The solution was to move the UI calls onto the UI thread.
Related
In .h file:
UIActivityIndicatorView *mySpinner;
In viewDidLoad:
mySpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
mySpinner.center = CGPointMake(160, 240);
mySpinner.hidesWhenStopped = YES;
[self.view addSubview:mySpinner];
and finally I am calling it on button click as:
[mySpinner startAnimating];
The problem is that when I called it in viewDidLoad it showed and start animating but didn't animate on button click not even show. Help me on this issue.
Thanks in advance
I'm guessing your 'mySpinner" ivar isn't being properly retained or declared.
In your .h file, declare it as a property. That is:
#property (strong) UIActivityIndicatorView *mySpinner;
then, when you create it:
self.mySpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
and when you reference it in your button click method:
[self.mySpinner startAnimating];
Thanks to everyOne who helped me ….
I have resolved the issue and here i am posting the answer for some one who is in search of this… actually the issue is "i am Downloading some records on synchronous request. So thats why UI Updation is blocked for a while.
so this is creating problem here….
On Button click i just make a new thread that call a method 'start'
[NSThread detachNewThreadSelector: #selector(Start) toTarget:self withObject:nil];
and the 'start' method is
- (void) Start
{
Spinner.hidden = NO;
[mySpinner startAnimating];
}
I have an action that can take a second or two when a row is selected in a UITableViewCell. I want to give the user feedback when they select the cell that I'm doing something. Currently it just shows the tableviewcell highlight. I added a UIActivityIndicatorView to my view. I have it hidden by default. I try to do this in my didSelectRowAtIndexPath:
{
CustomCell *cell = (CustomCell *)[tableView cellForRowAtIndexPath:indexPath];
cell.activityIndicator.hidden = NO;
[cell.activityIndicator startAnimating];
// do long task
[cell.activityIndicator stopAnimating];
cell.activityIndicator.hidden = YES;
}
This code does not show my activityindicator. If I delete the
activityIndicator.hidden = YES;
in the
setCustomObject:(id)newObject
of my CustomCell class, I do see the indicator. It's just static though. I want to hide it until they click on the cell, animate while long task is running, then stop animating and hide again when long task is over. Any thoughts? Thanks!
Try updating the activity indicator in the main thread
dispatch_async(dispatch_get_main_queue(), ^{
cell.activityIndicator.hidden = NO;
[cell.activityIndicator startAnimating];
});
//do long task
dispatch_async(dispatch_get_main_queue(), ^{
cell.activityIndicator.hidden = YES;
[cell.activityIndicator stopAnimating];
});
in the setCustomObject:(id)newObject method, instead of setting it to hidden, try this:
activityIndicator.hidesWhenStopped = YES;
[acitivtyIndicator stopAnimating];
Then in the didSelectRowAtIndexPath method, remove the code that sets "hidden" or not, and just use [activityIndicator startAnimating] or [activityIndicator stopAnimating] to control both animation and whether it's hidden or not.
I have this problem where I am adding an UIActivityIndicatorView to a UIScrollView; Everything is working fine, except it does not start spinning unless the UIScrollView is scrolled.
Can anyone help me with this issue?
Thank you.
here is some code:
UIActivityIndicatorView *loaderActivity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
loaderActivity.center = CGPointMake(87/2,y+56/2);
loaderActivity.tag=tag;
[mainScrollView addSubview:loaderActivity];
[loaderActivity startAnimating];
[loaderActivity release];
You need to call startAnimating on the activity indicator to have it animate. Alternatively in interface builder you can tick the "animating" tickbox.
The fact that it's not animating until you scroll in the scroll view is a symptom that your call to startAnimating is happening in a background thread. UIKit calls should be made in the main thread.
You can verify that it's happening in a background thread by adding code like this:
if ([NSThread isMainThread]) {
NSLog(#"Running on main thread.");
} else {
NSLog(#"Running on background thread.");
}
You'll want to make sure all of the code you showed in your question is running on the main thread. To do this, you can change your code to look something like this:
// this code would be wherever your existing code was
[self performSelectorOnMainThread:#selector(addActivityIndicatorToView:) withObject:mainScrollView waitUntilDone:YES];
// this would be a new method in the same class that your existing code is in
- (void) addActivityIndicatorToView:(UIView*) view {
UIActivityIndicatorView *loaderActivity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
loaderActivity.center = CGPointMake(87/2,y+56/2);
loaderActivity.tag=tag;
[view addSubview:loaderActivity];
[loaderActivity startAnimating];
[loaderActivity release];
}
activityIndicator = [[UIActivityIndicatorView alloc]
initWithFrame:CGRectMake(87/2,y+56/2);
[activityIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhite];
activityIndicator.tag=tag;
[mainScrollView addSubview:loaderActivity];
[activityIndicator startAnimating];
[activityIndicator release];
Had an issue where I made the startAnimating call in the viewDidLoad and didn't work. I moved the call in the viewWillAppear and it worked!
Try running the animator in a different thread.
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:#selector(showProgress) object:nil];
[thread start];
//do whatever your want here
//call this when you want it stop animating
[activityIndicator stopAnimating];
[thread release];
- (void)showProgress{
[activityIndicator startAnimating];
}
I have a view which is created in IB. inside it I have a scroll view created programmatically. Within the scroll view I connect to a web service and fetch the content and the image. I want to show an activity indicator while doing this. So I have:
- (void)viewDidLoad
{
[super viewDidLoad];
activityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activityIndicator.frame = CGRectMake(0.0, 0.0, 40.0, 40.0);
activityIndicator.center = self.view.center;
[self.view.window addSubview:activityIndicator];
And right after the scrollview is added, I have:
[self.view addSubview:scrollView];
// ADD Scroll View Ends
//Add the Lisitng Image
NSOperationQueue *queue = [NSOperationQueue new];
NSInvocationOperation *operation = [[NSInvocationOperation alloc]
initWithTarget:self
selector:#selector(loadImage)
object:nil];
[queue addOperation:operation];
And in loadimage I have:
- (void)loadImage {
[activityIndicator startAnimating];
I've tried [self.view.window addSubview:activityIndicator];, [self->ScrollView addSubview:activityIndicator];, [self.view addSubview:activityIndicator];
but I just can't get the indicator to show. Anyone have any idea what might be wrong?
You should do this in you viewDidload
- (void)viewDidLoad
{
//Start Activity Indicator View
indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
indicatorView.frame = CGRectMake(40.0, 20.0, 60.0, 60.0);
indicatorView.center = self.view.center;
[self.view addSubview:indicatorView];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[indicatorView startAnimating];
[self performSelectorInBackground:#selector(loadscroll) withObject:self];
}
Note: "performSelectorInBackground" will show you an activity indicator on the view and your loadScroll method will fetch all data from internet and do other work.
-(void)loadscroll
{
//Your Scroll View
//Your other Data Manipulation even from internet
//When data is fetched display it
[self removeActivityIndicator]; //To stop activity Indicator
}
- (void)removeActivityIndicator
{
[indicatorView stopAnimating];
}
What I have found so far after multiple times facing above problem with activity indicator.
Activity indicator and the function (or method or piece of code) that is required to be executed after appearance of activity indicator both can't run on main thread. If it is so activity indicator will not appear. The solution is to run activity indicator on main thread and the function in a background thread.
I have also faced a case in which the function followed by activity indicator can't run in a background thread. In my case it was playing a music file using MPMoviePlayerController that can't be executed in a background thread. What I did to solve this issue was to run activity indicator in the main thread and then used an NSTimer to call my method after a delay that was good enough for activity indicator to appear and start animating.
I have also found that activity indicator must be called in performSelectorOnMainThread and should be added as a subview on the top view of given viewController once it starts animating.
Once it is not needed it should be removed by calling removeFromSuperView method.
I've added the ELCimagepicker (https://github.com/Fingertips/ELCImagePickerController) to my project and it works perfectly, allowing the user to select multiple images for a slideshow. But when you click 'Save', there can be a lengthy delay depending on how many photos were added.
I've been trying to add a UIActivityIndicator when the user clicks 'Save', but having trouble due to the modal view that is presented. I can call a method from the activity that ELCimagepicker presents (ELCImagePickerController) and this gets actioned by the activity handling the presenting of the image picker. But whenever I try to add to the view, it isn't shown as the modal is on top of the activity indicator.
I've tried using bringSubviewToFront, I've tried adding the code directly to the imagepicker method file with [[self parentViewController] addSubView], but no luck.
Here's the latest code I tried: (indicator is declared in the .h file as UIActivityIndicator *indicator)
indicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
indicator.hidden=false;
[self.navigationController.view addSubview:self.indicator];
[self.navigationController.view bringSubviewToFront:self.indicator];
[indicator startAnimating];
if([delegate respondsToSelector:#selector(elcImagePickerController:showIndicator:)]) {
[delegate performSelector:#selector(elcImagePickerController:showIndicator:) withObject:self withObject:#"test"];
}
Has anyone had any success with adding a UIActivityIndicator on top of the ELCimagepicker, or another modal view handled by another class?
I've tried MBProgressHUD but couldn't get that working quite right either - it would show up when I used it in the ELCimagepicker class, but crashed on removal with:
bool _WebTryThreadLock(bool), 0x42368e0: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...
Any help would be fantastic.
Thanks.
I have figure out your problem. You can do this as below..
-(void)selectedAssets:(NSArray*)_assets {
UIActivityIndicatorView * activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
UIViewController * topView = [self.viewControllers objectAtIndex:[self.viewControllers count]-1];
activityIndicator.center = CGPointMake(topView.view.frame.size.width/2, topView.view.frame.size.height/2);
[activityIndicator setHidden:NO];
[topView.view addSubview:activityIndicator];
[topView.view bringSubviewToFront:activityIndicator];
[activityIndicator startAnimating];
[self performSelector:#selector(doProcess:) withObject:_assets afterDelay:2.1];
}
- (void) doProcess:(NSArray *)_assets {
NSMutableArray *returnArray = [[[NSMutableArray alloc] init] autorelease];
for(ALAsset *asset in _assets) {
NSMutableDictionary *workingDictionary = [[NSMutableDictionary alloc] init];
[workingDictionary setObject:[asset valueForProperty:ALAssetPropertyType] forKey:#"UIImagePickerControllerMediaType"];
[workingDictionary setObject:[UIImage imageWithCGImage:[[asset defaultRepresentation] fullScreenImage]] forKey:#"UIImagePickerControllerOriginalImage"];
[workingDictionary setObject:[[asset valueForProperty:ALAssetPropertyURLs] valueForKey:[[[asset valueForProperty:ALAssetPropertyURLs] allKeys] objectAtIndex:0]] forKey:#"UIImagePickerControllerReferenceURL"];
[returnArray addObject:workingDictionary];
[workingDictionary release];
}
[self popToRootViewControllerAnimated:NO];
[[self parentViewController] dismissModalViewControllerAnimated:YES];
if([delegate respondsToSelector:#selector(elcImagePickerController:didFinishPickingMediaWithInfo:)]) {
[delegate performSelector:#selector(elcImagePickerController:didFinishPickingMediaWithInfo:) withObject:self withObject:[NSArray arrayWithArray:returnArray]];
}
}
Let me know if this answer help you ...
Thanks,
MinuMaster
It looks like you are updating UI on a background thread. All UIKit updates are to be done in the main thread. So I recommend you execute methods doing UI updates using performSelectorOnMainThread:withObject:.
I solved the issue like this
activityIndicatorObject = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
// Set Center Position for ActivityIndicator
activityIndicatorObject.center = CGPointMake(150, 250);
activityIndicatorObject.backgroundColor=[UIColor grayColor];
// Add ActivityIndicator to your view
[self.view addSubview:activityIndicatorObject];
activityIndicatorObject.hidesWhenStopped=NO;
[activityIndicatorObject startAnimating];