问题描述
在我的应用程序中,我使用用户名文本字段、密码文本字段和登录按钮登录.当点击登录按钮时,我检查字段.这次我需要显示一个活动指标,但我的 var 活动指标总是隐藏的.这是我的代码.
in my app i have a login with a usernamaeTextfield, passwordtextfield and login button. When the login button is tapped i check the fields. I need show a activityindicator in this time, but my var activityindicator is always hidden.This is my code.
@IBOutlet weak var activity: UIActivityIndicatorView!
override func viewDidLoad() {
self.activity.hidden = true
super.viewDidLoad()}
@IBAction func login(sender: AnyObject) {
activity.hidden = false
activity.startAnimating()
if (self.username.isEmpty || self.password.isEmpty){
self.showAlert("Asegurese de ingresar un usuario y contraseña!")
}else{
var user = user_function()
if !user.user_valid(self.username,password: self.password){
self.showAlert("Usuario Invalido")
}else{
}
}
activity.hidden = true
activity.stopAnimating()
}
我的 user_valid 代码是
my code of user_valid is
func user_valid(username :String, password : String)->Bool{
var resultados : Array<JSON> = []
userbase64 = self.encode_to_base64(username)
passbase64 = self.encode_to_base64(password)
var api = channels_function()
resultados = api.load_videos("https://api.cxntv.com/api/v1/videos/?type=canales&page_size=100&ordering=-id")
if errormessage.isEmpty{
api.save_LiveChannels(resultados)
saver_user(userbase64, passbase64: passbase64, username: username, password: password)
errormessage = ""
return true
}else{
errormessage = ""
return false}
}
并加载视频是:
func load_videos(url :String)->Array<JSON>{
var resultados : Array<JSON> = []
var request = Get_Data()
self.task_completed = false
request.remoteUrl = url
request.getData({data, error -> Void in
println("los datos")
//println(data)
if (data != nil){
// Fix possible error if no "results" key
if let results = data["results"].array {
resultados = results
self.task_completed = true
}
println("Data reloaded")
} else {
println("api.getData failed")
self.task_completed = true
}
})
while(!self.task_completed){}
return resultados
}
获取数据为:
var remoteUrl = ""
func getData(completionHandler: ((JSON!, NSError!) -> Void)!) -> Void {
let url: NSURL = NSURL(string: remoteUrl)!
let request: NSMutableURLRequest = NSMutableURLRequest(URL: url)
let session = NSURLSession.sharedSession()
println(request.HTTPBody)
request.addValue(userbase64 ,forHTTPHeaderField: "X_CXN_USER")
request.addValue( passbase64,forHTTPHeaderField: "X_CXN_PASS")
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
if (error != nil) {
return completionHandler(nil, error)
}
var error: NSError?
let json = JSON(data : data)
if (error != nil){
return completionHandler(nil, error)
} else {
if let results = json["detail"].string {
errormessage = results
return completionHandler(nil, error)
} else {
return completionHandler(json, nil)
}
}
})
task.resume()
}
推荐答案
问题在于 loadVideos
,您在其中采用了一个非常好的异步方法并使其同步(阻止 UI 更新), 并且,使用旋转的 while
循环以一种非常低效的方式完成了这项工作.相反,使 loadVideos
异步:
The problem is loadVideos
, in which you've taken a very nice, asynchronous method and made it synchronous (blocking UI updates), and, have done so in a pretty inefficient manner with a spinning while
loop. Instead, make loadVideos
asynchronous:
func loadVideos(url:String, completionHandler: (Array<JSON>?) -> ()) {
var request = Get_Data()
request.remoteUrl = url
request.getData {data, error in
println("los datos")
//println(data)
if (data != nil){
// Fix possible error if no "results" key
if let results = data["results"].array {
completionHandler(results)
}
println("Data reloaded")
} else {
println("api.getData failed")
completionHandler(nil)
}
}
}
然后 userValid
应该使用完成块参数(使用它自己的 completionBlock 模式):
And then userValid
should use the completion block parameter (employing a completionBlock pattern of its own):
func userValid(username :String, password : String, completionHandler: (Bool) -> ()) {
userbase64 = encode_to_base64(username)
passbase64 = encode_to_base64(password)
var api = channelsFunction()
api.loadVideos("https://api.cxntv.com/api/v1/videos/?type=canales&page_size=100&ordering=-id") { results in
if results != nil {
api.save_LiveChannels(results!)
saver_user(userbase64, passbase64: passbase64, username: username, password: password)
errormessage = ""
completionHandler(true)
}else{
completionHandler(false)
}
}
}
然后 login
也会异步调用它:
And then login
would call this asynchronously, too:
@IBAction func login(sender: AnyObject) {
activity.hidden = false
activity.startAnimating()
if username.isEmpty || password.isEmpty {
showAlert("Asegurese de ingresar un usuario y contraseña!")
} else {
userValid() { success in
if !user.user_valid(self.username,password: self.password){
self.showAlert("Usuario Invalido")
}else{
}
dispatch_async(dispatch_get_main_queue(), {
activity.hidden = true
activity.stopAnimating()
}
}
}
}
我确定我没有正确掌握您的所有函数和变量,但希望您能看到这种模式:不要使用同步方法并在异步方法中使用 completionHandler
参数.
I'm sure I don't have all of your functions and variables right, but hopefully you can see the pattern: Don't use synchronous methods and use completionHandler
parameters with your asynchronous methods.
--
如果您想查看我在您共享附加代码之前发布的原始答案,请查看此答案的修订历史记录.但以上概述了基本方法.
If you want to see my original answer, that I posted before you shared the additional code, see the revision history of this answer. But the above outlines the basic approach.
这篇关于如何快速显示活动指示器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!