feat(view, model): 增加自动保存功能
增加自动保存功能 Signed-off-by: Ching <loooching@gmail.com>
This commit is contained in:
parent
89d38faea4
commit
ac3031dd05
@ -11,4 +11,5 @@ import SwiftUI
|
||||
|
||||
struct const {
|
||||
static let defaultEmojiFontSize: CGFloat = 40
|
||||
static let coalescingInterval = 5.0
|
||||
}
|
||||
|
||||
@ -10,14 +10,55 @@ import SwiftUI
|
||||
class EmojiArtDocument: ObservableObject {
|
||||
@Published private(set) var emojiArt: EmojiArtModel {
|
||||
didSet {
|
||||
scheduleAutosave()
|
||||
if emojiArt.background != oldValue.background {
|
||||
fetchBackgoundImageDataIfNecessary()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var autosaveTimer: Timer?
|
||||
|
||||
private func scheduleAutosave() {
|
||||
autosaveTimer?.invalidate()
|
||||
autosaveTimer = Timer.scheduledTimer(withTimeInterval: const.coalescingInterval, repeats: false) { _ in
|
||||
self.autoSave()
|
||||
}
|
||||
}
|
||||
|
||||
private enum Autosave {
|
||||
static let filename = "Autosaved.emojiart"
|
||||
static var url: URL? {
|
||||
let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
|
||||
return documentDirectory?.appendingPathComponent(filename)
|
||||
}
|
||||
}
|
||||
|
||||
private func autoSave() {
|
||||
if let url = Autosave.url {
|
||||
save(to: url)
|
||||
}
|
||||
}
|
||||
|
||||
private func save(to url: URL) {
|
||||
let thisFunction = "\(String(describing: self)).\(#function)"
|
||||
do {
|
||||
let data: Data = try emojiArt.json()
|
||||
print("\(thisFunction) json = \(String(data: data, encoding: .utf8) ?? "nil")")
|
||||
try data.write(to: url)
|
||||
print("\(thisFunction) success")
|
||||
} catch {
|
||||
print("\(thisFunction) error = \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
emojiArt = EmojiArtModel()
|
||||
if let url = Autosave.url, let autosavedEmojiArt = try? EmojiArtModel(url: url) {
|
||||
emojiArt = autosavedEmojiArt
|
||||
fetchBackgoundImageDataIfNecessary()
|
||||
} else {
|
||||
emojiArt = EmojiArtModel()
|
||||
}
|
||||
}
|
||||
|
||||
var emojis: [EmojiArtModel.Emoji] { emojiArt.emojis }
|
||||
|
||||
@ -8,11 +8,36 @@
|
||||
import Foundation
|
||||
|
||||
extension EmojiArtModel {
|
||||
enum Background: Equatable {
|
||||
enum Background: Equatable, Codable {
|
||||
case blank
|
||||
case url(URL)
|
||||
case imageData(Data)
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
if let url = try? container.decode(URL.self, forKey: .url) {
|
||||
self = .url(url)
|
||||
} else if let imageData = try? container.decode(Data.self, forKey: .imageData) {
|
||||
self = .imageData(imageData)
|
||||
} else {
|
||||
self = .blank
|
||||
}
|
||||
}
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case url = "theURL"
|
||||
case imageData
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
switch self {
|
||||
case .url(let url): try container.encode(url, forKey: .url)
|
||||
case .imageData(let data): try container.encode(data, forKey: .imageData)
|
||||
case .blank: break
|
||||
}
|
||||
}
|
||||
|
||||
var url: URL? {
|
||||
switch self {
|
||||
case .url(let url): return url
|
||||
|
||||
@ -7,11 +7,11 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
struct EmojiArtModel {
|
||||
struct EmojiArtModel: Codable {
|
||||
var background: Background = EmojiArtModel.Background.blank
|
||||
var emojis = [Emoji]()
|
||||
|
||||
struct Emoji: Identifiable {
|
||||
struct Emoji: Identifiable, Hashable, Codable {
|
||||
let text: String
|
||||
var x: Int
|
||||
var y: Int
|
||||
@ -27,14 +27,25 @@ struct EmojiArtModel {
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
|
||||
func json() throws -> Data {
|
||||
return try JSONEncoder().encode(self)
|
||||
}
|
||||
|
||||
|
||||
init(json: Data) throws {
|
||||
self = try JSONDecoder().decode(EmojiArtModel.self, from: json)
|
||||
}
|
||||
|
||||
init(url: URL) throws {
|
||||
let data = try Data(contentsOf: url)
|
||||
self = try EmojiArtModel.init(json: data)
|
||||
}
|
||||
|
||||
init() {}
|
||||
|
||||
private var uniqueEmojiId = 0
|
||||
mutating func addEmoji(_ text: String, at location: (x: Int, y: Int), size: Int) {
|
||||
uniqueEmojiId += 1
|
||||
emojis.append(Emoji(text: text, x: location.x, y: location.y, size: size, id: uniqueEmojiId))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user