2016-04-16 18 views
0

Web APIを使用してJSONにアクセスし、GRDMovieオブジェクトを初期化しています。それが進行している間、他のいくつかのプロパティのために別のURLを使用してAPIをヒットする必要があります。これは、クロージャがスキップされるため、GRDMovie initメソッドでいくつかの問題を引き起こしています。以下のコード:Swift - クロージャを使用してinitメソッドのプロパティを設定する

var posterImage : UIImage? 
let title : String 
let score : Double 
var rating : String? 
let releaseDate : String 
let overview : String 
let movieID : Int 
let smallURL : String 
let year : String 

init(title:String, overview:String, score:Double, movieID:Int, releaseDate:String, smallURL: String, year:String) { 

    self.title = title 
    self.overview = overview 
    self.score = score 
    self.movieID = movieID 
    self.releaseDate = releaseDate 
    self.smallURL = smallURL 
    self.year = year 
    self.rating = nil 
    self.posterImage = nil 


    self.getMovieRatingWith(movieID) { (rating) in 
     self.rating = rating 
    } 

    self.getPosterImageDataFromURL(smallURL) { (posterImage) in 
     self.posterImage = posterImage 
    } 
} 

func getMovieRatingWith(movieID: Int, completion: (rating: String) ->()) { 

    var apiDict = NSDictionary() 
    var rating: String = "" 

    let urlString:String = "http://api.themoviedb.org/3/movie/\(movieID)?api_key=ebea8cfca72fdff8d2624ad7bbf78e4c&append_to_response=releases" 
    let escapedUrlString = urlString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet()) 
    let apiURL = NSURL(string:escapedUrlString!) 
    let session = NSURLSession.sharedSession() 

    session.dataTaskWithURL(apiURL!, completionHandler: { (data:NSData?, response:NSURLResponse?, error:NSError?) in 
     do { 
      if let data2 = data { 
       let jsonDict = try NSJSONSerialization.JSONObjectWithData(data2, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary 
       //send json outward 
       apiDict = jsonDict 

       if let releases = apiDict["releases"] as? NSDictionary { 
        if let countries = releases["countries"] as? [NSDictionary] { 
         for countryData in countries { 
          if let place: String = countryData["iso_3166_1"] as? String { 
           if place == "US" { 
            rating = countryData["certification"] as! String 
           } else { 

           } 
          } 
         } 
        } 
       } 

       if rating == "" { 
        rating = "Not Available" 
       } 

       completion(rating: rating) 
       //print(rating) 
      } 
     } catch { 
      //handle NSError 
      print("error") 
     } 
    }).resume() 
} 

func getPosterImageDataFromURL(smallURL:String, completion: (posterImage: UIImage) ->()) { 

    let escapedURLString:String = smallURL.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())! 
    let callURL = NSURL(string: escapedURLString) 
    let session = NSURLSession.sharedSession() 

    session.dataTaskWithURL(callURL!) { (data:NSData?, response:NSURLResponse?, error:NSError?) in 
     do { 
      if let data2 = data { 
       let poster = UIImage(data: data2) 
       completion(posterImage: poster!) 
      } 
     } 
    } 

} 

当然私はposterImageと評価のためにnilを得ています。これらの値を正しく取得するには、どのように構造化するのですか?

+1

あなたはあまりにもすぐに値を読み取っているようですか? – nielsbot

+1

あなたは値が設定されるのを待って、現在のスレッドをブロックすることができます。これはおそらくあなたがやりたいことではありません。 _rating_と_posterImage_の値が最終的に設定されたときに通知を送信する(またはKVOのようなものを使用する)ようにアプリケーションを再構築することができます。 – nielsbot

+1

あなたは本当にinitメソッドでネットワークコールを行うべきではありません。そのオブジェクトに対して必要なすべての呼び出しを行い、見つかったデータでオブジェクトを作成します。 – PeejWeej

答えて

0

私はその代わりにコントローラのAPI呼び出しを行う方が良いと思います。最初にobjを作成するか、apiコールバックが必要なものに依存した後にobjを作成することができます。

objを最初に作成する場合は、以下のようにします。 GRDMovieController.swiftで

(私はランダムに名前を付ける):OBJ INITどこかで

let obj : GRDMovie? 

とデータを取得するためのAPIを呼び出します。

obj = GRDMovie(title, overview: overview, score: score, movieID: id, releaseDate: date, smallURL: url, year: year) 
getMovieRatingWith(obj) 
getPosterImageDataFromURL(obj) 

と機能は次のようなものになることができますこれは:

func getMovieRatingWith(movieObj: GDVMovie) { 
    var apiDict = NSDictionary() 
    var rating: String = "" 

    let urlString:String = "http://api.themoviedb.org/3/movie/\(movieObj.movieID)?api_key=ebea8cfca72fdff8d2624ad7bbf78e4c&append_to_response=releases" 
    let escapedUrlString = urlString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet()) 
    let apiURL = NSURL(string:escapedUrlString!) 
    let session = NSURLSession.sharedSession() 

    session.dataTaskWithURL(apiURL!, completionHandler: { (data:NSData?, response:NSURLResponse?, error:NSError?) in 
     do { 
      if let data2 = data { 
       let jsonDict = try NSJSONSerialization.JSONObjectWithData(data2, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary 
       //send json outward 
       apiDict = jsonDict 

       if let releases = apiDict["releases"] as? NSDictionary { 
        if let countries = releases["countries"] as? [NSDictionary] { 
         for countryData in countries { 
          if let place: String = countryData["iso_3166_1"] as? String { 
           if place == "US" { 
            rating = countryData["certification"] as! String 
           } else { 

           } 
          } 
         } 
        } 
       } 

       if rating == "" { 
        rating = "Not Available" 
       } 

       movieObj.rating = rating 

       //print(rating) 
      } 
     } catch { 
      //handle NSError 
      print("error") 
     } 
    }).resume() 
} 

func getPosterImageDataFromURL(movieObj: GRDMovie) { 

    let escapedURLString:String = movieObj.smallURL.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())! 
    let callURL = NSURL(string: escapedURLString) 
    let session = NSURLSession.sharedSession() 

    session.dataTaskWithURL(callURL!) { (data:NSData?, response:NSURLResponse?, error:NSError?) in 
     do { 
      if let data2 = data { 
       let poster = UIImage(data: data2) 
       movieObj.posterImage = poster 
      } 
     } 
    } 

} 

私が間違っている場合は、私がこれを助けることを願って私を修正してください。