Итак, я немного больше тренируюсь с основными данными после окончания курса. Так что я все еще немного новичок в этом. Итак, у меня есть 3 сущности с именами Pokemon, Type & Ability. Таким образом, у покемона может быть много типов, таких как огонь, вода, полет и так далее. Тип также может иметь несколько покемонов, которые являются огонь, вода, полет и так далее. То же самое касается Способности, поэтому я установил отношения многие ко многим. Вот как это выглядит.
Я анализирую некоторые JSON формы API и пытаюсь сохранить их в основных данных. Теперь вот где у меня немного проблем. Вот так выглядит мой код, и он в основном анализирует JSON.
struct Service {
static let shared = Service()
func downloadPokemonsFromServer(completion: @escaping ()->()) {
let urlString = "https://pokeapi.co/api/v2/pokemon?limit=9"
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, error) in
if let err = error {
print("Unable to fetch pokemon", err)
}
guard let data = data else { return }
let privateContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
privateContext.parent = CoreDataManager.shared.persistentContainer.viewContext
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let pokemonJSON = try decoder.decode(PokemonsJSON.self, from: data)
pokemonJSON.pokemons.forEach { (JSONPokemon) in
let pokemon = Pokemon(context: privateContext)
pokemon.name = JSONPokemon.name
pokemon.url = JSONPokemon.detailUrl
//Would want to set pokemon types here but
//When i call fetchMoreDetails(pokemon:,urlString:,completion:)
//The pokemon is always nil inside fetchMoreDetails
}
try privateContext.save()
try privateContext.parent?.save()
completion()
} catch let err {
print("Unable to decode PokemonJSON. Error: ",err)
completion()
}
}.resume()
}
func fetchMoreDetails(pokemon: Pokemon, urlString: String, completion: @escaping ()->()) {
guard let url = URL(string: urlString) else { return }
let privateContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
privateContext.parent = CoreDataManager.shared.persistentContainer.viewContext
URLSession.shared.dataTask(with: url) { (data, response, error) in
if let err = error {
print("Unable to get more details for pokemon", err)
}
guard let data = data else { return }
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let pokemonDetailJSON = try decoder.decode(PokemonDetailJSON.self, from: data)
pokemonDetailJSON.types.forEach { (nestedType) in
let type = Type(context: privateContext)
type.name = nestedType.type.name
//How do I add type to pokemon.types this does work
//pokemon.types?.adding(type)
}
try privateContext.save()
try privateContext.parent?.save()
completion()
} catch let err {
print("Unable to decode pokemon more details", err)
completion()
}
}.resume()
}
}
Я могу разобрать все нормально и все, но я просто не могу добавить новый тип в pokemons.types , Я смотрел на переполнение стека, но большинство решений, кажется, в Objective C.
Вот так выглядит мой ViewController, и я также использую NSFetchResultController.
class PokemonTableVC: UITableViewController {
lazy var pokemonController: NSFetchedResultsController<Pokemon> = {
let context = CoreDataManager.shared.persistentContainer.viewContext
let request: NSFetchRequest<Pokemon> = Pokemon.fetchRequest()
let nameSort = NSSortDescriptor(key: "name", ascending: true)
request.sortDescriptors = [nameSort]
let controller = NSFetchedResultsController(fetchRequest: request, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
controller.delegate = self
return controller
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
tableView.refreshControl = refreshControl
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Delete", style: .done, target: self, action: #selector(handleDelete))
try? pokemonController.performFetch()
}
@objc func handleDelete() {
print("Deleting")
let context = CoreDataManager.shared.persistentContainer.viewContext
guard let pokemons = pokemonController.fetchedObjects else { return }
pokemons.forEach { (pokemon) in
context.delete(pokemon)
}
do {
try context.save()
} catch let err {
print("Unable to save data", err)
}
}
@objc func handleRefresh() {
print("DDDDD")
Service.shared.downloadPokemonsFromServer {
self.pokemonController.fetchedObjects?.forEach({ (pokemon) in
print(pokemon.name)
Service.shared.fetchMoreDetails(pokemon: pokemon, urlString: pokemon.url ?? "") {
print(pokemon.abilities?.count)
}
})
}
tableView.refreshControl?.endRefreshing()
}
}
Я могу предоставить другие свои структуры, если это необходимо. Но в основном я пытаюсь добавить тип в pokemon.types также хотел бы добавить fetchMoreDetails, когда я получаю покемонов, где я размещаю комментарий. Буду очень признателен за любые отзывы.