2017-06-24 8 views
1

detailという名前のオブジェクトをRestManager.swiftという名前のファイルからViewControllerに渡そうとしています。オブジェクトにはすべての要素が含まれていますが、ビューコントローラで呼び出すと空になります。私がオンラインで集めたものから、バックグラウンドスレッドで作業しているURLSessionと関係があるかもしれません。URLSessionからViewControllerへのオブジェクトの受け渡し

私のRestManager.swiftはこのように見えます。

class RestManager { 


func reqDetails(id: Int) { 
    // Create URL 
    let id = String(id) 
    let url = "https://website.example.com/" 
    let url = URL(string: url + id)! 

    let task = URLSession.shared.dataTask(with: url) { (data, response, error) in 

     if error != nil 
     { 
      print ("ERROR") 
     } 

     else 
     { 
      if let content = data 
      { 

        let jsonData = JSON(data: content) 

        let id = jsonData["id"].intValue 
        let name = jsonData["title"]["rendered"].string! 
        let link = jsonData["link"].url! 
        let content = jsonData["content"]["rendered"].string! 


        // Create Object 
        let detail = Detail(id: id, name: name, content: content, thumbnailUrl: link) 
        self.details.append(detail) 

      } 
     } 
    } 
    task.resume() 
} 
} 

私のビューコントローラはそうのようになります。

class DetailViewController: UIViewController { 

var ListingID = Int() 
let restManager = RestManager() 

@IBOutlet weak var ContentLabel: UILabel! 

override func viewDidLoad() { 
    super.viewDidLoad() 
    restManager.reqDetails(id: ListingID) 
    ContentLabel.text? = restManager.details[0].name // After running the app this index value is out of range. 


} 

.. 

} 

答えて

3

は、機能的に近いが、この

などのデータを渡すために

'を

func reqDetails(id: Int,completionHandler:@escaping (_ detilObject:Detail)->Void) { 
    // Create URL 
    let id = String(id) 
    let url = "https://website.example.com/" 
    let url = URL(string: url + id)! 

    let task = URLSession.shared.dataTask(with: url) { (data, response, error) in 

     if error != nil 
     { 
      print ("ERROR") 
     } 

     else 
     { 
      if let content = data 
      { 

        let jsonData = JSON(data: content) 

        let id = jsonData["id"].intValue 
        let name = jsonData["title"]["rendered"].string! 
        let link = jsonData["link"].url! 
        let content = jsonData["content"]["rendered"].string! 


        // Create Object 
        let detail = Detail(id: id, name: name, content: content, thumbnailUrl: link) 
        self.details.append(detail) 
        completionHandler(self.details) 

      } 
     } 
    } 
    task.resume() 
} 

' を使用して、このようなあなたの関数を呼び出します。 「

restManager.reqDetails(id: ListingID , completionHandler: { (detail) in 
       // here is your detail object 
      }) 

0

あなたはあなたの問題は(それはすぐに準備ができて非常に低いだと)すぐに応答を読み取ろうに起因することが正しいです。データが準備できたら(エラーが発生したとき)、コントローラ(メインスレッド/キュー)に通知する方法が必要です。 initRestManager(controller: self))に渡された

簡単な無粋ソリューションは、(それが保持サイクルを起こさないように弱い)あなたのRestManagerweak var controller: DetailViewControllerを追加することです場合とコントローラを伝えるためにURLタスクの閉鎖で、その参照を使用します準備ができているか、エラーが出ています。

RestManagerDetailViewControllerの緊密な結合を避けるために、通知またはデリゲートパターンを使用する必要があります。

+0

:「effectView」ものを無視し、それが参考になっかもしれませんJSONデータにマッピングされているこれらの構造体を知ることも

そして:-)特別なカーソル待ちスピナーのためでありますあなたのviewcontrollerのパラメータとしてあなたの '詳細'配列でコールバックを取得します。今すぐプロトコルで代理人を迅速に実装する方法を見てみましょう。 – Tann

0

こんにちは、私はあなただけで非同期プログラミングの典型的な落とし穴に遭遇したと思います。あなたは、URLSessionから戻ってくる前に、タスクの戻り値を求めています。 この例のような補完ハンドラを自分で作成することで、Darkskyの天気データを取得できます。 これについてはクラスを作成する必要はありません。関数だけです。

PSノート私はAlamofire、SwiftyJSON、Glossを使用しており、RESTインターフェイスを使用して複雑さを大幅に軽減しています。これはスイフト3です!

import Alamofire 
import SwiftyJSON 
import Gloss 


typealias DarkSkyWeatherForecast = (_ json : Gloss.JSON?, _ error : Error?) -> Void 


func getWeatherForcast(latitude:Double, longitude:Double, completionHandler:@escaping DarkSkyWeatherForecast) -> Void { 

    let urlString = "https://api.darksky.net/forecast/"+darkSkyKey+"/"+String(latitude)+","+String(longitude)+"?units=si" 

    Alamofire.request(urlString).responseJSON { (response) in 
     if let resp = response.result.value { 
      let json = JSON(resp) 
      let glossJson = json.dictionaryObject 
      completionHandler(glossJson, nil) 
     }else{ 
      completionHandler(nil, response.error) 
     } 
    } 
} 

、通話、このような関数:

getWeatherForcast(latitude: lat, longitude: lon) { (jsonArg, error) in 
      if error == nil{ 
       guard let weather = DarkSkyWeather(json: jsonArg!) else { 
        self.effectView.removeFromSuperview() 
        return 
       } 
       if let ambTemp = weather.currently?.temperature, let windspd = weather.currently?.windSpeed, let windDir = weather.currently?.windBearing{ 
        self.effectView.removeFromSuperview() 
        self.ambTemperature.text = String(ambTemp) 
        self.windSpeed.text = String(windspd) 
        self.windDirection.text = String(windDir) 
        self.getSpeed() 
       } 
      }else{ 

       self.effectView.removeFromSuperview() 
       let alert = UIAlertController(title: "Error", message: "Could not get weather forecast", preferredStyle: .alert) 
       let okAction = UIAlertAction(title: "OK", style: .default, handler: { (action) in 
        self.dismiss(animated: true, completion: nil) 
       }) 
       alert.addAction(okAction) 
       self.present(alert, animated: true, completion: nil) 
      } 
     } 

注完了ハンドラが終了し、実際にいくつかのデータまたはエラーが返されたら、私はテキストフィールドを埋めます。

//common struct for weather data 
public struct WeatherDataStruct : Decodable{ 
    let time : Int? 
    let summary : String? 
    let icon : String? 
    let precipIntensity : Double? 
    let precipProbability : Double? 
    let precipType : String? 
    let temperature : Double? 
    let apparentTemperature : Double? 
    let dewPoint : Double? 
    let humidity: Double? 
    let windSpeed : Double? 
    let windBearing : Int? 
    let visibility : Double? 
    let cloudCover : Double? 
    let pressure : Double? 
    let ozone : Double? 

    public init?(json: JSON){ 
     self.time = "time" <~~ json 
     self.summary = "summary" <~~ json 
     self.icon = "icon" <~~ json 
     self.precipIntensity = "precipIntensity" <~~ json 
     self.precipProbability = "precipProbability" <~~ json 
     self.precipType = "precipType" <~~ json 
     self.temperature = "temperature" <~~ json 
     self.apparentTemperature = "apparantTemperature" <~~ json 
     self.dewPoint = "dewPoint" <~~ json 
     self.humidity = "humidity" <~~ json 
     self.windSpeed = "windSpeed" <~~ json 
     self.windBearing = "windBearing" <~~ json 
     self.visibility = "visibility" <~~ json 
     self.cloudCover = "cloudCover" <~~ json 
     self.pressure = "pressure" <~~ json 
     self.ozone = "ozone" <~~ json 
    } 
} 

//hourly weather struct 
public struct HourlyStruct : Decodable{ 
    let summary : String? 
    let icon : String? 
    let data : [WeatherDataStruct]? 

    public init?(json: JSON) { 
     self.summary = "summary" <~~ json 
     self.icon = "icon" <~~ json 
     self.data = "data" <~~ json 
    } 
} 

//total struct for the whole json answer from darksky weather 
public struct DarkSkyWeather : Decodable{ 
    let latitude : Double? 
    let longitude : Double? 
    let timezone : String? 
    let offset : Int? 
    let currently : WeatherDataStruct? 
    let hourly : HourlyStruct? 

    public init?(json: JSON) { 
     self.latitude = "latitude" <~~ json 
     self.longitude = "longitude" <~~ json 
     self.timezone = "timezone" <~~ json 
     self.offset = "offset" <~~ json 
     self.currently = "currently" <~~ json 
     self.hourly = "hourly" <~~ json 
    } 
} 
あなたは委任プロセスを使用することができます
関連する問題