2017-06-16 68 views
-2

我想從swift 3中關閉數組提取數組,並且它不適合我。我有我的JSON解析器在WeatherGetter類中,我在viewcontroller.swift的視圖中調用它加載文件如何將weather_data數組分配給某個外部變量?無法在swift中訪問關閉之外的數據

class WeatherGetter { 

    func getWeather(_ zip: String, startdate: String, enddate: String, completion: @escaping (([[Double]]) -> Void)) { 
     // This is a pretty simple networking task, so the shared session will do. 
     let session = URLSession.shared 

     let string = "Insert API address" 

     let url = URL(string: string) 
     var weatherRequestURL = URLRequest(url:url! as URL) 
     weatherRequestURL.httpMethod = "GET" 


     // The data task retrieves the data. 
     let dataTask = session.dataTask(with: weatherRequestURL) { 
      (data, response, error) -> Void in 
      if let error = error { 
       // Case 1: Error 
       // We got some kind of error while trying to get data from the server. 
       print("Error:\n\(error)") 
      } 
      else { 
       // Case 2: Success 
       // We got a response from the server! 
       do { 
        var temps = [Double]() 
        var winds = [Double]() 
        let weather = try JSON(data: data!) 
        //print(weather) 
        let conditions1 = weather["data"] 
        let conditions2 = conditions1["weather"] 
        let count = conditions2.count 
        for i in 0...count-1 { 
         let conditions3 = conditions2[i] 
         let conditions4 = conditions3["hourly"] 
         let count2 = conditions4.count 
         for j in 0...count2-1 { 
          let conditions5 = conditions4[j] 
          let tempF = conditions5["tempF"].doubleValue 
          let windspeed = conditions5["windspeedKmph"].doubleValue 
          //temps.updateValue(tempF, forKey: "\(date)//\(j)") 
          temps.append(tempF) 
          winds.append(windspeed) 
         } 
        } 
        //print(temps) 
        //print(winds) 
        completion([temps, winds]) 

       } 
       catch let jsonError as NSError { 
        // An error occurred while trying to convert the data into a Swift dictionary. 
        print("JSON error description: \(jsonError.description)") 
       } 
      } 
     } 

     // The data task is set up...launch it! 

     dataTask.resume() 
    } 


} 

override func viewDidLoad() { 
    super.viewDidLoad() 

    let weather = WeatherGetter() 

    weather.getWeather("13323", startdate: "2016-10-01", enddate: "2017-04-30"){(weather_data) -> Void in 
     print(weather_data[1]) 
    } 

     //Do your stuff with isResponse variable. 
    } 
+0

爲什麼'getWeather()'方法不返回任何內容?畢竟它被稱爲'get'。 – NRitH

回答

0

你可以把它分配給類屬性是這樣的:

var weatherData: [[Double]]() 

override func viewDidLoad() { 
    super.viewDidLoad() 

    let weather = WeatherGetter() 

    weather.getWeather("13323", startdate: "2016-10-01", enddate: "2017-04-30"){(weather_data) -> Void in 
     self.weatherData = weather_data 
     // reload or display data 
    } 
} 

你需要記住的是,網絡請求需要一些時間,所以這就是爲什麼你會打電話像reloadData一旦你知道你已收到回覆。

舉例來說,網絡響應需要100毫秒的響應時間。在數據響應時,viewDidLoad中的所有代碼都將完全完成。所以當你收到數據時,你需要對收到的數據作出迴應。如果您的手機信號不好,可能需要更長的時間。

這就是您使用回調/關閉的原因。當操作完成

UPDATE他們被稱爲:

內的GetWeather的代碼顯示了多個錯誤,我不會讓我跑原樣。

我設法從天氣API得到一個響應,通過略微修改代碼並註釋掉很多。這裏的主要問題是您不會將您的JSON數據轉換爲特定類型。

// The data task retrieves the data. 
    let dataTask = session.dataTask(with: weatherRequestURL) { 
     (data, response, error) -> Void in 

     guard error == nil, let data = data else { 
      print("ERROR") 
      return 
     } 

     // Case 2: Success 
     // We got a response from the server! 
     do { 
      var temps = [Double]() 
      var winds = [Double]() 
      if let weather = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String:AnyObject] { 

       if let conditions1 = weather["data"] as? [String:AnyObject] { 
        print(conditions1) 
       } 

      } 
     } catch let jsonError { 
      // An error occurred while trying to convert the data into a Swift dictionary. 
      print("JSON error description: \(jsonError)") 
     } 

    } 

    dataTask.resume() 

請參閱上面的代碼,我如何在選擇類型時選擇性地展開值。這是您在整個代碼中需要做的事情,並檢查您在每個步驟中獲得的正確數據。不幸的是API響應對我來說太大了,無法在這裏完成。

Unwrapping JSON Swift

Swift Closures

iOS Networking with Swift - 這是一個免費的課程,我強烈推薦。這就是我學習iOS網絡的方式。

+0

非常感謝您的回覆。我是初學者,對回調/關閉知之甚少。我如何實現回調?我仍然沒有從getWeather函數中獲取數組 –

+0

我沒有完全檢查你在getWeather函數內部做了什麼,我會在我的機器上運行它並檢查。它可能太多了,無法在這裏完全解釋閉包,但我有一些我可以分享的資源/鏈接。讓我看看代碼中發生了什麼第一次 – Scriptable

+0

我已經更新了我的答案,並提供了一些可能有用的資源 – Scriptable

0

正如@Scriptable所述,響應需要一段時間才能被處理,因爲它是異步的。你可以做的是添加OperationQueue.main.addOperation將當前進程分配給主隊列。這將優先處理您的網絡響應。你也可以把你的reloadData放在這個部分。

var weatherData: [Double]() 

override func viewDidLoad() { 
super.viewDidLoad() 

    let weather = WeatherGetter() 

    OperationQueue.main.addOperation { 
     weather.getWeather("13323", startdate: "2016-10-01", enddate: "2017-04-30"){(weather_data) -> Void in 
     print(weather_data[1]) 
     // reloadData() 
     } 
    } 
}