#ios #swift #function #core-data #swiftui
Вопрос:
Я хочу отделить свои функции от представлений SwiftUI. У меня есть эта функция:
import Foundation
import CoreData
func deleteAll() {
let fetchRequestItems: NSFetchRequest<NSFetchRequestResult> = Item.fetchRequest()
let deleteRequestItems = NSBatchDeleteRequest(fetchRequest: fetchRequestItems)
do {
try viewContext.save()
try viewContext.execute(deleteRequestItems)
viewContext.reset()
} catch let error as NSError {
print(error)
}
}
Я получаю ошибку в 3 строках с viewContext:
Не удается найти «viewContext» в области видимости
Та же функция работает, когда она находится внутри представления SwiftUI. Но в представлениях есть viewContext, введенный таким образом:
ContentView()
.environment(.managedObjectContext, persistenceController.container.viewContext)
Итак, вопрос в том,:
Как внедрить/использовать контекст основных данных (viewContext) внутри функций в отдельных файлах Swift?
РЕДАКТИРОВАТЬ: Persistence.swift взят из шаблона SwiftUI 2.0 и выглядит так:
import CoreData
struct PersistenceController {
static let shared = PersistenceController()
static var preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
for _ in 0..<10 {
let newItem = Item(context: viewContext)
newItem.timestamp = Date()
}
do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error (nsError), (nsError.userInfo)")
}
return result
}()
let container: NSPersistentCloudKitContainer
init(inMemory: Bool = false) {
container = NSPersistentCloudKitContainer(name: "Moneto")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error (error), (error.userInfo)")
}
})
}
}
Комментарии:
1.
deleteAll(context: NSManagedObjectContext) { … }
2. Это работает! Спасибо, @JoakimDanielson 🙂 Не могли бы вы отправить его в качестве ответа, пожалуйста, чтобы я мог его принять? 2 небольших комментария. 1. Это
deleteAll(viewContext: NSManagedObjectContext) { … }
в моем случае. 2. Когда я запускаю функцию, я должен использоватьdeleteAll(viewContext: viewContext)
Ответ №1:
Вы должны внедрить управляемый контекст в свою функцию
func deleteAll(viewContext: NSManagedObjectContext) {
//…
}
Это также дает вам преимущество в том, что вы можете выбрать, из какого контекста удалять, если вы работаете с фоновым или дочерним контекстами
Ответ №2:
Добавьте этот параметр в свое представление
@Environment(.managedObjectContext) var viewContext
Комментарии:
1. Спасибо, но у меня есть это на примете. Если быть точным, у меня есть:
@Environment(.managedObjectContext) private var viewContext
. Но даже безprivate
этого ничего не получается. Пожалуйста, обратите внимание, что моя функция находится в отдельном файле. Не в представлении СвифтУИ. Это быстрый файл с одной только функцией.2. Нет, это нехорошо. пожалуйста, переместите свою функцию в свой вид или модель представления.
3. Значит, я не могу хранить их в отдельных файлах? Как правильно разбить представление на более мелкие части, если у вас там много функций?
4. используйте расширение. создайте расширение своего представления как
extension ContentView {...}
и добавьте это расширение в отдельный файл. Глобальная функция — не очень хорошая идея.5. Вы также можете сделать контекст представления статичным из файла Persistence.swift, а затем использовать его везде .