Page Menu
Home
Musing Studio
Search
Configure Global Search
Log In
Files
F12338943
LocalStorageManager.swift
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
5 KB
Subscribers
None
LocalStorageManager.swift
View Options
import
CoreData
#if
os
(
iOS
)
import
UIKit
#elseif
os
(
macOS
)
import
AppKit
#endif
final
class
LocalStorageManager
{
private
let
logger
=
Logging
(
for
:
String
(
describing
:
LocalStorageManager
.
self
))
public
static
var
standard
=
LocalStorageManager
()
public
let
container
:
NSPersistentContainer
private
let
containerName
=
"LocalStorageModel"
private
init
()
{
container
=
NSPersistentContainer
(
name
:
containerName
)
setupStore
(
in
:
container
)
registerObservers
()
}
func
saveContext
()
{
if
container
.
viewContext
.
hasChanges
{
do
{
logger
.
log
(
"Saving context to local store started..."
)
try
container
.
viewContext
.
save
()
logger
.
log
(
"Context saved to local store."
)
}
catch
{
logger
.
logCrashAndSetFlag
(
error
:
LocalStoreError
.
couldNotSaveContext
)
}
}
}
func
purgeUserCollections
()
throws
{
let
fetchRequest
:
NSFetchRequest
<
NSFetchRequestResult
>
=
NSFetchRequest
(
entityName
:
"WFACollection"
)
let
deleteRequest
=
NSBatchDeleteRequest
(
fetchRequest
:
fetchRequest
)
do
{
logger
.
log
(
"Purging user collections from local store..."
)
try
container
.
viewContext
.
executeAndMergeChanges
(
using
:
deleteRequest
)
logger
.
log
(
"User collections purged from local store."
)
}
catch
{
logger
.
log
(
"
\(
LocalStoreError
.
couldNotPurgeCollections
.
localizedDescription
)
"
,
level
:
.
error
)
throw
LocalStoreError
.
couldNotPurgeCollections
}
}
}
private
extension
LocalStorageManager
{
var
oldStoreURL
:
URL
{
let
appSupport
=
FileManager
.
default
.
urls
(
for
:
.
applicationSupportDirectory
,
in
:
.
userDomainMask
).
first
!
return
appSupport
.
appendingPathComponent
(
"LocalStorageModel.sqlite"
)
}
var
sharedStoreURL
:
URL
{
let
id
=
"group.com.abunchtell.writefreely"
let
groupContainer
=
FileManager
.
default
.
containerURL
(
forSecurityApplicationGroupIdentifier
:
id
)
!
return
groupContainer
.
appendingPathComponent
(
"LocalStorageModel.sqlite"
)
}
func
setupStore
(
in
container
:
NSPersistentContainer
)
{
if
!
FileManager
.
default
.
fileExists
(
atPath
:
oldStoreURL
.
path
)
{
container
.
persistentStoreDescriptions
.
first
!.
url
=
sharedStoreURL
}
container
.
loadPersistentStores
{
_
,
error
in
self
.
logger
.
log
(
"Loading local store..."
)
if
let
error
=
error
{
self
.
logger
.
logCrashAndSetFlag
(
error
:
LocalStoreError
.
couldNotLoadStore
(
error
.
localizedDescription
))
}
self
.
logger
.
log
(
"Loaded local store."
)
}
migrateStore
(
for
:
container
)
container
.
viewContext
.
automaticallyMergesChangesFromParent
=
true
container
.
viewContext
.
mergePolicy
=
NSMergeByPropertyObjectTrumpMergePolicy
}
func
migrateStore
(
for
container
:
NSPersistentContainer
)
{
// Check if the shared store exists before attempting a migration — for example, in case we've already attempted
// and successfully completed a migration, but the deletion of the old store failed for some reason.
guard
!
FileManager
.
default
.
fileExists
(
atPath
:
sharedStoreURL
.
path
)
else
{
return
}
let
coordinator
=
container
.
persistentStoreCoordinator
// Get a reference to the old store.
guard
let
oldStore
=
coordinator
.
persistentStore
(
for
:
oldStoreURL
)
else
{
return
}
// Attempt to migrate the old store over to the shared store URL.
do
{
self
.
logger
.
log
(
"Migrating local store to shared store..."
)
try
coordinator
.
migratePersistentStore
(
oldStore
,
to
:
sharedStoreURL
,
options
:
nil
,
withType
:
NSSQLiteStoreType
)
self
.
logger
.
log
(
"Migrated local store to shared store."
)
}
catch
{
logger
.
logCrashAndSetFlag
(
error
:
LocalStoreError
.
couldNotMigrateStore
(
error
.
localizedDescription
))
}
// Attempt to delete the old store.
do
{
logger
.
log
(
"Deleting migrated local store..."
)
try
FileManager
.
default
.
removeItem
(
at
:
oldStoreURL
)
logger
.
log
(
"Deleted migrated local store."
)
}
catch
{
logger
.
logCrashAndSetFlag
(
error
:
LocalStoreError
.
couldNotDeleteStoreAfterMigration
(
error
.
localizedDescription
)
)
}
}
func
registerObservers
()
{
let
center
=
NotificationCenter
.
default
#if
os
(
iOS
)
let
notification
=
UIApplication
.
willResignActiveNotification
#elseif
os
(
macOS
)
let
notification
=
NSApplication
.
willResignActiveNotification
#endif
// We don't need to worry about removing this observer because we're targeting iOS 9+ / macOS 10.11+; the
// system will clean this up the next time it would be posted to.
// See: https://developer.apple.com/documentation/foundation/notificationcenter/1413994-removeobserver
// And: https://developer.apple.com/documentation/foundation/notificationcenter/1407263-removeobserver
// swiftlint:disable:next discarded_notification_center_observer
center
.
addObserver
(
forName
:
notification
,
object
:
nil
,
queue
:
nil
,
using
:
self
.
saveContextOnResignActive
)
}
func
saveContextOnResignActive
(
_
notification
:
Notification
)
{
saveContext
()
}
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 15, 9:17 AM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3491210
Attached To
rWFSUI WriteFreely SwiftUI
Event Timeline
Log In to Comment