From c3a8abf8dc90699554c6f01fe58fe43e25da3209 Mon Sep 17 00:00:00 2001 From: Riley Testut Date: Mon, 20 May 2019 21:24:53 +0200 Subject: [PATCH] Switches to Core Data model objects --- AltStore.xcodeproj/project.pbxproj | 41 +++++++++--- AltStore/AppDelegate.swift | 16 ++++- AltStore/Apps/AppDetailViewController.swift | 4 +- AltStore/Apps/AppTableViewCell.swift | 2 +- AltStore/Apps/AppsViewController.swift | 57 ++++++++++++----- AltStore/Base.lproj/Main.storyboard | 15 ++--- .../JSONDecoder+ManagedObjectContext.swift | 36 +++++++++++ .../AltStore.xcdatamodel/contents | 19 ++++++ AltStore/Model/App.swift | 62 ++++++++++++++++--- AltStore/Model/DatabaseManager.swift | 48 ++++++++++++++ AltStore/Resources/Apps.json | 22 +++++++ AltStore/Resources/Apps.plist | 51 --------------- AltStore/SecondViewController.swift | 20 ------ 13 files changed, 272 insertions(+), 121 deletions(-) create mode 100644 AltStore/Extensions/JSONDecoder+ManagedObjectContext.swift create mode 100644 AltStore/Model/AltStore.xcdatamodeld/AltStore.xcdatamodel/contents create mode 100644 AltStore/Model/DatabaseManager.swift create mode 100644 AltStore/Resources/Apps.json delete mode 100644 AltStore/Resources/Apps.plist delete mode 100644 AltStore/SecondViewController.swift diff --git a/AltStore.xcodeproj/project.pbxproj b/AltStore.xcodeproj/project.pbxproj index b7b16aa4..8f6a0943 100644 --- a/AltStore.xcodeproj/project.pbxproj +++ b/AltStore.xcodeproj/project.pbxproj @@ -9,6 +9,11 @@ /* Begin PBXBuildFile section */ BF5AB3A82285FE7500DC914B /* AltSign.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF5AB3A72285FE6C00DC914B /* AltSign.framework */; }; BF5AB3A92285FE7500DC914B /* AltSign.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BF5AB3A72285FE6C00DC914B /* AltSign.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + BFB11692229322E400BB457C /* DatabaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFB11691229322E400BB457C /* DatabaseManager.swift */; }; + BFB1169B2293274D00BB457C /* JSONDecoder+ManagedObjectContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFB1169A2293274D00BB457C /* JSONDecoder+ManagedObjectContext.swift */; }; + BFB1169D22932DB100BB457C /* Apps.json in Resources */ = {isa = PBXBuildFile; fileRef = BFB1169C22932DB100BB457C /* Apps.json */; }; + BFBBE2DD22931B20002097FA /* AltStore.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = BFBBE2DB22931B20002097FA /* AltStore.xcdatamodeld */; }; + BFBBE2DF22931F73002097FA /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBBE2DE22931F73002097FA /* App.swift */; }; BFD2476E2284B9A500981D42 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2476D2284B9A500981D42 /* AppDelegate.swift */; }; BFD247702284B9A500981D42 /* AppsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2476F2284B9A500981D42 /* AppsViewController.swift */; }; BFD247722284B9A500981D42 /* SecondViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD247712284B9A500981D42 /* SecondViewController.swift */; }; @@ -20,8 +25,6 @@ BFD2478C2284C4C300981D42 /* AppIconImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2478B2284C4C300981D42 /* AppIconImageView.swift */; }; BFD2478F2284C8F900981D42 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2478E2284C8F900981D42 /* Button.swift */; }; BFD247932284D4B700981D42 /* AppTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD247922284D4B700981D42 /* AppTableViewCell.swift */; }; - BFD247952284D7BD00981D42 /* Apps.plist in Resources */ = {isa = PBXBuildFile; fileRef = BFD247942284D7BD00981D42 /* Apps.plist */; }; - BFD2479A2284D80900981D42 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD247992284D80900981D42 /* App.swift */; }; BFD2479C2284E19A00981D42 /* AppDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2479B2284E19A00981D42 /* AppDetailViewController.swift */; }; BFD2479F2284FBD000981D42 /* UIColor+AltStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2479E2284FBD000981D42 /* UIColor+AltStore.swift */; }; /* End PBXBuildFile section */ @@ -43,6 +46,11 @@ /* Begin PBXFileReference section */ BF5AB3A72285FE6C00DC914B /* AltSign.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = AltSign.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + BFB11691229322E400BB457C /* DatabaseManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseManager.swift; sourceTree = ""; }; + BFB1169A2293274D00BB457C /* JSONDecoder+ManagedObjectContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "JSONDecoder+ManagedObjectContext.swift"; sourceTree = ""; }; + BFB1169C22932DB100BB457C /* Apps.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Apps.json; sourceTree = ""; }; + BFBBE2DC22931B20002097FA /* AltStore.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = AltStore.xcdatamodel; sourceTree = ""; }; + BFBBE2DE22931F73002097FA /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = ""; }; BFD2476A2284B9A500981D42 /* AltStore.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AltStore.app; sourceTree = BUILT_PRODUCTS_DIR; }; BFD2476D2284B9A500981D42 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; BFD2476F2284B9A500981D42 /* AppsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppsViewController.swift; sourceTree = ""; }; @@ -55,8 +63,6 @@ BFD2478B2284C4C300981D42 /* AppIconImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIconImageView.swift; sourceTree = ""; }; BFD2478E2284C8F900981D42 /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; BFD247922284D4B700981D42 /* AppTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppTableViewCell.swift; sourceTree = ""; }; - BFD247942284D7BD00981D42 /* Apps.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Apps.plist; sourceTree = ""; }; - BFD247992284D80900981D42 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = ""; }; BFD2479B2284E19A00981D42 /* AppDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDetailViewController.swift; sourceTree = ""; }; BFD2479E2284FBD000981D42 /* UIColor+AltStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+AltStore.swift"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -139,7 +145,7 @@ isa = PBXGroup; children = ( BFD247762284B9A700981D42 /* Assets.xcassets */, - BFD247942284D7BD00981D42 /* Apps.plist */, + BFB1169C22932DB100BB457C /* Apps.json */, ); path = Resources; sourceTree = ""; @@ -156,7 +162,9 @@ BFD247982284D7FC00981D42 /* Model */ = { isa = PBXGroup; children = ( - BFD247992284D80900981D42 /* App.swift */, + BFBBE2DB22931B20002097FA /* AltStore.xcdatamodeld */, + BFB11691229322E400BB457C /* DatabaseManager.swift */, + BFBBE2DE22931F73002097FA /* App.swift */, ); path = Model; sourceTree = ""; @@ -165,6 +173,7 @@ isa = PBXGroup; children = ( BFD2479E2284FBD000981D42 /* UIColor+AltStore.swift */, + BFB1169A2293274D00BB457C /* JSONDecoder+ManagedObjectContext.swift */, ); path = Extensions; sourceTree = ""; @@ -228,7 +237,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - BFD247952284D7BD00981D42 /* Apps.plist in Resources */, + BFB1169D22932DB100BB457C /* Apps.json in Resources */, BFD2477A2284B9A700981D42 /* LaunchScreen.storyboard in Resources */, BFD247772284B9A700981D42 /* Assets.xcassets in Resources */, BFD247752284B9A500981D42 /* Main.storyboard in Resources */, @@ -244,11 +253,14 @@ files = ( BFD2478F2284C8F900981D42 /* Button.swift in Sources */, BFD247722284B9A500981D42 /* SecondViewController.swift in Sources */, + BFB11692229322E400BB457C /* DatabaseManager.swift in Sources */, + BFBBE2DF22931F73002097FA /* App.swift in Sources */, BFD2478C2284C4C300981D42 /* AppIconImageView.swift in Sources */, BFD2479C2284E19A00981D42 /* AppDetailViewController.swift in Sources */, BFD2476E2284B9A500981D42 /* AppDelegate.swift in Sources */, BFD247702284B9A500981D42 /* AppsViewController.swift in Sources */, - BFD2479A2284D80900981D42 /* App.swift in Sources */, + BFBBE2DD22931B20002097FA /* AltStore.xcdatamodeld in Sources */, + BFB1169B2293274D00BB457C /* JSONDecoder+ManagedObjectContext.swift in Sources */, BFD247932284D4B700981D42 /* AppTableViewCell.swift in Sources */, BFD2479F2284FBD000981D42 /* UIColor+AltStore.swift in Sources */, ); @@ -450,6 +462,19 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCVersionGroup section */ + BFBBE2DB22931B20002097FA /* AltStore.xcdatamodeld */ = { + isa = XCVersionGroup; + children = ( + BFBBE2DC22931B20002097FA /* AltStore.xcdatamodel */, + ); + currentVersion = BFBBE2DC22931B20002097FA /* AltStore.xcdatamodel */; + path = AltStore.xcdatamodeld; + sourceTree = ""; + versionGroupType = wrapper.xcdatamodel; + }; +/* End XCVersionGroup section */ }; rootObject = BFD247622284B9A500981D42 /* Project object */; } diff --git a/AltStore/AppDelegate.swift b/AltStore/AppDelegate.swift index bdfcfd80..9773e183 100644 --- a/AltStore/AppDelegate.swift +++ b/AltStore/AppDelegate.swift @@ -13,9 +13,19 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - // Override point for customization after application launch. + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool + { + DatabaseManager.shared.start { (error) in + if let error = error + { + print("Failed to start DatabaseManager.", error) + } + else + { + print("Started DatabaseManager") + } + } + return true } diff --git a/AltStore/Apps/AppDetailViewController.swift b/AltStore/Apps/AppDetailViewController.swift index ebfa6ce9..17fe3d3c 100644 --- a/AltStore/Apps/AppDetailViewController.swift +++ b/AltStore/Apps/AppDetailViewController.swift @@ -32,7 +32,6 @@ class AppDetailViewController: UITableViewController private lazy var screenshotsDataSource = self.makeScreenshotsDataSource() @IBOutlet private var nameLabel: UILabel! - @IBOutlet private var subtitleLabel: UILabel! @IBOutlet private var developerButton: UIButton! @IBOutlet private var appIconImageView: UIImageView! @@ -73,8 +72,7 @@ private extension AppDetailViewController func update() { self.nameLabel.text = self.app.name - self.subtitleLabel.text = self.app.subtitle - self.developerButton.setTitle(self.app.developer, for: .normal) + self.developerButton.setTitle(self.app.developerName, for: .normal) self.appIconImageView.image = UIImage(named: self.app.iconName) let text = String(format: NSLocalizedString("Download %@", comment: ""), self.app.name) diff --git a/AltStore/Apps/AppTableViewCell.swift b/AltStore/Apps/AppTableViewCell.swift index 733056d9..e8ad4411 100644 --- a/AltStore/Apps/AppTableViewCell.swift +++ b/AltStore/Apps/AppTableViewCell.swift @@ -11,7 +11,7 @@ import UIKit @objc class AppTableViewCell: UITableViewCell { @IBOutlet var nameLabel: UILabel! - @IBOutlet var subtitleLabel: UILabel! + @IBOutlet var developerLabel: UILabel! @IBOutlet var appIconImageView: UIImageView! @IBOutlet var button: UIButton! diff --git a/AltStore/Apps/AppsViewController.swift b/AltStore/Apps/AppsViewController.swift index 82c092bb..48813036 100644 --- a/AltStore/Apps/AppsViewController.swift +++ b/AltStore/Apps/AppsViewController.swift @@ -23,6 +23,13 @@ class AppsViewController: UITableViewController self.tableView.tableFooterView = UIView() } + override func viewWillAppear(_ animated: Bool) + { + super.viewWillAppear(animated) + + self.fetchApps() + } + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { guard segue.identifier == "showAppDetail" else { return } @@ -38,27 +45,45 @@ class AppsViewController: UITableViewController private extension AppsViewController { - func makeDataSource() -> RSTArrayTableViewDataSource + func makeDataSource() -> RSTFetchedResultsTableViewDataSource { - let appsFileURL = Bundle.main.url(forResource: "Apps", withExtension: "plist")! + let fetchRequest = App.fetchRequest() as NSFetchRequest + fetchRequest.relationshipKeyPathsForPrefetching = [#keyPath(InstalledApp.app)] + fetchRequest.sortDescriptors = [NSSortDescriptor(keyPath: \App.name, ascending: true)] + fetchRequest.returnsObjectsAsFaults = false - do - { - let data = try Data(contentsOf: appsFileURL) - let apps = try PropertyListDecoder().decode([App].self, from: data) + let dataSource = RSTFetchedResultsTableViewDataSource(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.shared.viewContext) + dataSource.cellConfigurationHandler = { (cell, app, indexPath) in + let cell = cell as! AppTableViewCell + cell.nameLabel.text = app.name + cell.developerLabel.text = app.developerName + cell.appIconImageView.image = UIImage(named: app.iconName) - let dataSource = RSTArrayTableViewDataSource(items: apps) - dataSource.cellConfigurationHandler = { (cell, app, indexPath) in - let cell = cell as! AppTableViewCell - cell.nameLabel.text = app.name - cell.subtitleLabel.text = app.subtitle - cell.appIconImageView.image = UIImage(named: app.iconName) } - return dataSource } - catch - { - fatalError("Failed to load apps. \(error)") + + return dataSource + } + + func fetchApps() + { + DatabaseManager.shared.persistentContainer.performBackgroundTask { (context) in + let appsFileURL = Bundle.main.url(forResource: "Apps", withExtension: "json")! + + do + { + let data = try Data(contentsOf: appsFileURL) + + let decoder = JSONDecoder() + decoder.managedObjectContext = context + + _ = try decoder.decode([App].self, from: data) + try context.save() + } + catch + { + fatalError("Failed to save fetched apps. \(error)") + } } } } diff --git a/AltStore/Base.lproj/Main.storyboard b/AltStore/Base.lproj/Main.storyboard index 7ba0e007..2438eae7 100644 --- a/AltStore/Base.lproj/Main.storyboard +++ b/AltStore/Base.lproj/Main.storyboard @@ -143,8 +143,8 @@ + - @@ -196,7 +196,7 @@ - + -