Here is my code for the AnimeDetailsViewController.swift ``` import UIKit class AnimeDetailsViewController: UIViewController { @IBOutlet weak var titleLabel: UILabel! @IBOutlet weak var episodesLabel: UILabel! @IBOutlet weak var posterView: UIImageView! @IBOutlet weak var synopsisLabel: UILabel! var animeItem: AnimeFromTop! //we get the data for this animeItem from the DiscoverViewController during segue. Anime objectthat the user selected from the top anime list var animeSynopsis : String? override func viewDidLoad() { super.viewDidLoad() // let animeID = animeItem.mal_id//we need the anime id to get the synopsis of the anime // getSynopsis(anime_ID: animeID) getSynopsis(anime_ID: animeItem.mal_id) { (synopsis, error) in DispatchQueue.main.async { self.synopsisLabel.text = synopsis print(self.synopsisLabel.text as Any) } } //set up layout synopsisLabel.sizeToFit() if animeItem.episodes == 0 { episodesLabel.text = "Null" } else { episodesLabel.text = "\(animeItem.episodes ?? 0) episodes" } titleLabel.text = animeItem.title let imgUrlString = animeItem.image_url //image url in string let imgURL = URL(string: imgUrlString)! posterView.af.setImage(withURL: imgURL) // setupLayout() // Do any additional setup after loading the view. } //The purpose of this function is to make an API call to get the synopsis of our anime, which is not provided by the top anime endpoint. This function gets an anime object from the API but only with the synopsis because we don't need the rest of the huge data. func getSynopsis(anime_ID : Int, synopsisCompletionHandler: @escaping (String?, Error?) -> Void) { let animeID = anime_ID //we need the anime id to get the synopsis of the anime //API CALL to get the synopsis let urlString = "https://api.jikan.moe/v3/anime/\(animeID)" //url String guard let url = URL(string: urlString) else { //if not able to create a url from urlString, just return print("Not able to create url object from url String") return } //Create a Data Task, which is how you perform actual API calls and networking tasks let task = URLSession.shared.dataTask(with: url, completionHandler: { data, _, error in guard let data = data, error == nil else { return } //do - catch function because the decoder function can actually throw an error so we want to account for that too var anime: AnimeSynopsis? do { anime = try JSONDecoder().decode(AnimeSynopsis.self, from: data) if let synopsis = anime?.synopsis { synopsisCompletionHandler(synopsis, nil) } } catch { print("Failed to Decode Error") } }) task.resume() //starts the API call //this is where synopsisCompletionHandler(synopsis, nil) is called } /* // MARK: - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation override func prepare(for segue: UIStoryboardSegue, sender: Any?) { // Get the new view controller using segue.destination. // Pass the selected object to the new view controller. } */ } ``` Here is my code for the DiscoverViewController.swift (which shows the top anime as well as lets me view the Anime's info when clicked on) ``` import UIKit import AlamofireImage class DiscoverViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate { @IBOutlet weak var topTableView: UITableView! var filteredAnimes: SearchResults? //this property will hold the animes that user searches for // topResults will contain the array of dictionaries that represent the top animes returned to us by an API call var topResults : TopAnimes? //By initializing UISearchController with a nil value for searchResultsController, you’re telling the search controller that you want to use the same view you’re searching to display the results. If you specify a different view controller here, the search controller will display the results in that view controller instead. var searchController: UISearchController! //In order for the DiscoverViewController to respond to the search bar, it must implement UISearchResultsUpdating. This protocol defines methods to update search results based on information the user enters into the search bar. Do this outside of the main DiscoverViewController function at the bottom. private var searchResultsTableController : SearchResultsViewController! //creates an instance of the class SearchViewController var anime_with_synopsis : String? override func viewDidLoad() { super.viewDidLoad() setUpSearchBar() // Loading data for the top anime view controller in Discover View topTableView.dataSource = self topTableView.delegate = self let group = DispatchGroup() group.enter() getTopAnimes(group) //API call to get an array of dictionaries of top animes group.wait() topTableView.reloadData()//calls on the table view functions to reload data with data received from the API call } //MARK: - API Call and table view configurations for the Top Anime table view controller func getTopAnimes(_ group: DispatchGroup) { let urlString = "https://api.jikan.moe/v3/top/anime" //url String //Create a url object from the url String. Use guard so that if cannot be created as an url object, then provide optional error message. Created as an optional guard let url = URL(string: urlString) else { //if not able to create a url from urlString, just return print("Not able to create url object from url String") return } //Create a Data Task, which is how you perform actual API calls and networking tasks //the completionHandler returns 3 optional parameters, but we only care about the Data and Error so we will do _ for discardable for the 2nd parameter URLResponse let task = URLSession.shared.dataTask(with: url, completionHandler: { [self] data, _, error in guard let data = data, error == nil else { return } //do - catch function because the decoder function can actually throw an error so we want to account for that too var results: TopAnimes? do { results = try JSONDecoder().decode(TopAnimes.self, from: data) } catch { print("Failed to Decode Error") } guard let final = results else { return } //final is the top results array // print(final.top) topResults = final group.leave() }) task.resume() //starts the API call } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 50 //return 50 because get request to the top/anime/ endpoint returns a list of 50 anime } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { //reuse cell prototype. Reuse the cell of class TopAnimeTableViewCell with identifier of same name let cell = tableView.dequeueReusableCell(withIdentifier: "TopCell", for: indexPath) as! TopAnimeTableViewCell guard let topAnimes = self.topResults else { //to ensure topAnimes is not nil return cell } let anime = topAnimes.top[indexPath.row] let title = anime.title let animeId = anime.mal_id cell.TopAnimeTitle.text = title let imgUrlString = anime.image_url //image url in string let imgURL = URL(string: imgUrlString)! //convert the image url from string to url so that we can download it. Since imgURL is an optional type, must unwrap it so use force-unwrap using '!' to abort execution if the optional value contains 'nil' //this function .af.setImage(withURL: URL) from the pod AlomofireImage downloads the images from the imgURL and sets it to the UIImageView. cell.TopImage.af.setImage(withURL: imgURL) let item: AnimelistItem! = AnimelistItem(mal_id: animeId, image_url: imgUrlString, title: title, synopsis: anime.synopsis, episodes: anime.episodes) cell.item = item cell.viewController = self return cell } //Segues to AnimeDetailsViewController when a cell is selected func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { // if let cell = tableView.cellForRow(at: indexPath) as? TopAnimeTableViewCell { // cell.didSelect(indexPath: indexPath as NSIndexPath) // } // print("selected") let anime = topResults?.top[indexPath.row] performSegue(withIdentifier: "showAnimeDetails", sender: anime) } func setUpSearchBar() { searchResultsTableController = (storyboard?.instantiateViewController(withIdentifier: "SearchResultsViewController") as! SearchResultsViewController) // Initializing with searchResultsController set to searchResultTableController means that // UIsearchController will use this view controller to display the search results searchController = UISearchController(searchResultsController: searchResultsTableController) //Makes the Search Results Updater the searchResultTableController of class SearchResultsViewController. So whenever user types in the search bar, the updateSearchResults(for searchController: UISearchController) function in the SearchResultsViewController is called which will update the content in the SearchResultsViewController. searchController.searchResultsUpdater = searchResultsTableController // If we are using this same view controller to present the results // dimming or obscuring it out wouldn't make sense. Should probably only set // this to yes if using another controller to display the search results. searchController.obscuresBackgroundDuringPresentation = false searchController.searchBar.sizeToFit() searchController.searchBar.enablesReturnKeyAutomatically = false self.navigationItem.searchController = searchController //set search controller bar into the navigation bar self.navigationItem.hidesSearchBarWhenScrolling = false //allow users to see the search bar even when scrolling // Sets this view controller as presenting view controller for the search interface definesPresentationContext = true //displays the search bar in the view controller properly searchController.searchBar.placeholder = "Search anime by name" } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "showAnimeDetails" { let vc = segue.destination as! AnimeDetailsViewController vc.animeItem = (sender as! AnimeFromTop) } } } ``` Lastly, here is the code for SearchResultsViewController.swift ``` import UIKit import AlamofireImage class SearchResultsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating { @IBOutlet weak var tableView: UITableView! var searchResults: SearchResults? //property to store the array of dictionaries for animes that the search query returns //Whenever user types in the search bar, thiss function is called to update the Search Results override func viewDidLoad() { super.viewDidLoad() print("called") } func updateSearchResults(for searchController: UISearchController) { if let inputText = searchController.searchBar.text, !inputText.isEmpty { getSearchResults(searchQuery: inputText) //call // filteredResults = searchResults } tableView.reloadData() } func getSearchResults(searchQuery: String) { let urlString = "https://api.jikan.moe/v3/search/anime?q=\(searchQuery)" //url String //Create a url object from the url String. Use guard so that if cannot be created as an url object, then provide optional error message. Created as an optional // print(urlString) guard let url = URL(string: urlString) else { //if not able to create a url from urlString, just return print("Not able to create url object from url String") return } //Create a Data Task, which is how you perform actual API calls and networking tasks //the completionHandler returns 3 optional parameters, but we only care about the Data and Error so we will do _ for discardable for the 2nd parameter URLResponse print(url) let task = URLSession.shared.dataTask(with: url, completionHandler: { [self] data, _, error in guard let data = data, error == nil else { return } //do - catch function because the decoder function can actually throw an error so we want to account for that too var results: SearchResults? do { results = try JSONDecoder().decode(SearchResults.self, from: data) } catch { print("Failed to Decode Error") } guard let final = results else { return } //final is the search query results array // print(final.results) searchResults = final }) task.resume() //starts the API call } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return searchResults?.results.count ?? 0 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "SearchCell") as! SearchCell guard let filteredResults = searchResults else { return cell } let anime = filteredResults.results[indexPath.row] let title = anime.title let animeId = anime.mal_id cell.searchAnimeTitle.text = title let imgUrlString = anime.image_url //image url in string let imgURL = URL(string: imgUrlString)! cell.searchImage.af.setImage(withURL: imgURL) let item: AnimelistItem! = AnimelistItem( mal_id: animeId, image_url: imgUrlString, title: title, synopsis: anime.synopsis, episodes: anime.episodes ?? 0 ) cell.item = item cell.viewController = self return cell } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "showAnimeDetails" { let vc = segue.destination as! AnimeDetailsViewController vc.animeItem = (sender as! AnimeFromTop) } } } ``` In my main storyboard, I have both the search results view controller and the discover scene view controller both connected via segue to the anime view details view controller (both set at present modally ). Again, I'm trying to be able to have the app allow me to view an anime's info when clicked on after finding it via search results the same way it works when I click on an anime from the discover tab. All help will be appreciated.