尝试将JSON项附加到数组但不起作用

时间:2017-01-17 01:06:24

标签: ios arrays json swift

我正在尝试序列化一个GET请求然后制作一个电影对象,然后将该电影对象附加到一个电影数组中,我将用它来显示UI上的信息。

我是新人,现在已经在这个问题上挣扎了一段时间:(

如果你看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]



//}

}

2 个答案:

答案 0 :(得分: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()
}

答案 1 :(得分: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(){

    }