use backgroundContext to fetch viewer
This commit is contained in:
@ -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 {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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")))
|
||||
}
|
||||
|
||||
@ -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))
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user