在我的应用程序中,我使用usernamaeTextfield,passwordtextfield和登录按钮登录。点击登录按钮后,我会检查字段。我需要在这个时候显示一个activityindicator,但我的var activityindicator总是被隐藏。 这是我的代码。
@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代码是
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()
}
答案 0 :(得分:0)
这是因为您以相同的方法显示和隐藏它,不允许应用程序更新屏幕。
尝试调度
// CODE***
activity.hidden = true
activity.stopAnimating()
异步。
答案 1 :(得分:0)
您的代码包含与服务器的连接,因此startAnimating
和stopAnimating
之间的代码将在不同的线程上执行,这就是为什么在您注意到之前将执行隐藏功能。
您需要做的是在收到服务器的响应后显示activityIndicator
并将其隐藏在连接代码中。此外,您应该编写代码以隐藏此类调度中的activityIndicator
:
dispatch_async(dispatch_get_main_queue(), { () -> Void in
activity.hidden = true
activity.stopAnimating()
})
如果您发布其余代码,答案会更有帮助。
编辑:
您应该从login
功能中删除隐藏代码,并在load_videos
中隐藏activityIndicator,如下所示:
func load_videos(url :String)->Array<JSON>{
...
request.getData({data, error -> Void in
println("los datos")
dispatch_async(dispatch_get_main_queue(), { () -> Void in
activity.hidden = true
activity.stopAnimating()
})
...
})
return resultados
}
答案 2 :(得分:0)
您显示的代码永远不会按预期工作。由于您处于IBAction中,因此可以安全地假设在调用此函数时,您通常在主线程上运行。
我认为// CODE***
部分需要很长时间(否则就不需要活动指示符)。
因此你当前要么
stopAnimating
移动到该后台任务。应该做的事情如下:
@IBAction func login(sender: AnyObject) {
activity.hidden = false
activity.startAnimating()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
// CODE***
dispatch_async(dispatch_get_main_queue(), {
activity.hidden = true
activity.stopAnimating()
})
})
}
需要注意的是,必须再次在主线程上进行停止。
答案 3 :(得分:0)
问题是loadVideos
,你已经采用了一个非常好的异步方法并使其同步(阻止UI更新),并且以非常低效的方式进行了旋转{ {1}}循环。相反,使while
异步:
loadVideos
然后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)
}
}
}
应该使用完成块参数(使用自己的completionBlock模式):
userValid
然后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
我确定我没有正确使用您的所有功能和变量,但希望您能看到这种模式:不要使用同步方法并在您的@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
异步方法。
-
如果您想查看我在分享其他代码之前发布的原始答案,请参阅此答案的修订历史记录。但上面概述了基本方法。
答案 4 :(得分:0)
您应该学会使用dispatch_async
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)){
//Code take time here
//<#Code#>
dispatch_async(dispatch_get_main_queue(){
//update UI
//<#Code#>
}
}
并记住main queue