Получить значение из объектов массива с помощью AlamofireObjectMapper/ObjectMapper (быстро — iOS)

Я новичок в этом картостроении и слишком запутался. У меня есть запрос API, учитывая заголовок, API возвращает это:

{
Response = True;
Search =     (
            {
        Poster = "https://images-na.ssl-images-amazon.com/images/M/MV5BMjAxODQ2MzkyMV5BMl5BanBnXkFtZTgwNjU3MTE5OTE@._V1_SX300.jpg";
        Title = ARQ;
        Type = movie;
        Year = 2016;
        imdbID = tt5640450;
    },
            {
        Poster = "N/A";
        Title = Arq;
        Type = movie;
        Year = 2011;
        imdbID = tt2141601;
    },
            {
        Poster = "N/A";
        Title = "A.R.Q.";
        Type = movie;
        Year = 2015;
        imdbID = tt3829612;
    }
);
totalResults = 3;

}

Поэтому я создал отображаемый класс для этого результата:

class SearchResponse: Mappable {
    var isSuccess  : String?
    var searchArray: [Movie]?
    var searchCount: String?

    required init?(map: Map) {
    }

    func mapping(map: Map) {
        isSuccess   <- map["Response"]
        searchArray <- map["Search"]
        searchCount <- map["totalResults"]
    }
}

class Movie: Mappable {

    var posterURL  : String?
    var title      : String?
    var runtime    : String?
    var director   : String?
    var actors     : String?
    var genre      : String?
    var plot       : String?
    var production : String?
    var year       : String?
    var imdbID     : String?
    var imdbRating : String?

    required init?(map: Map) {

    }

    func mapping(map: Map) {
        posterURL  <- map["Poster"]
        title      <- map["Title"]
        runtime    <- map["Runtime"]
        director   <- map["Director"]
        actors     <- map["Actors"]
        genre      <- map["Genre"]
        plot       <- map["Plot"]
        production <- map["Production"]
        year       <- map["Year"]
        imdbID     <- map["imdbID"]
        imdbRating <- map["imdbRating"]
    }
}

Вопрос: Я сопоставил этот класс фильмов вот так, но для поиска по названию у меня будет только 4 таких атрибута. Но для следующего поиска мне понадобятся все они. Это правильно? Или мне следует создать два отдельных класса для обработки каждого типа ответов?

В порядке! Я показываю результат этого поиска в моем SearchTableViewController. Теперь я хочу показать более подробную информацию об этом фильме (любом фильме из массива «Поиск» в этом предыдущем ответе). Для этого API предлагает другой тип поиска — поиск по imdbID. Итак, я создал переход в моем SearchTableViewController, чтобы получить этот идентификатор и перейти к моему MovieViewController (представление, которое покажет эти данные):

let searchSegue = "segueFromSearch"

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let searchIndex = tableView.indexPathForSelectedRow?.row
    let movie = movies?[searchIndex!]
    let selectedImdbID = movie?.imdbID

    print("|Table View Controler| Segue. IMDB_ID: \(String(describing: selectedImdbID))")

    if segue.identifier == searchSegue {
        if let destination = segue.destination as? MovieViewController {

            destination.imdbID = selectedImdbID!

            print("|Table View Controler| Inside of if let. Debug print: I get til here. imdbID = \(selectedImdbID!)")
        }

    }
}

Моя функция для этого запроса API:

//The movieSearched variable is the text typed on my searchBar
let URL = "https://www.omdbapi.com/?s=\(movieSearched)&type=movie"
    Alamofire.request(URL).responseObject{ (response: DataResponse<SearchResponse>) in
        print("response is: \(response)")

        switch response.result {
        case .success(let value):
            let searchResponse = value
            self.movies = (searchResponse.searchArray)
            self.searchTableView.reloadData()


        case .failure(let error):
            let alert = UIAlertController(title: "Error", message: "Error 4xx / 5xx: \(error)", preferredStyle: UIAlertControllerStyle.alert)
            alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
            self.present(alert, animated: true, completion: nil)
        }

    }

Хорошо, учитывая этот обзор того, что у меня есть, давайте поговорим о моей проблеме...

Когда я ищу по идентификатору, ответ Json таков:

{
    Actors = "Robbie Amell, Rachael Taylor, Shaun Benson, Gray Powell";
    Awards = "N/A";
    BoxOffice = "N/A";
    Country = "USA, Canada";
    DVD = "16 Sep 2016";
    Director = "Tony Elliott";
    Genre = "Sci-Fi, Thriller";
    Language = English;
    Metascore = "N/A";
    Plot = "Trapped in a lab and stuck in a time loop, a disoriented couple fends off masked raiders while harboring a new energy source that could save humanity.";
    Poster = "https://images-na.ssl-images-amazon.com/images/M/MV5BMjAxODQ2MzkyMV5BMl5BanBnXkFtZTgwNjU3MTE5OTE@._V1_SX300.jpg";
    Production = Netflix;
    Rated = "N/A";
    Ratings =     (
        {
            Source = "Internet Movie Database";
            Value = "6.4/10";
        },
        {
            Source = "Rotten Tomatoes";
            Value = "60%";
        }
    );
    Released = "16 Sep 2016";
    Response = True;
    Runtime = "88 min";
    Title = ARQ;
    Type = movie;
    Website = "N/A";
    Writer = "Tony Elliott";
    Year = 2016;
    imdbID = tt5640450;
    imdbRating = "6.4";
    imdbVotes = "17,481";
}

Моя проблема

Я сделал этот запрос alamofire для поиска по ID:

func getMovieById() {

    let URL = "https://www.omdbapi.com/?i=\(String(describing: imdbID!)))"

    Alamofire.request(URL).responseObject{ (response: DataResponse<SearchResponse>) in
        print("|MovieController| Response is: \(response)")

        let Result = response.result.value
        print("Result for search by id: \(String(describing: Result!.searchArray))")

        // Have to get the values here, right?

    }
}

Очевидно, я не получаю данные, которые мне нужны здесь. Так...

Вопросы:

  1. Как я могу получить значения Json["Search"] с отображаемыми классами?
  2. Должен ли я изменить классы, которые у меня есть? Если да, то как и почему?

Я слишком смущен таким количеством слоев. Кроме того, я новичок в Swift и впервые использую этот ObjectMapper. Извините за столько кода здесь, но я думаю, что мне нужно было объяснить свой сценарий.


person U23r    schedule 28.04.2017    source источник
comment
Вместо Alamofire.request(URL).responseObject используйте Alamofire.request(URL).responseJSON.   -  person onnoweb    schedule 29.04.2017


Ответы (1)


Вы должны сопоставить каждое свойство с правильным типом данных этого свойства. Один из объектов в вашем ответе содержит логическое значение (например, "Response"), но вы объявляете его как строку. Мы должны точно соответствовать типу данных свойства, иначе объект будет нулевым и не будет сопоставлен.

Также ответ search by id не соответствует вашему классу картографа.

let Result = response.result.value неправильно. response.result.value даст вам SearchResponse объект.

Итог

Вы должны сначала получить правильную часть отображения. Любые несоответствующие типы не будут сопоставлены. Использование объекта ответа даст вам весь объект со всеми сопоставлениями вместо JSON, очевидно. Так и должно быть: let movie = response.result.value. Затем вы получаете доступ к свойствам фильма, например, для ex. movie.actors

person badhanganesh    schedule 28.04.2017
comment
Поиск по заголовку работает нормально и возвращает именно то, что я хочу. Моя проблема в том, как я могу выполнить этот запрос, используя идентификатор, чтобы получить массив словарей, используя responseObject. Если я использую responseJSON, я получаю то, что хочу: Alamofire.request(URL).responseJSON { response in if let json = response.result.value { let movieJSON = json as? [String : AnyObject] print(movieJSON! as Any) } } Но как это сделать с помощью responseObject? - person U23r; 29.04.2017
comment
Вы должны сначала получить правильную часть отображения. Любые несоответствующие типы не будут сопоставлены. Использование объекта ответа даст вам весь объект со всеми сопоставлениями вместо JSON, очевидно. Так и должно быть: let movie = response.result.value. Затем вы получаете доступ к свойствам фильма, например, например. movie.actors - person badhanganesh; 29.04.2017