mirror of
https://github.com/writeas/writefreely-swiftui-multiplatform.git
synced 2024-11-15 01:11:02 +00:00
Fix crash-on-load bug by cleaning up/thread-sanitizing CoreData calls
This commit is contained in:
parent
bd695b23e6
commit
e7408a47e9
@ -2,7 +2,6 @@ import SwiftUI
|
||||
|
||||
struct AccountLogoutView: View {
|
||||
@EnvironmentObject var model: WriteFreelyModel
|
||||
@Environment(\.managedObjectContext) var moc
|
||||
|
||||
@State private var isPresentingLogoutConfirmation: Bool = false
|
||||
@State private var editedPostsWarningString: String = ""
|
||||
|
@ -335,44 +335,53 @@ private extension WriteFreelyModel {
|
||||
DispatchQueue.main.async {
|
||||
self.isProcessingRequest = false
|
||||
}
|
||||
let request = WFAPost.createFetchRequest()
|
||||
do {
|
||||
var postsToDelete = posts.userPosts.filter { $0.status != PostStatus.local.rawValue }
|
||||
let fetchedPosts = try result.get()
|
||||
for fetchedPost in fetchedPosts {
|
||||
if let managedPost = posts.userPosts.first(where: { $0.postId == fetchedPost.postId }) {
|
||||
managedPost.wasDeletedFromServer = false
|
||||
if let fetchedPostUpdatedDate = fetchedPost.updatedDate,
|
||||
let localPostUpdatedDate = managedPost.updatedDate {
|
||||
managedPost.hasNewerRemoteCopy = fetchedPostUpdatedDate > localPostUpdatedDate
|
||||
let locallyCachedPosts = try LocalStorageManager.persistentContainer.viewContext.fetch(request)
|
||||
do {
|
||||
var postsToDelete = locallyCachedPosts.filter { $0.status != PostStatus.local.rawValue }
|
||||
let fetchedPosts = try result.get()
|
||||
for fetchedPost in fetchedPosts {
|
||||
if let managedPost = locallyCachedPosts.first(where: { $0.postId == fetchedPost.postId }) {
|
||||
DispatchQueue.main.async {
|
||||
managedPost.wasDeletedFromServer = false
|
||||
if let fetchedPostUpdatedDate = fetchedPost.updatedDate,
|
||||
let localPostUpdatedDate = managedPost.updatedDate {
|
||||
managedPost.hasNewerRemoteCopy = fetchedPostUpdatedDate > localPostUpdatedDate
|
||||
} else {
|
||||
print("Error: could not determine which copy of post is newer")
|
||||
}
|
||||
postsToDelete.removeAll(where: { $0.postId == fetchedPost.postId })
|
||||
}
|
||||
} else {
|
||||
print("Error: could not determine which copy of post is newer")
|
||||
DispatchQueue.main.async {
|
||||
let managedPost = WFAPost(context: LocalStorageManager.persistentContainer.viewContext)
|
||||
managedPost.postId = fetchedPost.postId
|
||||
managedPost.slug = fetchedPost.slug
|
||||
managedPost.appearance = fetchedPost.appearance
|
||||
managedPost.language = fetchedPost.language
|
||||
managedPost.rtl = fetchedPost.rtl ?? false
|
||||
managedPost.createdDate = fetchedPost.createdDate
|
||||
managedPost.updatedDate = fetchedPost.updatedDate
|
||||
managedPost.title = fetchedPost.title ?? ""
|
||||
managedPost.body = fetchedPost.body
|
||||
managedPost.collectionAlias = fetchedPost.collectionAlias
|
||||
managedPost.status = PostStatus.published.rawValue
|
||||
managedPost.wasDeletedFromServer = false
|
||||
}
|
||||
}
|
||||
postsToDelete.removeAll(where: { $0.postId == fetchedPost.postId })
|
||||
} else {
|
||||
let managedPost = WFAPost(context: LocalStorageManager.persistentContainer.viewContext)
|
||||
managedPost.postId = fetchedPost.postId
|
||||
managedPost.slug = fetchedPost.slug
|
||||
managedPost.appearance = fetchedPost.appearance
|
||||
managedPost.language = fetchedPost.language
|
||||
managedPost.rtl = fetchedPost.rtl ?? false
|
||||
managedPost.createdDate = fetchedPost.createdDate
|
||||
managedPost.updatedDate = fetchedPost.updatedDate
|
||||
managedPost.title = fetchedPost.title ?? ""
|
||||
managedPost.body = fetchedPost.body
|
||||
managedPost.collectionAlias = fetchedPost.collectionAlias
|
||||
managedPost.status = PostStatus.published.rawValue
|
||||
managedPost.wasDeletedFromServer = false
|
||||
}
|
||||
}
|
||||
for post in postsToDelete {
|
||||
post.wasDeletedFromServer = true
|
||||
}
|
||||
DispatchQueue.main.async {
|
||||
LocalStorageManager().saveContext()
|
||||
self.posts.loadCachedPosts()
|
||||
DispatchQueue.main.async {
|
||||
for post in postsToDelete {
|
||||
post.wasDeletedFromServer = true
|
||||
}
|
||||
LocalStorageManager().saveContext()
|
||||
}
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
} catch {
|
||||
print(error)
|
||||
print("Error: Failed to fetch cached posts")
|
||||
}
|
||||
}
|
||||
|
||||
@ -387,23 +396,37 @@ private extension WriteFreelyModel {
|
||||
// See: https://github.com/writeas/writefreely-swift/issues/20
|
||||
do {
|
||||
let fetchedPost = try result.get()
|
||||
let foundPostIndex = posts.userPosts.firstIndex(where: {
|
||||
$0.title == fetchedPost.title && $0.body == fetchedPost.body
|
||||
})
|
||||
guard let index = foundPostIndex else { return }
|
||||
let cachedPost = self.posts.userPosts[index]
|
||||
cachedPost.appearance = fetchedPost.appearance
|
||||
cachedPost.body = fetchedPost.body
|
||||
cachedPost.createdDate = fetchedPost.createdDate
|
||||
cachedPost.language = fetchedPost.language
|
||||
cachedPost.postId = fetchedPost.postId
|
||||
cachedPost.rtl = fetchedPost.rtl ?? false
|
||||
cachedPost.slug = fetchedPost.slug
|
||||
cachedPost.status = PostStatus.published.rawValue
|
||||
cachedPost.title = fetchedPost.title ?? ""
|
||||
cachedPost.updatedDate = fetchedPost.updatedDate
|
||||
DispatchQueue.main.async {
|
||||
LocalStorageManager().saveContext()
|
||||
let request = WFAPost.createFetchRequest()
|
||||
let matchBodyPredicate = NSPredicate(format: "body == %@", fetchedPost.body)
|
||||
if let fetchedPostTitle = fetchedPost.title {
|
||||
let matchTitlePredicate = NSPredicate(format: "title == %@", fetchedPostTitle)
|
||||
request.predicate = NSCompoundPredicate(
|
||||
andPredicateWithSubpredicates: [
|
||||
matchTitlePredicate,
|
||||
matchBodyPredicate
|
||||
]
|
||||
)
|
||||
} else {
|
||||
request.predicate = matchBodyPredicate
|
||||
}
|
||||
do {
|
||||
let cachedPostsResults = try LocalStorageManager.persistentContainer.viewContext.fetch(request)
|
||||
guard let cachedPost = cachedPostsResults.first else { return }
|
||||
cachedPost.appearance = fetchedPost.appearance
|
||||
cachedPost.body = fetchedPost.body
|
||||
cachedPost.createdDate = fetchedPost.createdDate
|
||||
cachedPost.language = fetchedPost.language
|
||||
cachedPost.postId = fetchedPost.postId
|
||||
cachedPost.rtl = fetchedPost.rtl ?? false
|
||||
cachedPost.slug = fetchedPost.slug
|
||||
cachedPost.status = PostStatus.published.rawValue
|
||||
cachedPost.title = fetchedPost.title ?? ""
|
||||
cachedPost.updatedDate = fetchedPost.updatedDate
|
||||
DispatchQueue.main.async {
|
||||
LocalStorageManager().saveContext()
|
||||
}
|
||||
} catch {
|
||||
print("Error: Failed to fetch cached posts")
|
||||
}
|
||||
} catch {
|
||||
print(error)
|
||||
@ -435,7 +458,6 @@ private extension WriteFreelyModel {
|
||||
cachedPost.hasNewerRemoteCopy = false
|
||||
DispatchQueue.main.async {
|
||||
LocalStorageManager().saveContext()
|
||||
self.posts.loadCachedPosts()
|
||||
}
|
||||
} catch {
|
||||
print(error)
|
||||
|
@ -2,7 +2,6 @@ import SwiftUI
|
||||
|
||||
struct CollectionListView: View {
|
||||
@EnvironmentObject var model: WriteFreelyModel
|
||||
@Environment(\.managedObjectContext) var moc
|
||||
|
||||
@FetchRequest(
|
||||
entity: WFACollection.entity(),
|
||||
|
@ -2,40 +2,18 @@ import SwiftUI
|
||||
import CoreData
|
||||
|
||||
class PostListModel: ObservableObject {
|
||||
@Published var userPosts = [WFAPost]()
|
||||
|
||||
init() {
|
||||
loadCachedPosts()
|
||||
}
|
||||
|
||||
func loadCachedPosts() {
|
||||
let request = WFAPost.createFetchRequest()
|
||||
let sort = NSSortDescriptor(key: "createdDate", ascending: false)
|
||||
request.sortDescriptors = [sort]
|
||||
|
||||
userPosts = []
|
||||
do {
|
||||
let cachedPosts = try LocalStorageManager.persistentContainer.viewContext.fetch(request)
|
||||
userPosts.append(contentsOf: cachedPosts)
|
||||
} catch {
|
||||
print("Error: Failed to fetch cached posts.")
|
||||
}
|
||||
}
|
||||
|
||||
func remove(_ post: WFAPost) {
|
||||
LocalStorageManager.persistentContainer.viewContext.delete(post)
|
||||
LocalStorageManager().saveContext()
|
||||
}
|
||||
|
||||
func purgePublishedPosts() {
|
||||
userPosts = []
|
||||
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "WFAPost")
|
||||
fetchRequest.predicate = NSPredicate(format: "status != %i", 0)
|
||||
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
|
||||
|
||||
do {
|
||||
try LocalStorageManager.persistentContainer.viewContext.executeAndMergeChanges(using: deleteRequest)
|
||||
loadCachedPosts()
|
||||
} catch {
|
||||
print("Error: Failed to purge cached posts.")
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import SwiftUI
|
||||
|
||||
struct PostListView: View {
|
||||
@EnvironmentObject var model: WriteFreelyModel
|
||||
@Environment(\.managedObjectContext) var moc
|
||||
@Environment(\.managedObjectContext) var managedObjectContext
|
||||
|
||||
@State var selectedCollection: WFACollection?
|
||||
@State var showAllPosts: Bool = false
|
||||
@ -103,7 +103,7 @@ struct PostListView: View {
|
||||
}
|
||||
|
||||
private func createNewLocalDraft() {
|
||||
let managedPost = WFAPost(context: LocalStorageManager.persistentContainer.viewContext)
|
||||
let managedPost = WFAPost(context: self.managedObjectContext)
|
||||
managedPost.createdDate = Date()
|
||||
managedPost.title = ""
|
||||
managedPost.body = ""
|
||||
|
@ -2,7 +2,6 @@ import SwiftUI
|
||||
|
||||
struct PostEditorView: View {
|
||||
@EnvironmentObject var model: WriteFreelyModel
|
||||
@Environment(\.managedObjectContext) var moc
|
||||
@Environment(\.horizontalSizeClass) var horizontalSizeClass
|
||||
@Environment(\.presentationMode) var presentationMode
|
||||
|
||||
@ -147,7 +146,6 @@ struct PostEditorView: View {
|
||||
&& post.postId == nil {
|
||||
DispatchQueue.main.async {
|
||||
model.posts.remove(post)
|
||||
model.posts.loadCachedPosts()
|
||||
}
|
||||
} else if post.status != PostStatus.published.rawValue {
|
||||
DispatchQueue.main.async {
|
||||
@ -160,7 +158,6 @@ struct PostEditorView: View {
|
||||
private func publishPost() {
|
||||
DispatchQueue.main.async {
|
||||
LocalStorageManager().saveContext()
|
||||
model.posts.loadCachedPosts()
|
||||
model.publish(post: post)
|
||||
}
|
||||
#if os(iOS)
|
||||
|
@ -49,7 +49,6 @@ struct PostEditorView: View {
|
||||
&& post.postId == nil {
|
||||
DispatchQueue.main.async {
|
||||
model.posts.remove(post)
|
||||
model.posts.loadCachedPosts()
|
||||
}
|
||||
} else if post.status != PostStatus.published.rawValue {
|
||||
DispatchQueue.main.async {
|
||||
@ -62,7 +61,6 @@ struct PostEditorView: View {
|
||||
private func publishPost() {
|
||||
DispatchQueue.main.async {
|
||||
LocalStorageManager().saveContext()
|
||||
model.posts.loadCachedPosts()
|
||||
model.publish(post: post)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user