Home>
Progress from the last question

Because I received the result as I thought last time,
1.I put a query and corresponded to multiple information.
2. Add TextField and add search function in TableView.
3. Create TableViewCell and add the items I want to display in nib.
4. Obtained id from APi and added didselect.

Source code
import UIKit
import SafariServices
class ViewController: UIViewController,UITextFieldDelegate {
    @IBOutlet weak var movieTableView: UITableView!
    @IBOutlet weak var field: UITextField!
    var movies = [Movie]()
    override func viewDidLoad() {
        super.viewDidLoad()
        movieTableView.register(MovieTableViewCell.nib(), forCellReuseIdentifier: MovieTableViewCell.identifier)
        movieTableView.delegate = self
        movieTableView.dataSource = self
        field.delegate = self
        fechData()
    }
    func textFieldShouldReturn(_ textField: UITextField) ->Bool {
        fechData()
        return true
    }
    func fechData(){
        field.resignFirstResponder()
        guard let text = field.text, !text.isEmpty else {
            return
        }
        let query = text.replacingOccurrences(of: "", with: "%20")
        let url = text.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
        movies.removeAll()
        URLSession.shared.dataTask(with: URL(string: "https://api.themoviedb.org/3/search/movie?api_key=your API&language=ja&query=\(query)&page=1")!,
                                   completionHandler: (data, response, error in
                                    guard let data = data else {
                                        print(error?.localizedDescription ?? "Unknown error")
                                        return
                                    }
                                    var result: MovieStruct?
                                    do {
                                        result = try JSONDecoder().decode(MovieStruct.self, from: data)
                                    }
                                    catch{
                                        print("JSON perse error")
                                    }
                                    guard let finalResult = result else{
                                        return}
                                    let newMovies = finalResult.results
                                    self.movies.append(contentsOf: newMovies)
                                    DispatchQueue.main.async {
                                        self.movieTableView.reloadData()
                                    }
            }).resume()
    }
}
extension ViewController:UITableViewDelegate,UITableViewDataSource{
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) ->Int {
        return movies.count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->UITableViewCell {
        let cell = movieTableView.dequeueReusableCell(withIdentifier: MovieTableViewCell.identifier, for: indexPath) as! MovieTableViewCell
        cell.configure(with: movies[indexPath.row])
        return cell
    }
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        let url = "https://www.themoviedb.org/movie/\(movies[indexPath.row].id)?language=ja"
        let vc = SFSafariViewController(url: URL(string: url)!)
        present(vc, animated: true)
    }
}
struct MovieStruct:Codable {
    let results: [Movie]
}
struct Movie: Codable {
    let title: String
    let release_date:String?
    let poster_path:String?
    let id:Int?
}
TableViewCell
import UIKit
class MovieTableViewCell: UITableViewCell {
    @IBOutlet var movieTitleLabel: UILabel!
    @IBOutlet var movieReleaseDateLabel: UILabel!
    @IBOutlet var moviePosterImageView: UIImageView!
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }
    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }
    static let identifier = "MovieTableViewCell"static func nib() ->UINib{
        return UINib(nibName: "MovieTableViewCell", bundle: nil)
    }
    func configure(with model:Movie){
        self.movieTitleLabel.text = model.title
        self.movieReleaseDateLabel.text = model.release_date
        let url = model.poster_path
        if let data = try? Data(contentsOf: URL(string: url!)!){
            self.moviePosterImageView.image = UIImage(data: data)
        }
    }
}
Questions&errors

1. Search hits vary and nill is included in url.

For example, if you enter star, the STAR WARS information will appear.
If i type titanic, in configure

Fatal error: Unexpectedly found nil while unwrapping an Optional value


Next to url is nill.

2. poster is not displayed
Whether or not you hit the search above
When Hit, moviePosterImageView set in MovieTableViewCell is blank with nothing displayed.
Since title and release_date are displayed, I think that it is set to nil somewhere whether poster_path is not received.

3. Japanese cannot be supported
Previously to receive API Japanese

let url = text.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)


I learned that I can correspond in Japanese with, but at the URL Session

Fatal error: Unexpectedly found nil while unwrapping an Optional value


Will come out.

4. I can't fly to the site I wanted with didselect.

let url = "https://www.themoviedb.org/movie/\(movies[indexPath.row].id)?language=ja"
let vc = SFSafariViewController(url: URL(string: url)!)
present(vc, animated: true)


I would like to jump to the IMDB movie information details page like this
I fly to IMDB's HP site, but it says that the page I am looking for cannot be found.

STARWARS Last Jedi Details URL
https://www.themoviedb.org/movie/181808-star-wars-the-last-jedi?language=ja
Doraemon Takarajima
//https://www.themoviedb.org/movie/495925?language=ja


As the search URL varies as described above,

let url = "https://www.themoviedb.org/movie/\(movies[indexPath.row].id)?language=ja"


In the above case, only id is set, so should Titile be taken into consideration?
We apologize for the large number of questions and codes.

  • Answer # 1

    1. Search hits vary and nill is included in url.
    2. poster is not displayed

    As I pointed out last time,model.poster_pathIsnilMay be.
    It seems that some movies have no poster information (image URL). In such cases,nilWill come back.

    If you search by "titanic", many movies have posters, but "titanic 2000" does not have a poster, so an error will occur during cell creation.

    Also,model.poster_pathI don't know the base URL (I don't know if it's correct) but only the image name, so I need to add the base URL.

    https://developers.themoviedb.org/3/getting-started/images

    If you modify these all together

      func configure(with model:Movie){
            self.movieTitleLabel.text = model.title
            self.movieReleaseDateLabel.text = model.release_date
            // Add the URL to poster_path.
            // By the way, ignore if posther_path is nil
            if let poster_path = model.poster_path {
                let url = "https://image.tmdb.org/t/p/w500/" + poster_path
                if let data = try? Data(contentsOf: URL(string: url)!){
                    self.moviePosterImageView.image = UIImage(data: data)
                }
            } else {
                // If there is no applicable poster
                // titanic 2000 etc.
                moviePosterImageView.image = nil
            }
        }

    It will look like.

    Cell is reused, so if there is no image data,moviePosterImageView.imageTonilIt may be better to put in or display an image corresponding to "no poster".

    3. Japanese cannot be supported

    let url = text.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)

    addingPercentEncoding(withAllowedCharaters:)The return value of is an optional type, so you need to keep that in mind.

    addingPercentEncoding(withAllowedCharacters:)

    Return Value

    Returns the encoded string, or nil if the transformation is not possible.

    Easy to fix

          //let query = text.replacingOccurrences(of: "", with: "%20")
            //let url = text.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
            guard let query = text.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else (
                // Processing when conversion is not possible
                print("Percent encoding failure")
                return
            }

    With this feeling, you will be able to search in Japanese for the time being.

    4. I can't fly to the site I wanted with didselect.

    I think this is the only way for you to read the API reference yourself and find out how to get the URL of detailed information.

    At least the JSON I'm searching this time doesn't seem to contain such information.