如何在swift中显示activityindicator?

时间:2015-08-02 20:09:23

标签: ios xcode swift

在我的应用程序中,我使用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()

}

5 个答案:

答案 0 :(得分:0)

这是因为您以相同的方法显示和隐藏它,不允许应用程序更新屏幕。

尝试调度

// CODE***
activity.hidden = true
activity.stopAnimating()

异步。

答案 1 :(得分:0)

您的代码包含与服务器的连接,因此startAnimatingstopAnimating之间的代码将在不同的线程上执行,这就是为什么在您注意到之前将执行隐藏功能。

您需要做的是在收到服务器的响应后显示activityIndicator并将其隐藏在连接代码中。此外,您应该编写代码以隐藏此类调度中的activityIndicator

dispatch_async(dispatch_get_main_queue(), { () -> Void in
    activity.hidden = true
    activity.stopAnimating()      
})

如果您发布其余代码,答案会更有帮助。

编辑:

您应该从login功能中删除隐藏代码,并在load_videos中隐藏activityIndi​​cator,如下所示:

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***部分需要很长时间(否则就不需要活动指示符)。

因此你当前要么

  • 实际上在主线程上执行耗时的操作,因此将其锁定 - &gt;很坏。由于您在主/ UI循环中没有发生UI更新,因此在完全登录之前不会显示任何活动指示符,这是您再次隐藏指标的确切时间。
  • 或在后台异步执行操作(推荐方式)。如果您这样做,则必须将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

中的UPDATE UI