2016-04-16 3 views
0

Я запускаю веб-API для доступа к некоторому JSON и инициализации объекта GRDMovie. Хотя это происходит, мне нужно нажать API, используя другой URL для некоторых других свойств. Это вызывает некоторые проблемы в методе init GRDMovie, поскольку закрытие пропускается. Код ниже: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!) 
      } 
     } 
    } 

} 

Естественно, я получаю ноль для плакатаИзделия и рейтинг. Как мне структурировать это, чтобы правильно зафиксировать эти значения?

+1

похоже, что вы слишком быстро читаете значения? – nielsbot

+1

вы можете дождаться значений, которые будут установлены, блокируя текущий поток, который, вероятно, не является тем, что вы хотите сделать. или реструктурировать приложение, чтобы вы отправили уведомление (или использовали что-то вроде KVO) для принятия решения, когда значения _rating_ и _posterImage_ в конечном итоге будут установлены. – nielsbot

+1

Вы действительно не должны делать сетевые вызовы в методе init. Сделайте все вызовы, необходимые для этого объекта, затем создайте объект с найденными данными. – PeejWeej

ответ

0

Я думаю, что лучше сделать вызов api в контроллере. Вы можете сначала создать объект obj или создать его после того, как обратный вызов api зависит от того, что вы хотите.

Если вы хотите создать объект obj, сделайте это ниже.

В GRDMovieController.swift (я просто назвать это случайным образом):

let obj : GRDMovie? 

где-нибудь инициализации в OBJ и вызвать 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 
      } 
     } 
    } 

} 

Пожалуйста, исправьте меня, если я ошибаюсь и надеюсь, что это поможет.

Смежные вопросы