I am working with an app which parses an feed online. When I click the refresh button, it takes some time to re parse the file and show 开发者_开发技巧its data. I want an activity indicator in the middle of the view when I click refresh button. And when parsing is done, that indicator should hide.
I am using this code but it is not working:
- (IBAction)refreshFeed:(id)sender
{
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[self.view addSubview:spinner];
[spinner startAnimating];
// parsing code code
[spinner release];
}
A UIActivityIndicator generally needs to be placed into a separate thread from the long process (parsing feed) in order to appear.
If you want to keep everything in the same thread, then you need to give the indicator time to appear. This Stackoverflow question addresses placing a delay in the code.
EDIT: Two years later, I think that any time you are using a delay to make something happen you are probably doing it wrong. Here is how I would do this task now:
- (IBAction)refreshFeed:(id)sender {
//main thread
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; [self.view addSubview:spinner];
//switch to background thread
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
//back to the main thread for the UI call
dispatch_async(dispatch_get_main_queue(), ^{
[spinner startAnimating];
});
// more on the background thread
// parsing code code
//back to the main thread for the UI call
dispatch_async(dispatch_get_main_queue(), ^{
[spinner stopAnimating];
});
});
}
I think i am not able to explain it well.ok lets try again. its a nav based app. i have tableView. every cell creates a detailView. on RootView which is a tableview there is a refresh button. when i click that button it parses the feed again. and it takes some time. for that time program doesnt respond. and parsing is complete it works again. now i need activity indicator for that time. i dont know how to add in xib. bcz when i open main.xib and put activity indicator in RootViewController. it comes infront of whole tableView. now may be i explained well. if not let me know i ll try again.
from what you are saying above the program is not responding during the parsing which is a problem. If the GUI freezes while you are parsing the data you should move that operation to a secondary thread. That way your GUI remains responsive and you will be able to see the activity indicator.
on the main thread you should have something similar to this in order to show the activity indicator:
UIActivityIndicatorView *av = [[[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray] autorelease];
av.frame = CGRectMake(round((yourView.frame.size.width - 25) / 2), round((yourView.frame.size.height - 25) / 2), 25, 25);
av.tag = 1;
[yourView addSubview:av];
[av startAnimating];
after the secondary thread is finished, this is the thread where you parse the data, you should call on the main thread something like this to remove the activity indicator:
UIActivityIndicatorView *tmpimg = (UIActivityIndicatorView *)[yourView viewWithTag:1];
[tmpimg removeFromSuperview];
Change the center of the activity indicator as
activityIndicator.center = self.view.center;
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activityIndicator.alpha = 1.0;
[collectionVwSearch addSubview:activityIndicator];
activityIndicator.center = CGPointMake([[UIScreen mainScreen]bounds].size.width/2, [[UIScreen mainScreen]bounds].size.height/2);
[activityIndicator startAnimating];//to start animating
For Swift
let activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView.init(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
activityIndicator.alpha = 1.0
collectionVwSearch.addSubview(activityIndicator)
activityIndicator.center = CGPointMake(UIScreen.mainScreen().bounds.size.width / 2, UIScreen.mainScreen().bounds.size.height / 2)
activityIndicator.startAnimating()
To stop activityIndicator wirte [activityIndicator stopAnimating]
on appropriate place
self.activity.center = CGPointMake(self.view.bounds.size.width / 2.0f, self.view.bounds.size.height / 2.0f);
self.activity.autoresizingMask = (UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin);
Add this code before starting your task:
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[self.view addSubview:spinner];
[spinner setFrame:CGRectMake((self.view.frame.size.width/2)-(spinner.frame.size.width/2), (self.view.frame.size.height/2)-(spinner.frame.size.height/2), spinner.frame.size.width, spinner.frame.size.height)];
[spinner startAnimating];
After completion of the task add:
[spinner stopAnimating];
In Swift, this worked for my app
let activity_view = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
activity_view.frame = CGRectMake(0.0, 0.0, 40.0,40.0)
activity_view.center = self.view.center
self.view.addSubview(activity_view)
activity_view.bringSubviewToFront(self.view)
activity_view.startAnimating()
/ create activity indicator
activityIndicator = [[UIActivityIndicatorView alloc]
initWithFrame:CGRectMake(0.0f, 0.0f, 20.0f, 20.0f)];
[activityIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhite];
...
[self.view addSubview:activityIndicator];
// release it
[activityIndicator release];
Better approach would be you add indicatore on xib & make it hide/unhide basedon your requirement
spinner.center = self.view.center;
To show spinner from rootController try:
[self.navigationController.visibleViewController.view addSubview:spinner];
or
[self.navigationController.view addSubview:spinner];
try like this
activityIndicator.center = CGPointMake(160,240);
The problem with some of the other answers is that a new activity indicator gets added every time so the subviews start piling up. Here is a complete example that only uses a single UIActivityIndicator
.
This is the entire code for the project above:
import UIKit
class ViewController: UIViewController {
// only using a single spinner instance
let spinner = UIActivityIndicatorView(activityIndicatorStyle: .WhiteLarge)
override func viewDidLoad() {
super.viewDidLoad()
// setup spinner
spinner.backgroundColor = UIColor(white: 0, alpha: 0.2) // make bg darker for greater contrast
self.view.addSubview(spinner)
}
@IBAction func startSpinnerButtonTapped(sender: UIButton) {
// start spinner
spinner.frame = self.view.frame // center it
spinner.startAnimating()
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
// do something that takes a long time
sleep(2)
// stop spinner when background task finishes
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.spinner.stopAnimating()
})
})
}
}
You can write swift 4
let spinner = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
override func viewDidLoad() {
super.viewDidLoad()
spinner.backgroundColor = UIColor(white: 0, alpha: 0.2) // make bg darker for greater contrast
self.view.addSubview(spinner)
}
@IBAction func foodActionBtn(_ sender: Any) {
// start spinner
spinner.frame = self.view.frame // center it
spinner.startAnimating()
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = DispatchQueue.global(qos: .background)
backgroundQueue.async(execute: {
sleep(2)
self.spinner.stopAnimating()
})
}
SWIFT 5
Declaration
let activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView.init(style: UIActivityIndicatorView.Style.medium)
//if you want a bigger activity indicator, change style from .medium to .large
ViewDidLoad
activityIndicator.alpha = 1.0
view.addSubview(activityIndicator)
activityIndicator.center = view.center
Activate activity indicator, in my case it is in `didSelectRowAt` method
activityIndicator.startAnimating()
If you push to another viewController while animation is active, and then pop back, you will still see activity indicator animating, so you should do this
override func viewWillAppear(_ animated: Bool) {
if activityIndicator.isAnimating {
activityIndicator.stopAnimating()
}
}
Mr Poscean my code is working. But is you want show big appearing of activity indicator you can use it....
var activityIndicator = UIActivityIndicatorView()
activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray)
activityIndicator.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
let transform: CGAffineTransform = CGAffineTransform(scaleX: 1.5, y: 1.5)
activityIndicator.transform = transform
activityIndicator.center = self.view.center
activityIndicator.startAnimating()
self.view.addSubview(activityIndicator)
精彩评论