forked from shadowfacts/Tusker
Add LazilyDecoding for CoreData embedded objects
This commit is contained in:
parent
2a419eb87c
commit
7deb4fc5b4
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public class Attachment: Decodable {
|
public class Attachment: Codable {
|
||||||
public let id: String
|
public let id: String
|
||||||
public let kind: Kind
|
public let kind: Kind
|
||||||
public let url: URL
|
public let url: URL
|
||||||
|
@ -58,7 +58,7 @@ public class Attachment: Decodable {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Attachment {
|
extension Attachment {
|
||||||
public enum Kind: String, Decodable {
|
public enum Kind: String, Codable {
|
||||||
case image
|
case image
|
||||||
case video
|
case video
|
||||||
case gifv
|
case gifv
|
||||||
|
@ -68,7 +68,7 @@ extension Attachment {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Attachment {
|
extension Attachment {
|
||||||
public class Metadata: Decodable {
|
public class Metadata: Codable {
|
||||||
public let length: String?
|
public let length: String?
|
||||||
public let duration: Float?
|
public let duration: Float?
|
||||||
public let audioEncoding: String?
|
public let audioEncoding: String?
|
||||||
|
@ -99,7 +99,7 @@ extension Attachment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ImageMetadata: Decodable {
|
public class ImageMetadata: Codable {
|
||||||
public let width: Int?
|
public let width: Int?
|
||||||
public let height: Int?
|
public let height: Int?
|
||||||
public let size: String?
|
public let size: String?
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public class Emoji: Decodable {
|
public class Emoji: Codable {
|
||||||
public let shortcode: String
|
public let shortcode: String
|
||||||
public let url: URL
|
public let url: URL
|
||||||
public let staticURL: URL
|
public let staticURL: URL
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public class Mention: Decodable {
|
public class Mention: Codable {
|
||||||
public let url: URL
|
public let url: URL
|
||||||
public let username: String
|
public let username: String
|
||||||
public let acct: String
|
public let acct: String
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
D60D2B8223844C71001B87A3 /* BaseStatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60D2B8123844C71001B87A3 /* BaseStatusTableViewCell.swift */; };
|
D60D2B8223844C71001B87A3 /* BaseStatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60D2B8123844C71001B87A3 /* BaseStatusTableViewCell.swift */; };
|
||||||
D60E2F272442372B005F8713 /* StatusMO.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60E2F232442372B005F8713 /* StatusMO.swift */; };
|
D60E2F272442372B005F8713 /* StatusMO.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60E2F232442372B005F8713 /* StatusMO.swift */; };
|
||||||
D60E2F292442372B005F8713 /* AccountMO.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60E2F252442372B005F8713 /* AccountMO.swift */; };
|
D60E2F292442372B005F8713 /* AccountMO.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60E2F252442372B005F8713 /* AccountMO.swift */; };
|
||||||
|
D60E2F2C24423EAD005F8713 /* LazilyDecoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60E2F2B24423EAD005F8713 /* LazilyDecoding.swift */; };
|
||||||
D60E2F2E244248BF005F8713 /* MastodonCachePersistentStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60E2F2D244248BF005F8713 /* MastodonCachePersistentStore.swift */; };
|
D60E2F2E244248BF005F8713 /* MastodonCachePersistentStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60E2F2D244248BF005F8713 /* MastodonCachePersistentStore.swift */; };
|
||||||
D61099B42144B0CC00432DC2 /* Pachyderm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D61099AB2144B0CC00432DC2 /* Pachyderm.framework */; };
|
D61099B42144B0CC00432DC2 /* Pachyderm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D61099AB2144B0CC00432DC2 /* Pachyderm.framework */; };
|
||||||
D61099BB2144B0CC00432DC2 /* PachydermTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61099BA2144B0CC00432DC2 /* PachydermTests.swift */; };
|
D61099BB2144B0CC00432DC2 /* PachydermTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61099BA2144B0CC00432DC2 /* PachydermTests.swift */; };
|
||||||
|
@ -1236,6 +1237,7 @@
|
||||||
D6028B9A2150811100F223B9 /* MastodonCache.swift */,
|
D6028B9A2150811100F223B9 /* MastodonCache.swift */,
|
||||||
D6C693EE216192C2007D6A6D /* TuskerNavigationDelegate.swift */,
|
D6C693EE216192C2007D6A6D /* TuskerNavigationDelegate.swift */,
|
||||||
D6DFC69F242C4CCC00ACC392 /* WeakArray.swift */,
|
D6DFC69F242C4CCC00ACC392 /* WeakArray.swift */,
|
||||||
|
D60E2F2B24423EAD005F8713 /* LazilyDecoding.swift */,
|
||||||
D6F1F84E2193B9BE00F5FE67 /* Caching */,
|
D6F1F84E2193B9BE00F5FE67 /* Caching */,
|
||||||
D6757A7A2157E00100721E32 /* XCallbackURL */,
|
D6757A7A2157E00100721E32 /* XCallbackURL */,
|
||||||
D62D241E217AA46B005076CC /* Shortcuts */,
|
D62D241E217AA46B005076CC /* Shortcuts */,
|
||||||
|
@ -1664,6 +1666,7 @@
|
||||||
D62D2422217AA7E1005076CC /* UserActivityManager.swift in Sources */,
|
D62D2422217AA7E1005076CC /* UserActivityManager.swift in Sources */,
|
||||||
D60D2B8223844C71001B87A3 /* BaseStatusTableViewCell.swift in Sources */,
|
D60D2B8223844C71001B87A3 /* BaseStatusTableViewCell.swift in Sources */,
|
||||||
D60E2F272442372B005F8713 /* StatusMO.swift in Sources */,
|
D60E2F272442372B005F8713 /* StatusMO.swift in Sources */,
|
||||||
|
D60E2F2C24423EAD005F8713 /* LazilyDecoding.swift in Sources */,
|
||||||
D62D2424217ABF3F005076CC /* NSUserActivity+Extensions.swift in Sources */,
|
D62D2424217ABF3F005076CC /* NSUserActivity+Extensions.swift in Sources */,
|
||||||
D646C958213B367000269FB5 /* LargeImageShrinkAnimationController.swift in Sources */,
|
D646C958213B367000269FB5 /* LargeImageShrinkAnimationController.swift in Sources */,
|
||||||
D6A3BC852321F6C100FD64D5 /* AccountListTableViewController.swift in Sources */,
|
D6A3BC852321F6C100FD64D5 /* AccountListTableViewController.swift in Sources */,
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import CoreData
|
import CoreData
|
||||||
|
import Pachyderm
|
||||||
|
|
||||||
@objc(AccountMO)
|
@objc(AccountMO)
|
||||||
public class AccountMO: NSManagedObject {
|
public class AccountMO: NSManagedObject {
|
||||||
|
@ -22,8 +23,8 @@ public class AccountMO: NSManagedObject {
|
||||||
@NSManaged public var bot: Bool
|
@NSManaged public var bot: Bool
|
||||||
@NSManaged public var createdAt: Date?
|
@NSManaged public var createdAt: Date?
|
||||||
@NSManaged public var displayName: String?
|
@NSManaged public var displayName: String?
|
||||||
@NSManaged public var emojis: Data?
|
@NSManaged public var emojisData: Data?
|
||||||
@NSManaged public var fields: Data?
|
@NSManaged public var fieldsData: Data?
|
||||||
@NSManaged public var followersCount: Int64
|
@NSManaged public var followersCount: Int64
|
||||||
@NSManaged public var followingCount: Int64
|
@NSManaged public var followingCount: Int64
|
||||||
@NSManaged public var header: URL?
|
@NSManaged public var header: URL?
|
||||||
|
@ -36,4 +37,10 @@ public class AccountMO: NSManagedObject {
|
||||||
@NSManaged public var username: String?
|
@NSManaged public var username: String?
|
||||||
@NSManaged public var movedTo: AccountMO?
|
@NSManaged public var movedTo: AccountMO?
|
||||||
|
|
||||||
|
@LazilyDecoding(arrayFrom: \AccountMO.emojisData)
|
||||||
|
var emojis: [Emoji]
|
||||||
|
|
||||||
|
@LazilyDecoding(arrayFrom: \AccountMO.fieldsData)
|
||||||
|
var fields: [Account.Field]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import CoreData
|
import CoreData
|
||||||
|
import Pachyderm
|
||||||
|
|
||||||
@objc(StatusMO)
|
@objc(StatusMO)
|
||||||
public final class StatusMO: NSManagedObject {
|
public final class StatusMO: NSManagedObject {
|
||||||
|
@ -41,4 +42,16 @@ public final class StatusMO: NSManagedObject {
|
||||||
@NSManaged public var inReplyToAccount: AccountMO?
|
@NSManaged public var inReplyToAccount: AccountMO?
|
||||||
@NSManaged public var reblog: StatusMO?
|
@NSManaged public var reblog: StatusMO?
|
||||||
|
|
||||||
|
@LazilyDecoding(arrayFrom: \StatusMO.attachmentsData)
|
||||||
|
var attachments: [Attachment]
|
||||||
|
|
||||||
|
@LazilyDecoding(arrayFrom: \StatusMO.emojisData)
|
||||||
|
var emoji: [Emoji]
|
||||||
|
|
||||||
|
@LazilyDecoding(arrayFrom: \StatusMO.hashtagsData)
|
||||||
|
var hashtags: [Hashtag]
|
||||||
|
|
||||||
|
@LazilyDecoding(arrayFrom: \StatusMO.mentionsData)
|
||||||
|
var mentions: [Mention]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
<attribute name="bot" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
<attribute name="bot" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||||
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
|
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
|
||||||
<attribute name="displayName" attributeType="String"/>
|
<attribute name="displayName" attributeType="String"/>
|
||||||
<attribute name="emojis" attributeType="Binary"/>
|
<attribute name="emojisData" attributeType="Binary"/>
|
||||||
<attribute name="fields" optional="YES" attributeType="Binary"/>
|
<attribute name="fieldsData" optional="YES" attributeType="Binary"/>
|
||||||
<attribute name="followersCount" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
<attribute name="followersCount" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||||
<attribute name="followingCount" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
<attribute name="followingCount" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||||
<attribute name="header" attributeType="URI"/>
|
<attribute name="header" attributeType="URI"/>
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
//
|
||||||
|
// LazyDecoding.swift
|
||||||
|
// Tusker
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 4/11/20.
|
||||||
|
// Copyright © 2020 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
private let decoder = PropertyListDecoder()
|
||||||
|
private let encoder = PropertyListEncoder()
|
||||||
|
|
||||||
|
@propertyWrapper
|
||||||
|
struct LazilyDecoding<Enclosing, Value: Codable> {
|
||||||
|
|
||||||
|
private let keyPath: ReferenceWritableKeyPath<Enclosing, Data?>
|
||||||
|
private let fallback: Value
|
||||||
|
private var value: Value?
|
||||||
|
|
||||||
|
init(from keyPath: ReferenceWritableKeyPath<Enclosing, Data?>, fallback: Value) {
|
||||||
|
self.keyPath = keyPath
|
||||||
|
self.fallback = fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrappedValue: Value {
|
||||||
|
get { fatalError("called LazilyDecoding wrappedValue getter") }
|
||||||
|
set { fatalError("called LazilyDecoding wrappedValue setter") }
|
||||||
|
}
|
||||||
|
|
||||||
|
static subscript(_enclosingInstance instance: Enclosing, wrapped wrappedKeyPath: ReferenceWritableKeyPath<Enclosing, Value>, storage storageKeyPath: ReferenceWritableKeyPath<Enclosing, Self>) -> Value {
|
||||||
|
get {
|
||||||
|
var wrapper = instance[keyPath: storageKeyPath]
|
||||||
|
if let value = wrapper.value {
|
||||||
|
return value
|
||||||
|
} else {
|
||||||
|
guard let data = instance[keyPath: wrapper.keyPath] else { return wrapper.fallback }
|
||||||
|
do {
|
||||||
|
let value = try decoder.decode(Value.self, from: data)
|
||||||
|
wrapper.value = value
|
||||||
|
instance[keyPath: storageKeyPath] = wrapper
|
||||||
|
return value
|
||||||
|
} catch {
|
||||||
|
return wrapper.fallback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
var wrapper = instance[keyPath: storageKeyPath]
|
||||||
|
wrapper.value = newValue
|
||||||
|
instance[keyPath: storageKeyPath] = wrapper
|
||||||
|
let newData = try? encoder.encode(newValue)
|
||||||
|
instance[keyPath: wrapper.keyPath] = newData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension LazilyDecoding {
|
||||||
|
init(arrayFrom keyPath: ReferenceWritableKeyPath<Enclosing, Data?>) {
|
||||||
|
self.init(from: keyPath, fallback: [] as! Value)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue