菜鸟教程小白 发表于 2022-12-11 19:27:02

ios - 将保存的上下文从 AppDelegate 加载到另一个 ViewController


                                            <p><p>我正在尝试使我的 Viewcontroller 中的数组等于我的核心数据保存的对象。我正在使用核心数据并创建了一个名为 Pokemon 的实体,它具有 3 个属性 <strong><em>name</em></strong>、<strong><em>id</em></strong> 和 <strong>><em>一代</em></strong>。在应用程序委托(delegate)中,我使用以下函数从 <a href="https://pokeapi.co/api/v2/pokemon/" rel="noreferrer noopener nofollow">API</a> 获取 Pokemon .这就是我解析数据并保存上下文的方法:</p>

<pre><code> typealias DownloadCompleted = () -&gt; ()
var pokemonId: Int16 = 0

func fetchPokemon(url: String, completed: @escaping DownloadCompleted) {
    let context = coreData.persistentContainer.viewContext

    let url = URLRequest(url: URL(string: url)!)

    let task = URLSession.shared.dataTask(with: url) { (data, repsonse, error) in
      if error != nil {
            print(error!)
      }

      do {

            let jsonResult = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSDictionary
            let jsonArray = jsonResult.value(forKey: &#34;results&#34;) as! []
            for pokemonData in jsonArray {
                self.pokemonId += 1

                if self.pokemonId &gt; 721 {

                  self.coreData.saveContext()
                  return
                }

                guard let name = pokemonData[&#34;name&#34;] as? String else {
                  return
                }

                let pokemon = Pokemon(context: context)
                pokemon.name = name
                pokemon.id = self.pokemonId
                print(&#34;Name: \(pokemon.name) Id:\(self.pokemonId)&#34;)

                if self.pokemonId &lt;= 151 {
                  pokemon.generation = 1
                } else if self.pokemonId &lt;= 251 {
                  pokemon.generation = 2
                }else if self.pokemonId &lt;= 386 {
                  pokemon.generation = 3
                } else if self.pokemonId &lt;= 493 {
                  pokemon.generation = 4
                } else if self.pokemonId &lt;= 649 {
                  pokemon.generation = 5
                } else if self.pokemonId &lt;= 721 {
                  pokemon.generation = 6
                }

            }



            guard let nextURL = jsonResult.value(forKey: &#34;next&#34;) as? String else {
                self.coreData.saveContext()
                return
            }

            DispatchQueue.main.async {
                self.fetchPokemon(url: nextURL, completed: {
                  self.coreData.saveContext()
                })
                completed()
            }

      } catch let err {
            print(err.localizedDescription)
      }



    }
    task.resume()

}
</code></pre>

<p>这就是我在 appDelegate 中的称呼。真的不知道在 fetchPokemon 中间要做什么或如何在另一个 ViewController 中调用它。所以我把它留空,不确定这是否与我遇到的问题有关。</p>

<pre><code>func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: ?) -&gt; Bool {

    let context = self.coreData.persistentContainer.viewContext
    let pokemonListVC = self.window?.rootViewController as! PokemonListVC
    pokemonListVC.context = context
    fetchPokemon(url: pokemonAPI) {

    }
    return true
}
</code></pre>

<p>我正在使用应用商店中的这个 SQL-Light 只读应用。我检查了数据,所有 721 只宠物小 Sprite 都在保存。现在,我不知道如何使 ViewController 中的数组等于保存的所有 721 个 Pokemon。我将此代码添加到我的 viewController 中。</p>

<pre><code>class PokemonListVC: UIViewController {

weak var context: NSManagedObjectContext! {
      didSet {
      return pokemon = Pokemon(context: context)
      }
}
var pokemon: Pokemon? = nil
lazy var pokemons = ()
override func viewDidLoad() {
      super.viewDidLoad()
      loadData()
}

func loadData() {
    pokemons = pokemon!.loadPokemon(generation: 1, context: context)
}
}
</code></pre>

<p>我创建了我的口袋妖怪实体的扩展,并添加了一个函数 loadPokemon,它按代过滤口袋妖怪。这是代码。</p>

<pre><code>extension Pokemon {

func loadPokemon(generation: Int16 = 0, context: NSManagedObjectContext) -&gt; {
    let request: NSFetchRequest&lt;Pokemon&gt; = Pokemon.fetchRequest()
      request.predicate = NSPredicate(format: &#34;generation = %@&#34;, generation)
      request.sortDescriptors =
      do {
            let pokemons = try context.fetch(request)
            print(&#34;My Pokemon count: \(pokemons.count)&#34;)
            return pokemons
      } catch let err {
            print(err.localizedDescription)
      }
    return []
}

}
</code></pre>

<p>当我在 ViewController 中调用 loadData 时,它会崩溃。数组计数为 0,英雄扩展中的数组计数也是 0。所以我不怎么让我的数组等于从 coreData 保存的 Pokemon。</p>

<p>非常感谢提供的任何帮助。 :)</p>

<p>这是我的 deleteRecords 代码,它也在我的 appDelegate 中。这会在应用启动时删除所有记录。我在 fetchPokemons 之前的 didFinishLaunchingWithOption 函数的最开头调用了这个方法。</p>

<pre><code>func deleteRecords() {
    let context = coreData.persistentContainer.viewContext
    let pokemonRequest: NSFetchRequest&lt;Pokemon&gt; = Pokemon.fetchRequest()

    var deleteRequest: NSBatchDeleteRequest
    var deleteResults: NSPersistentStoreResult

    do {
      deleteRequest = NSBatchDeleteRequest(fetchRequest: pokemonRequest as! NSFetchRequest&lt;NSFetchRequestResult&gt;)
      deleteResults = try context.execute(deleteRequest)
    } catch let err {
      print(err.localizedDescription)
    }

}
</code></pre></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>正如您所说,您确定所有 pockemon 记录都正确存储在您的 coredata 中,您可以通过提供 fetch 请求从您的 codedata 中简单地获取记录。我已经为联系人存储创建了演示,我可以通过此获取请求获取所有联系人,您可以在要获取所有记录的 ViewController 中尝试此代码。 </p>

<pre><code> let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let managedContext = appDelegate.persistentContainer.viewContext
    let fetchRequest = NSFetchRequest&lt;NSManagedObject&gt; (entityName: &#34;Pokemon&#34;)

    do {
      arrPockemon = try managedContext.fetch(fetchRequest)

    }catch let error as NSError {
      showAlert(string: error.localizedDescription)
    }
</code></pre>

<p>首先尝试获取所有记录,如果获得所有记录,则继续过滤扩展名和所有记录。希望它会帮助你。你可以从这里学习<a href="https://code.tutsplus.com/tutorials/core-data-and-swift-core-data-stack--cms-25065" rel="noreferrer noopener nofollow">https://code.tutsplus.com/tutorials/core-data-and-swift-core-data-stack--cms-25065</a> </p>

<p>在 userDefault 上保存标志。</p>

<pre><code> //check for first time when app is installed first time(first time flag is not present so)
    let userDefault = UserDefaults.standard.dictionaryRepresentation()
    if userDefault.keys.contains(&#34;isDataAvailable&#34;) {
      //key is availebe so check it
      if userDefault[&#34;isDataAvailable&#34;] as! String == &#34;1&#34;{
            //no need to call server for data
      }else{
            //fetch data from server
            // once you get data from server make isDataAvailable flage as 1
            UserDefaults.standard.setValue(&#34;1&#34;, forKey: &#34;isDataAvailable&#34;)
            UserDefaults.standard.synchronize()
      }
    }
    else{
      //flag is not avalable so call server for data
      // once you get data from server make isDataAvailable flage as 1
      UserDefaults.standard.setValue(&#34;1&#34;, forKey: &#34;isDataAvailable&#34;)
      UserDefaults.standard.synchronize()
    }
</code></pre></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 将保存的上下文从 AppDelegate 加载到另一个 ViewController,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/43290506/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/43290506/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 将保存的上下文从 AppDelegate 加载到另一个 ViewController