Skip to content

Instantly share code, notes, and snippets.

@thijsnado
Created January 3, 2020 14:57
Show Gist options
  • Save thijsnado/a84673e84409064efaec0069cba1cc7f to your computer and use it in GitHub Desktop.
Save thijsnado/a84673e84409064efaec0069cba1cc7f to your computer and use it in GitHub Desktop.
An example of how to easily use previews with SwiftUI views that query core data.
#if DEBUG
import CoreData
import SwiftUI
/// A protocol for allowing easy use of CoreData
/// with preview provider.
///
/// NOTE: you must still
/// make preview comply with PreviewProvider:
/// ```
/// struct OurPreview: CoreDataPreviewProvider, PreviewProvider {
/// static var body: some View {
/// // your view code
/// }
///
/// static func setupDb(_ context: NSManagedObjectContext) {
/// // setup db
/// }
/// }
/// ```
///
/// This helper is also unnecessary if you are passing in core data objects manually
/// instead of trying to query them using a fetched results controller.
protocol CoreDataPreviewProvider {
associatedtype Body: View
/// CoreDataPreviewProvider calls body to generate
/// previews method and automatically attach core data context to
/// environment
static var body: Body { get }
/// A clean contextObject will be sent to setupDB and can be
/// used to seed records for sake of previewing
///
/// Example usage:
/// ```
/// func setupDb(_ context: NSManagedObjectContext) {
/// let user = User(context: Context)
/// user.name = "Joe"
///
/// try! context.save()
/// }
///
static func setupDb(_ context: NSManagedObjectContext)
}
extension CoreDataPreviewProvider {
/// Don't override this method. Instead set body static method and
/// it will be called and setup with core data.
static var previews: some View {
let context = buildContextWithSetupData()
return body.environment(\.managedObjectContext, context)
}
private static func buildContextWithSetupData() -> NSManagedObjectContext {
let context = cleanPreviewContext()
setupDb(context)
return context
}
/// Iterates over all entities and destroys records, as well as resetting context and returning it
private static func cleanPreviewContext() -> NSManagedObjectContext {
let container = (UIApplication.shared.delegate as! AppDelegate).persistentContainer
let context = container.viewContext
context.reset()
try! container.managedObjectModel.entities.forEach { entity in
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entity.name!)
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
context.reset()
try context.execute(deleteRequest)
}
return context
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment