2017-01-17 2 views
0

Я пытаюсь сериализовать запрос GET, затем создать объект видео, а затем добавить этот объект фильма в массив фильмов, который я буду использовать для отображения информации об интерфейсе.Попытка добавить элементы JSON к массиву, но не работает

Я новичок, и боролись с этой проблемой в течение некоторого времени :(

Если вы посмотрите на self.movies?.append(movie), что не должно работать? Я не вижу никаких причин, как, когда я пытаюсь получить первый элемент я получаю фатальным индекс ошибки вне границ означает, что я в массив еще не заполнены .... не знаю, что я делаю неправильно :(

import UIKit 

class ViewController: UIViewController { 

var movies:[Movie]? = [] 

@IBOutlet weak var uiMovieTitle: UILabel! 


override func viewDidLoad() { 
    super.viewDidLoad() 
    // Do any additional setup after loading the view, typically from a nib. 
    getMovieData() 
    print(self.movies?.count) 
    setUI() 


} 

@IBAction func yesBtn(_ sender: UIButton) { 
    print(movies?[5].title ?? String()) 
} 

@IBAction func seenBtn(_ sender: UIButton) { 

} 

@IBAction func noBtn(_ sender: UIButton) { 

} 


@IBOutlet weak var moviePoster: UIImageView! 


let urlString = "https://api.themoviedb.org/3/discover/movie?api_key=935f539acbfed4b9e5534ddeed3fb57e&language=en-US&sort_by=popularity.desc&include_adult=false&include_video=false&page=1&with_genres=12" 

func getMovieData(){ 
    //Set up URL 
    let todoEndPoint: String = "https://api.themoviedb.org/3/discover/movie?api_key=935f539acbfed4b9e5534ddeed3fb57e&language=en-US&sort_by=popularity.desc&include_adult=false&include_video=false&page=1&with_genres=12" 

    guard let url = URL(string: todoEndPoint) else { 

     print("Cant get URL") 
     return 
    } 

    let urlRequest = URLRequest(url: url) 

    //Setting up session 
    let config = URLSessionConfiguration.default 
    let session = URLSession.shared 

    //Task setup 
    let task = session.dataTask(with: urlRequest) { (data, URLResponse, error) in 

     //Checking for errors 
     guard error == nil else{ 
      print("Error calling GET") 
      print(error) 
      return 
     } 
     //Checking if we got data 
     guard let responseData = data else{ 
      print("Error: No data") 
      return 
     } 

     self.movies = [Movie]() 

     do{//If we got data, if not print error 

      guard let todo = try JSONSerialization.jsonObject(with: responseData, options:.mutableContainers) as? [String:AnyObject] else{ 

       print("Error trying to convert data to JSON") 
       return 


      }//if data is Serializable, do this 


      if let movieResults = todo["results"] as? [[String: AnyObject]]{ 
       //For each movieobject inside of movieresult try to make a movie object 
       for moviesFromJson in movieResults{ 

        let movie = Movie() 

        //If all this works, set variables 
        if let title = moviesFromJson["title"] as? String, let movieRelease = moviesFromJson["release_date"] as? String, let posterPath = moviesFromJson["poster_path"] as? String, let movieId = moviesFromJson["id"] as? Int{ 

         movie.title = title 
         movie.movieRelease = movieRelease 
         movie.posterPath = posterPath 
         movie.movieId = movieId 


        } 

        self.movies?.append(movie) 

       } 

      } 
     }//do end 

     catch{ 
      print(error) 
     } 


    } 
    ////Do Stuff 



    task.resume() 

} 

func setUI(){ 

    //uiMovieTitle.text = self.movies![0].title 
    //print(self.movies?[0].title) 
} 

}

мой класс фильм:

import UIKit 

class Movie: NSObject { 


var title:String? 
var movieRelease: String? 
var posterPath:String? 
var movieId:Int? 
var movieGenre:[Int] = [] 

//public init(title:String, movieRelease:String, posterPath:String,movieId:Int) { 
    // self.movieId = movieId 
    //self.title = title 
    //self.movieRelease = movieRelease 
    //self.posterPath = posterPath 
    //self.movieGenre = [movieGenre] 



//} 

}

+0

Не пытайтесь добавить в вызове GET, он будет делать это ASync, так что вы получите эту ошибку, попробуйте сделать это в функцию обратного вызова, если вы не знаете, как это сделать, пожалуйста, спросите, и я попытаюсь объяснить его примером кода –

+0

Спасибо за такой быстрый ответ! Да, я не знаю, как это сделать, и объясните, пожалуйста, потому что я понимаю, что вы имеете в виду, но я не знаю, как и где я должен это делать :) – Pr0tonion

+0

okey позвольте мне, я сделаю новый ответ –

ответ

0

getMovieData называет сеть асинхронно. Ваш viewDidLoad вызывает это, а затем вызывает setUI() - но сеть все еще продолжается, когда вызывается setUI.

Вместо этого позвоните по номеру setUI, когда сеть будет завершена - после линии self.movies?.append(movie). Код UI должен произойти в основном потоке. Так что ...

for moviesFromJson... // your existing code 
    ... 
    self.movies?.append(movie) 
} 

// Refresh UI now movies have loaded. 
DispatchQueue.main.async { 
    setUI() 
} 
+0

Спасибо !!! Работал как шарм! – Pr0tonion

0
 import UIKit 

    class ViewController: UIViewController { 

    var movies:[Movie]? = [] 

    @IBOutlet weak var uiMovieTitle: UILabel! 


    override func viewDidLoad() { 
     super.viewDidLoad() 
     // Do any additional setup after loading the view, typically from a nib. 
     getMovieDataCall(completionHandler: {data, error in self. getMovieDataCallBack(data: data, error: error)}) 

    } 

func getMovieDataCallBack(data: Data?, error: Error?) { 
     if error == nil { 
      let dictionary = try! JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! Dictionary<String, AnyObject> 
      //do your appending here and then call setUI() 
      print("dictionaryMovie \(dictionary)") 
     } else { 
      showAlertView("", error?.localizedDescription) 
     } 
} 

    func getMovieDataCall(completionHandler: @escaping (Data?, Error?) -> Void)){ 
     //Set up URL 
     let todoEndPoint: String = "https://api.themoviedb.org/3/discover/movie?api_key=935f539acbfed4b9e5534ddeed3fb57e&language=en-US&sort_by=popularity.desc&include_adult=false&include_video=false&page=1&with_genres=12" 

     guard let url = URL(string: todoEndPoint) else { 

      print("Cant get URL") 
      return 
     } 

     let urlRequest = URLRequest(url: url) 

     //Setting up session 
     let config = URLSessionConfiguration.default 
     let session = URLSession.shared 

     //Task setup 
     let task = session.dataTask(with: urlRequest) { (data, URLResponse, error) in 

       if error != nil { 
        NSLog("GET-ERROR", "=\(error)"); 
        completionHandler(nil, error) 
       } else { 
        let dataString = String(data: data!, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) 
        print(dataString!) 
        completionHandler(data, nil) 
       } 

     task.resume() 

    } 

    func setUI(){ 

    } 
+0

вы видите, что сначала нужно выполнить запрос Get, иметь обработчик завершения для этого, когда это будет сделано, и у вас нет ошибки, добавьте, затем обновите свой пользовательский интерфейс, надеюсь, что это поможет, если вам нужно объяснить, пожалуйста, спросите –

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