сохранение ответа API на CoreData, по-прежнему показывает ноль при доступе

#ios #swift #core-data

#iOS #swift #core-data

Вопрос:

   func getGenreKeys(complition: @escaping (_ genre : GenreListModel?) -> ())
    {
        let genreUrl = URL(string: "(baseUrl)(genreListUrl)(apiKey)")!
        
        urlSessionManager(url: genreUrl,toUseDataType: GenreListModel.self) { json in
            
            //json will contain genreList Object , which can be used to get keys
            switch json
            {
            case .success(let genreListData) :
                complition(genreListData)
                CoreData.shared.saveGenreList(json: genreListData)
            case .failure(let error) :
                print(error)
            }
        }
        
    }
 

это приведенный выше код завершения api

   func saveGenreList(json: GenreListModel){
        let context = persistentContainer.viewContext
        let genreList = GenreList(context: context)
        
        json.genres?.forEach({ Genres in
            genreList.name = Genres.name
            do{
                try context.save()
             
            }
            catch{
                print("error in saving")
            }
        })
    }
 

это то, что я сделал, чтобы сохранить данные после завершения выборки api.

    var coreGenre : GenreList?

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return coreGenre?.name?.count ?? 0
 
 

приведенный выше код является частью VC, которая требуется для получения coreGenre.name чтобы дать подсчет, но это ноль

но когда я пытаюсь получить доступ из ViewController , создав переменную класса сущности core data , она возвращает nill

Комментарии:

1. Выведите ошибку в блоке catch и проверьте журнал ошибок. print("error in saving", error)

2. GenreListModel как тип, так и экземпляр не имеют смысла. И в forEach цикле вы собираетесь перезаписать данные в (только один раз) созданном экземпляре объекта.

3. он печатает данные, поэтому я надеюсь, что проблем с сохранением нет. genreList.name при печати в разделе сохранить он печатает имя, но не сохраняет его в основной базе данных i guss.

4. @vadian, не могли бы вы кратко рассказать? часть завершения работает. GenreListModel — это просто имя для переноса данных после успешного завершения

5. Назовите переменные, функции, регистры перечислений с начальной строчной буквой и назовите типы, структуры, классы, перечисления с начальной прописной буквой, чтобы избежать путаницы.

Ответ №1:

Что не так?

Я буду основывать свой ответ на коде там. В вашей учетной записи GitHub, где вы поделились этим кодом.

Первая проблема:

У вас есть:

 var genrelist : GenreListModel? {
    didSet{
        //after getting data a table needs to reload and ui elements needs to be used in main thread only
        DispatchQueue.main.async {
            self.tableView.reloadData()
            
        }
    }
}

var coreGenre : [GenreList]?

override func viewWillAppear(_ animated: Bool) {
    ...
    ApiManager.shared.getGenreKeys { genre in
        self.genrelist = genre
    }
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return coreGenre?.count ?? 0
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    ...
    genrelist?.genres?[indexPath.row].id
    ...
    cell.genreLabel.text = genrelist?.genres?[indexPath.row].name
    ...
}
 

Первая проблема:
coreGenre НИКОГДА НЕ УСТАНАВЛИВАЕТСЯ! genreList установлен, но нет coreGenre . Так что не ожидайте, что это будет что-то еще, что nil !
Вы не написали coreGenre = something
So tableView(_:numberOfRowsInSection:) всегда будет возвращаться 0 .

Сделайте свой выбор. Либо genreList или coreGenre :

 ApiManager.shared.getGenreKeys { genreList in
        self.coreGenre = genreList.genres
}
 

amp;

 var coreGenre: [GenreList] {
    didSet { DispatchQueue.main.async { self.tableView.reloadData() } }
}
 

И удалите var genreList

Или удалите coreGenre .

Это должно исправить UITableView , и именно здесь ваш вопрос вводит в заблуждение: здесь нет CoreData. В completion of getGenreKeys() вы возвращаете значение. CoreData сохраняет значение в методе, но это все.

Это:

 API -> Parse Value -> Save in CoreData
                   -> Completion        -> Reload TableView to Display
 

Теперь в вашем стеке CoreData у вас есть метод saveGenreList(json:) . Предполагая, что это работает, вы сохраняете его, но никогда не извлекаете.

NSFetchRequest В вашем коде нет. Посмотрите, как выполнить выборку в CoreData.

Просто перестаньте думать CoreData , чтобы понять проблему:

 let retrieveValueFromAPI = "I got it"
let savedValue = retrieveValueFromAPI // (1)
return retrieveValueFromAPI
 

В (1) вы получите предупреждение о неиспользуемой переменной от Xcode. Это точно такая же проблема. Здесь это «значение ОЗУ» вместо значения диска, но это та же логика. Вы не используете то, что сохранили.

Вам нужно продолжить работу и отладку. И debug не только устраняет проблему. Есть несколько шагов:

  • Воспроизвести проблему
  • Найдите его источник / поймите, в чем может быть проблема
  • Устраните проблему

Поиск его происхождения и причины — это шаги, которые вы пропустили, либо из-за неправильного понимания, либо из-за недостаточного пошагового исследования в вашем коде.