use backgroundContext to fetch viewer

This commit is contained in:
Satindar Dhillon
2022-04-21 20:27:10 -07:00
parent c310aa38fd
commit 80e5fb9a52
9 changed files with 97 additions and 53 deletions

View File

@ -51,7 +51,15 @@ enum PDFProvider {
return currentViewer
}
return try? await dataService.fetchViewer()
guard let viewerObjectID = try? await dataService.fetchViewer() else { return nil }
var result: Viewer?
await dataService.viewContext.perform {
result = dataService.viewContext.object(with: viewerObjectID) as? Viewer
}
return result
}()
if let viewer = viewer {

View File

@ -16,9 +16,11 @@ final class NewsletterEmailsViewModel: ObservableObject {
dataService.newsletterEmailsPublisher().sink(
receiveCompletion: { _ in },
receiveValue: { [weak self] result in
receiveValue: { [weak self] objectIDs in
self?.isLoading = false
self?.emails = result
dataService.viewContext.perform {
self?.emails = objectIDs.compactMap { dataService.viewContext.object(with: $0) as? NewsletterEmail }
}
self?.hasLoadedInitialEmails = true
}
)
@ -32,9 +34,13 @@ final class NewsletterEmailsViewModel: ObservableObject {
receiveCompletion: { [weak self] _ in
self?.isLoading = false
},
receiveValue: { [weak self] result in
receiveValue: { [weak self] objectID in
self?.isLoading = false
self?.emails.insert(result, at: 0)
dataService.viewContext.perform {
if let item = dataService.viewContext.object(with: objectID) as? NewsletterEmail {
self?.emails.insert(item, at: 0)
}
}
}
)
.store(in: &subscriptions)

View File

@ -18,8 +18,21 @@ import Views
}
func loadProfileData(dataService: DataService) async {
guard let viewer = try? await dataService.fetchViewer() else { return }
if let currentViewer = dataService.currentViewer {
loadProfileCardData(viewer: currentViewer)
return
}
guard let viewerObjectID = try? await dataService.fetchViewer() else { return }
await dataService.viewContext.perform {
if let viewer = dataService.viewContext.object(with: viewerObjectID) as? Viewer {
self.loadProfileCardData(viewer: viewer)
}
}
}
private func loadProfileCardData(viewer: Viewer) {
profileCardData = ProfileCardData(
name: viewer.unwrappedName,
username: viewer.unwrappedUsername,

View File

@ -64,9 +64,11 @@ public final class RootViewModel: ObservableObject {
return
}
if let username = try? await services.dataService.fetchViewer().username {
let path = linkRequestPath(username: username, requestID: linkRequestID)
webLinkPath = SafariWebLinkPath(id: UUID(), path: path)
if let viewerObjectID = try? await services.dataService.fetchViewer() {
if let viewer = services.dataService.viewContext.object(with: viewerObjectID) as? Viewer {
let path = linkRequestPath(username: viewer.unwrappedUsername, requestID: linkRequestID)
webLinkPath = SafariWebLinkPath(id: UUID(), path: path)
}
}
}

View File

@ -17,7 +17,7 @@ public final class DataService: ObservableObject {
let backgroundContext: NSManagedObjectContext
var subscriptions = Set<AnyCancellable>()
var viewContext: NSManagedObjectContext {
public var viewContext: NSManagedObjectContext {
persistentContainer.viewContext
}

View File

@ -5,7 +5,7 @@ import Models
import SwiftGraphQL
public extension DataService {
func createNewsletterEmailPublisher() -> AnyPublisher<NewsletterEmail, BasicError> {
func createNewsletterEmailPublisher() -> AnyPublisher<NSManagedObjectID, BasicError> {
enum MutationResult {
case saved(newsletterEmail: InternalNewsletterEmail)
case error(errorCode: Enums.CreateNewsletterEmailErrorCode)
@ -45,8 +45,8 @@ public extension DataService {
switch payload.data {
case let .saved(newsletterEmail: newsletterEmail):
if let newsletterEmailObject = newsletterEmail.persist(context: self.persistentContainer.viewContext) {
promise(.success(newsletterEmailObject))
if let newsletterEmailObjectID = newsletterEmail.persist(context: self.backgroundContext) {
promise(.success(newsletterEmailObjectID))
} else {
promise(.failure(.message(messageText: "coredata error")))
}

View File

@ -1,10 +1,11 @@
import Combine
import CoreData
import Foundation
import Models
import SwiftGraphQL
public extension DataService {
func newsletterEmailsPublisher() -> AnyPublisher<[NewsletterEmail], ServerError> {
func newsletterEmailsPublisher() -> AnyPublisher<[NSManagedObjectID], ServerError> {
enum QueryResult {
case success(result: [InternalNewsletterEmail])
case error(error: String)
@ -43,8 +44,8 @@ public extension DataService {
case let .success(payload):
switch payload.data {
case let .success(result: result):
if let newsletterEmailObject = result.persist(context: self.persistentContainer.viewContext) {
promise(.success(newsletterEmailObject))
if let newsletterEmailObjectIDs = result.persist(context: self.backgroundContext) {
promise(.success(newsletterEmailObjectIDs))
} else {
promise(.failure(.unknown))
}

View File

@ -6,7 +6,7 @@ import SwiftGraphQL
import Utils
public extension DataService {
func fetchViewer() async throws -> Viewer {
func fetchViewer() async throws -> NSManagedObjectID {
let selection = Selection<ViewerInternal, Objects.User> {
ViewerInternal(
userID: try $0.id(),
@ -36,8 +36,8 @@ public extension DataService {
DataService.registerIntercomUser?(payload.data.userID)
}
if let self = self, let viewer = payload.data.persist(context: self.persistentContainer.viewContext) {
continuation.resume(returning: viewer)
if let self = self, let viewerID = payload.data.persist(context: self.backgroundContext) {
continuation.resume(returning: viewerID)
} else {
continuation.resume(throwing: BasicError.message(messageText: "coredata error"))
}
@ -55,21 +55,26 @@ private struct ViewerInternal {
let name: String
let profileImageURL: String?
func persist(context: NSManagedObjectContext) -> Viewer? {
let viewer = Viewer(context: context)
viewer.userID = userID
viewer.username = username
viewer.name = name
viewer.profileImageURL = profileImageURL
func persist(context: NSManagedObjectContext) -> NSManagedObjectID? {
var objectID: NSManagedObjectID?
do {
try context.save()
logger.debug("Viewer saved succesfully")
return viewer
} catch {
context.rollback()
logger.debug("Failed to save Viewer: \(error.localizedDescription)")
return nil
context.performAndWait {
let viewer = Viewer(context: context)
viewer.userID = userID
viewer.username = username
viewer.name = name
viewer.profileImageURL = profileImageURL
do {
try context.save()
logger.debug("Viewer saved succesfully")
objectID = viewer.objectID
} catch {
context.rollback()
logger.debug("Failed to save Viewer: \(error.localizedDescription)")
}
}
return objectID
}
}

View File

@ -7,18 +7,23 @@ struct InternalNewsletterEmail {
let email: String
let confirmationCode: String?
func persist(context: NSManagedObjectContext) -> NewsletterEmail? {
let newsletterEmail = asManagedObject(inContext: context)
func persist(context: NSManagedObjectContext) -> NSManagedObjectID? {
var objectID: NSManagedObjectID?
do {
try context.save()
logger.debug("NewsletterEmail saved succesfully")
return newsletterEmail
} catch {
context.rollback()
logger.debug("Failed to save NewsletterEmail: \(error.localizedDescription)")
return nil
context.performAndWait {
let newsletterEmail = asManagedObject(inContext: context)
do {
try context.save()
logger.debug("NewsletterEmail saved succesfully")
objectID = newsletterEmail.objectID
} catch {
context.rollback()
logger.debug("Failed to save NewsletterEmail: \(error.localizedDescription)")
}
}
return objectID
}
func asManagedObject(inContext context: NSManagedObjectContext) -> NewsletterEmail {
@ -31,17 +36,21 @@ struct InternalNewsletterEmail {
}
extension Sequence where Element == InternalNewsletterEmail {
func persist(context: NSManagedObjectContext) -> [NewsletterEmail]? {
let newsletterEmails = map { $0.asManagedObject(inContext: context) }
func persist(context: NSManagedObjectContext) -> [NSManagedObjectID]? {
var result: [NSManagedObjectID]?
do {
try context.save()
logger.debug("NewsletterEmail saved succesfully")
return newsletterEmails
} catch {
context.rollback()
logger.debug("Failed to save NewsletterEmail: \(error.localizedDescription)")
return nil
context.performAndWait {
let newsletterEmails = map { $0.asManagedObject(inContext: context) }
do {
try context.save()
logger.debug("NewsletterEmail saved succesfully")
result = newsletterEmails.map(\.objectID)
} catch {
context.rollback()
logger.debug("Failed to save NewsletterEmail: \(error.localizedDescription)")
}
}
return result
}
}