2017-07-31 49 views
-1

我試圖訪問變量pic在請求後,但它在封閉,這就是爲什麼print(pic)不起作用。Swift3 - 如何訪問變量在封閉

有人會如何去訪問這個?

guard let url = URL(string: "myurl") else{ return } 
    var pic = "" 
    let session = URLSession.shared 
    session.dataTask(with: url) { (data, response, error) in 
     if let response = response { 
      print(response) 
     } 
     if let data = data { 
      print(data) 
      do { 
       let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? NSDictionary 
       if let parseJSON = json { 
        pic = parseJSON["picture"] as! String 
        print(json!) 
       } 
      } catch { 
       print(error) 
      } 
     } 

     }.resume() 

    print(pic) 
} 
+0

您必須在閉包的範圍外聲明一個變量,並將閉包內的值賦值給該變量。但是,由於您正在處理網絡請求,因此閉包實際上是一個完成處理程序,只有在異步請求完成後纔會立即返回,因此在完成塊之後立即打印值仍然無效。查看Swift中完成處理程序和異步函數的工作方式 –

+0

這是一個計時問題。 'print(pic)'語句是在'dataTask'的異步完成處理程序關閉有機會運行之前執行的。底線,請記住閉包異步運行,所以不要試圖在閉包之外立即使用結果。通常你會從封閉內發送UI更新到主隊列中,或者更好的是自己採用完成處理器模式。 – Rob

回答

0

假設PIC的圖像你會被加載到一個UIImageView

您可以添加一個活動指示燈您的ImageView。然後當你打電話給你的功能下載圖片只需添加:

guard let url = URL(string: "myurl") else{ return } 
activityIndicator.isHidden = false 
activityIndicator.startAnimating() 

用戶將知道下載正在進行中。完成後,

DispatchQueue.main.async { 
activityIndicator.isHidden = true 
activityIndicator.stopAnimating() 
myImageView.image = UIImage(named: "pic") 
} 
    }.resume 

在主隊列上調度將立即更新用戶界面。

+0

如果您要從'dataTask'完成處理程序關閉中更新UI,請確保將這些UI更新分派給主隊列。 – Rob

+0

只需添加。抱歉。 –