如何在按下按钮时立即启动活动指示器?
问题描述:
我在应用程序中创建一个活动的指标:如何在按下按钮时立即启动活动指示器?
@IBAction func LocateMe(sender: AnyObject) {
Loading.hidden = false
Loading.startAnimating()
}
在viewDidLoad中是隐藏的,当我点击按钮LocateMe我要开始看到它装载在屏幕上。 问题是,它开始加载,但很晚,它开始时,应用程序打开下一个视图控制器。 你有什么想法,只要用户点击按钮,我怎么才能开始在屏幕上显示它。如果用户等待并且没有指示他已完成操作的指示符,则这是毫无用处的。我也是开放的例子。
import UIKit
import MapKit
import CoreLocation
import SwiftyJSON
import SVProgressHUD
struct City {
let name : String
let location : CLLocation
let description :String
let imageName : NSURL
let fileLink : NSURL
func distanceTo(location:CLLocation) -> Int
{
let distanceMeters = location.distanceFromLocation(self.location)
let distanceKilometers = distanceMeters/1000.00
return Int(round(100 * distanceKilometers)/100)
}
}
class FirstViewController: UIViewController, CLLocationManagerDelegate {
@IBOutlet weak var Loading: UIActivityIndicatorView!
@IBOutlet weak var LocateMeButton: UIButton!
@IBOutlet weak var LabelTest: UILabel!
@IBOutlet weak var Slider: UISlider!
@IBOutlet weak var LabelValueSlider: UILabel!
var MySliderCurrentValue = Double()
var locationManager = CLLocationManager()
var userLoc : CLLocation!
var cities = [City]()
var nearbyCities = [City]()
override func viewDidLoad() {
super.viewDidLoad()
Loading.hidden = true
LocateMeButton.layer.cornerRadius = 5
// Do any additional setup after loading the view, typically from a nib.
// let path: String = NSBundle.mainBundle().pathForResource("cities", ofType: "json") as String!
let path = NSData(contentsOfURL: NSURL(string: "http://www.99website.eu/citiescopy.json")!) as NSData!
// let jsonData = NSData(contentsOfFile: path) as NSData!
var error : NSError?
let ReadableJSON2 = JSON (data:path, options: NSJSONReadingOptions.MutableContainers, error: &error)
print(error)
do {
let jsonObject = try NSJSONSerialization.JSONObjectWithData(path!, options: NSJSONReadingOptions.MutableContainers) as! [String:AnyObject]
for city in jsonObject["cities"] as! [[String:AnyObject]] {
//let coordinates = position["Position"] as! [String:CLLocationDegrees]
let cityName = city["Name"] as! String
let latitude = city["Latitude"] as! Double
let longitude = city["Longitude"] as! Double
let description = city["Description"] as! String
let image = city["Image"] as! String
let lin = city["Link"] as! String
let location = CLLocation(latitude: latitude, longitude: longitude)
let city = City(name: cityName, location: location,description: description, imageName: NSURL(string: image)!, fileLink: NSURL(string: lin)!)
cities.append(city)
}
} catch let error as NSError {
print(error)
}
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.requestWhenInUseAuthorization()
locationManager.startMonitoringSignificantLocationChanges()
locationManager.startUpdatingLocation()
if locationManager.respondsToSelector(#selector(locationManager.requestWhenInUseAuthorization)) {
locationManager.requestWhenInUseAuthorization()
locationManager.requestLocation()
}
else {
locationManager.startUpdatingLocation()
}
}
答
我相信你的问题是@AsadAli所说的。您的主线程上的加载数据是同步的。你应该尝试做的是将其移动到后台线程(异步),以便你的用户界面不会被阻止。
你可以做这样的事情:
/**
Loads the JSON data asyncrounously
- parameter urlString: the URL
- parameter completion: call on the main thread when the transaction is complete. Returning the data if it's there and an error if one exist.
*/
func loadJSONAsync(urlString: String, completion:(data: NSData?, error: NSError?) ->()) {
NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: urlString)!, completionHandler: { (data, response, error) -> Void in
dispatch_async(dispatch_get_main_queue(), {() -> Void in
if error != nil {
completion(data: nil, error: error)
}
else {
completion(data: data, error: nil)
}
})
}).resume()
}
然后调用它像这样在你的viewDidLoad
:
loadJSONAsync("") { (data, error) in
if let err = error {
print(err)
}
else {
//process JSON data
}
}
刚刚就能很快地清理你的viewDidLoad
我想构建这样的:
override func viewDidLoad() {
super.viewDidLoad()
Loading.hidden = true
LocateMeButton.layer.cornerRadius = 5
//
// You should start showing a loading wheel heree
//
//Load the JSON
loadJSONAsync("http://www.99website.eu/citiescopy.json") { (data, error) in
if let err = error {
print(err)
}
else {
processJSON(data)
}
}
// Start your location manager
startLocationManager()
}
func processJSON(data: NSData) {
var error : NSError?
let ReadableJSON2 = JSON (data:path, options: NSJSONReadingOptions.MutableContainers, error: &error)
print(error)
do {
let jsonObject = try NSJSONSerialization.JSONObjectWithData(path!, options: NSJSONReadingOptions.MutableContainers) as! [String:AnyObject]
for city in jsonObject["cities"] as! [[String:AnyObject]] {
//let coordinates = position["Position"] as! [String:CLLocationDegrees]
let cityName = city["Name"] as! String
let latitude = city["Latitude"] as! Double
let longitude = city["Longitude"] as! Double
let description = city["Description"] as! String
let image = city["Image"] as! String
let lin = city["Link"] as! String
let location = CLLocation(latitude: latitude, longitude: longitude)
let city = City(name: cityName, location: location,description: description, imageName: NSURL(string: image)!, fileLink: NSURL(string: lin)!)
cities.append(city)
//
// You should stop showing a loading wheel heree
//
}
} catch let error as NSError {
print(error)
}
}
func startLocationManager() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.requestWhenInUseAuthorization()
locationManager.startMonitoringSignificantLocationChanges()
locationManager.startUpdatingLocation()
if locationManager.respondsToSelector(#selector(locationManager.requestWhenInUseAuthorization)) {
locationManager.requestWhenInUseAuthorization()
locationManager.requestLocation()
}
else {
locationManager.startUpdatingLocation()
}
}
/**
Loads the JSON data asyncrounously
- parameter urlString: the URL
- parameter completion: call on the main thread when the transaction is complete. Returning the data if it's there and an error if one exist.
*/
func loadJSONAsync(urlString: String, completion:(data: NSData?, error: NSError?) ->()) {
NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: urlString)!, completionHandler: { (data, response, error) -> Void in
dispatch_async(dispatch_get_main_queue(), {() -> Void in
if error != nil {
completion(data: nil, error: error)
}
else {
completion(data: data, error: nil)
}
})
}).resume()
}
...你的变量名也应该是用小写声明:)
当你调用'LocateMe'时,你还执行了哪些其他代码。你在盯着任何位置服务吗?你正在加载一个新的'UIViewController'吗?您可能会在阻止动画的主线程上做某些事情。 – random
是的,我正在开始一个位置,等我可以上传整个代码 – Dakata
尝试注释掉这行代码。它会导致主线程冻结。 'let NSData(contentsOfURL:NSURL(string:“http://www.99website.eu/citiescopy.json”)!)作为NSData!'。尝试在后台线程中运行它或使用GCD。使用这个示例代码'dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),{ // All stuff here })' –