Adding datasource for Core Data
This commit is contained in:
parent
1c12fe5b40
commit
49046d5619
@ -59,6 +59,11 @@
|
||||
7A49F51227D406CB00AEAAE0 /* VName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F50B27D406CB00AEAAE0 /* VName.swift */; };
|
||||
7A49F51527D40C6100AEAAE0 /* AutoCat2.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F51327D40C6100AEAAE0 /* AutoCat2.xcdatamodeld */; };
|
||||
7A9F2AC327E71531006492A9 /* ACTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9F2AC227E71531006492A9 /* ACTabBarController.swift */; };
|
||||
7AE32D6427F05F89004EF6E0 /* VehicleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE32D6327F05F89004EF6E0 /* VehicleCell.swift */; };
|
||||
7AE32D6627F063A1004EF6E0 /* UIEdgeInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE32D6527F063A1004EF6E0 /* UIEdgeInsets.swift */; };
|
||||
7AE32D6927F06536004EF6E0 /* CoreDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE32D6827F06536004EF6E0 /* CoreDataSource.swift */; };
|
||||
7AE32D6E27F06D2D004EF6E0 /* SwiftDate in Frameworks */ = {isa = PBXBuildFile; productRef = 7AE32D6D27F06D2D004EF6E0 /* SwiftDate */; };
|
||||
7AE32D7127F06DA4004EF6E0 /* DateSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE32D7027F06DA4004EF6E0 /* DateSection.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@ -167,6 +172,10 @@
|
||||
7A49F50B27D406CB00AEAAE0 /* VName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VName.swift; sourceTree = "<group>"; };
|
||||
7A49F51427D40C6100AEAAE0 /* Shared.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Shared.xcdatamodel; sourceTree = "<group>"; };
|
||||
7A9F2AC227E71531006492A9 /* ACTabBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ACTabBarController.swift; sourceTree = "<group>"; };
|
||||
7AE32D6327F05F89004EF6E0 /* VehicleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleCell.swift; sourceTree = "<group>"; };
|
||||
7AE32D6527F063A1004EF6E0 /* UIEdgeInsets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIEdgeInsets.swift; sourceTree = "<group>"; };
|
||||
7AE32D6827F06536004EF6E0 /* CoreDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataSource.swift; sourceTree = "<group>"; };
|
||||
7AE32D7027F06DA4004EF6E0 /* DateSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateSection.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -198,6 +207,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
7AE32D6E27F06D2D004EF6E0 /* SwiftDate in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -220,6 +230,7 @@
|
||||
6841A709FA6B606978425A26 /* UIViewController.swift */,
|
||||
7A28283027E721A70049BDBF /* UIView.swift */,
|
||||
7A28283227E7263B0049BDBF /* UIStackView.swift */,
|
||||
7AE32D6527F063A1004EF6E0 /* UIEdgeInsets.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
@ -248,6 +259,7 @@
|
||||
6841AEAC436660C91E968C9F /* Components */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7AE32D6727F06512004EF6E0 /* TableView */,
|
||||
7A24C19927EE259000049E7F /* PlateView */,
|
||||
7A28282D27E720830049BDBF /* ACTabBar */,
|
||||
6841A0EB55A59DAC94129594 /* Extensions */,
|
||||
@ -312,6 +324,7 @@
|
||||
7A49F4A127D4061900AEAAE0 /* AutoCat2 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7AE32D6227F05F5D004EF6E0 /* Cells */,
|
||||
7A24C19427EE212E00049E7F /* Fonts */,
|
||||
7A49F4A227D4061900AEAAE0 /* AppDelegate.swift */,
|
||||
7A49F4A427D4061900AEAAE0 /* SceneDelegate.swift */,
|
||||
@ -347,6 +360,7 @@
|
||||
7A49F4D827D4064500AEAAE0 /* AutoCatCore */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7AE32D6F27F06D87004EF6E0 /* DataSource */,
|
||||
7A49F51327D40C6100AEAAE0 /* AutoCat2.xcdatamodeld */,
|
||||
7A49F50427D406CB00AEAAE0 /* Models */,
|
||||
7A49F4FF27D406C300AEAAE0 /* Services */,
|
||||
@ -407,6 +421,30 @@
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7AE32D6227F05F5D004EF6E0 /* Cells */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7AE32D6327F05F89004EF6E0 /* VehicleCell.swift */,
|
||||
);
|
||||
path = Cells;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7AE32D6727F06512004EF6E0 /* TableView */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7AE32D6827F06536004EF6E0 /* CoreDataSource.swift */,
|
||||
);
|
||||
path = TableView;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7AE32D6F27F06D87004EF6E0 /* DataSource */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7AE32D7027F06DA4004EF6E0 /* DateSection.swift */,
|
||||
);
|
||||
path = DataSource;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
@ -494,6 +532,9 @@
|
||||
dependencies = (
|
||||
);
|
||||
name = AutoCatCore;
|
||||
packageProductDependencies = (
|
||||
7AE32D6D27F06D2D004EF6E0 /* SwiftDate */,
|
||||
);
|
||||
productName = AutoCatCore;
|
||||
productReference = 7A49F4D727D4064500AEAAE0 /* AutoCatCore.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
@ -559,6 +600,7 @@
|
||||
packageReferences = (
|
||||
7A48B26527D9442A004D1A4B /* XCRemoteSwiftPackageReference "PKHUD" */,
|
||||
7A28283427E74C110049BDBF /* XCRemoteSwiftPackageReference "SwiftEntryKit" */,
|
||||
7AE32D6C27F06D2D004EF6E0 /* XCRemoteSwiftPackageReference "SwiftDate" */,
|
||||
);
|
||||
productRefGroup = 7A49F4A027D4061900AEAAE0 /* Products */;
|
||||
projectDirPath = "";
|
||||
@ -626,6 +668,8 @@
|
||||
7A49F4A727D4061900AEAAE0 /* ViewController.swift in Sources */,
|
||||
7A49F4A327D4061900AEAAE0 /* AppDelegate.swift in Sources */,
|
||||
7A49F4A527D4061900AEAAE0 /* SceneDelegate.swift in Sources */,
|
||||
7AE32D6427F05F89004EF6E0 /* VehicleCell.swift in Sources */,
|
||||
7AE32D6927F06536004EF6E0 /* CoreDataSource.swift in Sources */,
|
||||
6841AF924E165F1B3A3B5FB5 /* AuthController.swift in Sources */,
|
||||
6841A592745CDD869709EFA7 /* MainTabController.swift in Sources */,
|
||||
6841A8FF53F0AADF96B138C1 /* UIControl.swift in Sources */,
|
||||
@ -634,6 +678,7 @@
|
||||
6841A80BB89BFD8D18E79680 /* UITextField.swift in Sources */,
|
||||
7A24C19F27EE26B900049E7F /* CenterTextLayer.swift in Sources */,
|
||||
6841A5FE3E4927BF0EFF19F5 /* UIViewController.swift in Sources */,
|
||||
7AE32D6627F063A1004EF6E0 /* UIEdgeInsets.swift in Sources */,
|
||||
7A28282F27E720AC0049BDBF /* ACTabBarButton.swift in Sources */,
|
||||
6841A0EE0ECCDB3519F728E6 /* HistoryController.swift in Sources */,
|
||||
7A28283127E721A70049BDBF /* UIView.swift in Sources */,
|
||||
@ -682,6 +727,7 @@
|
||||
7A49F51527D40C6100AEAAE0 /* AutoCat2.xcdatamodeld in Sources */,
|
||||
7A49F50E27D406CB00AEAAE0 /* User.swift in Sources */,
|
||||
7A49F4FA27D406B200AEAAE0 /* ApiError.swift in Sources */,
|
||||
7AE32D7127F06DA4004EF6E0 /* DateSection.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -1169,6 +1215,14 @@
|
||||
minimumVersion = 5.0.0;
|
||||
};
|
||||
};
|
||||
7AE32D6C27F06D2D004EF6E0 /* XCRemoteSwiftPackageReference "SwiftDate" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/malcommac/SwiftDate";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 6.0.0;
|
||||
};
|
||||
};
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
@ -1182,6 +1236,11 @@
|
||||
package = 7A48B26527D9442A004D1A4B /* XCRemoteSwiftPackageReference "PKHUD" */;
|
||||
productName = PKHUD;
|
||||
};
|
||||
7AE32D6D27F06D2D004EF6E0 /* SwiftDate */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 7AE32D6C27F06D2D004EF6E0 /* XCRemoteSwiftPackageReference "SwiftDate" */;
|
||||
productName = SwiftDate;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
|
||||
/* Begin XCVersionGroup section */
|
||||
|
||||
@ -9,6 +9,15 @@
|
||||
"version" : "5.4.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swiftdate",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/malcommac/SwiftDate",
|
||||
"state" : {
|
||||
"revision" : "6190d0cefff3013e77ed567e6b074f324e5c5bf5",
|
||||
"version" : "6.3.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swiftentrykit",
|
||||
"kind" : "remoteSourceControl",
|
||||
|
||||
@ -12,12 +12,33 @@
|
||||
<key>AutoCat2.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>1</integer>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>AutoCatCore.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<key>SwiftDate (Playground) 1.xcscheme</key>
|
||||
<dict>
|
||||
<key>isShown</key>
|
||||
<false/>
|
||||
<key>orderHint</key>
|
||||
<integer>3</integer>
|
||||
</dict>
|
||||
<key>SwiftDate (Playground) 2.xcscheme</key>
|
||||
<dict>
|
||||
<key>isShown</key>
|
||||
<false/>
|
||||
<key>orderHint</key>
|
||||
<integer>4</integer>
|
||||
</dict>
|
||||
<key>SwiftDate (Playground).xcscheme</key>
|
||||
<dict>
|
||||
<key>isShown</key>
|
||||
<false/>
|
||||
<key>orderHint</key>
|
||||
<integer>2</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
|
||||
37
AutoCat2/Cells/VehicleCell.swift
Normal file
37
AutoCat2/Cells/VehicleCell.swift
Normal file
@ -0,0 +1,37 @@
|
||||
//
|
||||
// VehicleCell.swift
|
||||
// AutoCat2
|
||||
//
|
||||
// Created by Selim Mustafaev on 27.03.2022.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import AutoCatCore
|
||||
|
||||
class VehicleCell: UITableViewCell {
|
||||
|
||||
private let numberLabel = UILabel()
|
||||
.disableTranslatesAutoresizingMaskIntoConstraints()
|
||||
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
setup()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func setup() {
|
||||
contentView.addSubview(numberLabel)
|
||||
numberLabel.pin(to: contentView, insets: .init(all: 8))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension VehicleCell: ConfigurableCell {
|
||||
|
||||
func configure(with item: CDVehicle) {
|
||||
|
||||
}
|
||||
}
|
||||
20
AutoCat2/Components/Extensions/UIEdgeInsets.swift
Normal file
20
AutoCat2/Components/Extensions/UIEdgeInsets.swift
Normal file
@ -0,0 +1,20 @@
|
||||
//
|
||||
// UIEdgeInsets.swift
|
||||
// AutoCat2
|
||||
//
|
||||
// Created by Selim Mustafaev on 27.03.2022.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
extension UIEdgeInsets {
|
||||
|
||||
init(all: CGFloat) {
|
||||
self.init(top: all, left: all, bottom: all, right: all)
|
||||
}
|
||||
|
||||
init(vertical: CGFloat = 0, horizontal: CGFloat = 0) {
|
||||
self.init(top: vertical, left: horizontal, bottom: vertical, right: horizontal)
|
||||
}
|
||||
|
||||
}
|
||||
64
AutoCat2/Components/TableView/CoreDataSource.swift
Normal file
64
AutoCat2/Components/TableView/CoreDataSource.swift
Normal file
@ -0,0 +1,64 @@
|
||||
//
|
||||
// CoreDataSource.swift
|
||||
// AutoCat2
|
||||
//
|
||||
// Created by Selim Mustafaev on 27.03.2022.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import CoreData
|
||||
import AutoCatCore
|
||||
|
||||
protocol ConfigurableCell {
|
||||
|
||||
associatedtype Item
|
||||
|
||||
func configure(with item: Item)
|
||||
}
|
||||
|
||||
typealias ConfigurableTableViewCell = UITableViewCell & ConfigurableCell
|
||||
|
||||
class CoreDataSource<Item: NSManagedObject, Cell: ConfigurableTableViewCell>: NSObject, NSFetchedResultsControllerDelegate where Cell.Item == Item {
|
||||
|
||||
private let tableView: UITableView
|
||||
private let dataSource: UITableViewDiffableDataSource<DateSection<Item>, Item>
|
||||
private let fetchedResults: NSFetchedResultsController<Item>
|
||||
|
||||
init(tableView: UITableView, context: NSManagedObjectContext) {
|
||||
let cellIdentifier = String(describing: Cell.self)
|
||||
self.tableView = tableView
|
||||
|
||||
self.dataSource = UITableViewDiffableDataSource(tableView: tableView) { tv, ip, item in
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier,
|
||||
for: ip) as? Cell
|
||||
cell?.configure(with: item)
|
||||
return cell
|
||||
}
|
||||
|
||||
if let fetchRequest = Item.fetchRequest() as? NSFetchRequest<Item> {
|
||||
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "number", ascending: true)]
|
||||
let fr = NSFetchRequest<Item>(entityName: "Vehicle")
|
||||
fr.sortDescriptors = []
|
||||
self.fetchedResults = NSFetchedResultsController(fetchRequest: fr,
|
||||
managedObjectContext: context,
|
||||
sectionNameKeyPath: nil,
|
||||
cacheName: nil)
|
||||
} else {
|
||||
self.fetchedResults = NSFetchedResultsController()
|
||||
}
|
||||
|
||||
super.init()
|
||||
|
||||
self.tableView.dataSource = self.dataSource
|
||||
self.fetchedResults.delegate = self
|
||||
try? self.fetchedResults.performFetch()
|
||||
}
|
||||
|
||||
// MARK: - NSFetchedResultsControllerDelegate
|
||||
|
||||
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) {
|
||||
|
||||
let snapshotBridged = snapshot as NSDiffableDataSourceSnapshot<DateSection<Item>, Item>
|
||||
dataSource.apply(snapshotBridged)
|
||||
}
|
||||
}
|
||||
@ -11,9 +11,13 @@ class HistoryController: UIViewController {
|
||||
|
||||
private lazy var tableView: UITableView = {
|
||||
let table = UITableView()
|
||||
let cellIdentifier = String(describing: VehicleCell.self)
|
||||
table.register(VehicleCell.self, forCellReuseIdentifier: cellIdentifier)
|
||||
table.translatesAutoresizingMaskIntoConstraints = false
|
||||
return table
|
||||
}()
|
||||
|
||||
private var dataSource: CoreDataSource<CDVehicle, VehicleCell>?
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
@ -22,6 +26,19 @@ class HistoryController: UIViewController {
|
||||
|
||||
view.addSubview(tableView)
|
||||
tableView.pin(to: view)
|
||||
|
||||
showHistory()
|
||||
}
|
||||
|
||||
func showHistory() {
|
||||
Task {
|
||||
do {
|
||||
let storageService = try await StorageService.shared
|
||||
dataSource = CoreDataSource(tableView: tableView, context: storageService.context)
|
||||
} catch {
|
||||
show(error: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkPlateNumber(_ number: String) async {
|
||||
|
||||
60
AutoCatCore/DataSource/DateSection.swift
Normal file
60
AutoCatCore/DataSource/DateSection.swift
Normal file
@ -0,0 +1,60 @@
|
||||
//
|
||||
// DateSection.swift
|
||||
// AutoCatCore
|
||||
//
|
||||
// Created by Selim Mustafaev on 27.03.2022.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftDate
|
||||
|
||||
public class DateSection<T: Hashable> {
|
||||
|
||||
private var timestamp: Double = 0
|
||||
private var header: String
|
||||
private var elements: [T]
|
||||
|
||||
public init(timestamp: Double, items: [T]) {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateStyle = .medium
|
||||
formatter.timeStyle = .medium
|
||||
|
||||
let now = DateInRegion(Date(), region: Region.current)
|
||||
let monthStart = now.dateAtStartOf(.month)
|
||||
let weekStart = now.dateAtStartOf(.weekOfMonth)
|
||||
|
||||
let date = Date(timeIntervalSince1970: timestamp)
|
||||
let dateInRegion = DateInRegion(date, region: Region.current)
|
||||
if dateInRegion.isToday {
|
||||
self.header = NSLocalizedString("Today", comment: "")
|
||||
}
|
||||
else if dateInRegion.isYesterday {
|
||||
self.header = NSLocalizedString("Yesterday", comment: "")
|
||||
} else if dateInRegion.isAfterDate(weekStart, granularity: .day) {
|
||||
formatter.dateFormat = "EEEE"
|
||||
self.header = formatter.string(from: date)
|
||||
} else if dateInRegion.isAfterDate(monthStart, orEqual: false, granularity: .day) {
|
||||
formatter.dateStyle = .medium
|
||||
formatter.timeStyle = .none
|
||||
self.header = formatter.string(from: date)
|
||||
} else {
|
||||
formatter.dateFormat = "LLLL yyyy"
|
||||
self.header = formatter.string(from: date)
|
||||
}
|
||||
|
||||
self.timestamp = timestamp
|
||||
self.elements = items
|
||||
}
|
||||
}
|
||||
|
||||
extension DateSection: Hashable {
|
||||
|
||||
public static func == (lhs: DateSection<T>, rhs: DateSection<T>) -> Bool {
|
||||
return lhs.timestamp == rhs.timestamp && lhs.elements == rhs.elements
|
||||
}
|
||||
|
||||
public func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(self.timestamp)
|
||||
hasher.combine(self.elements)
|
||||
}
|
||||
}
|
||||
@ -7,11 +7,11 @@ protocol StorageServiceProtocol {
|
||||
func store(vehicle: Vehicle) throws -> CDVehicle
|
||||
}
|
||||
|
||||
class StorageService: StorageServiceProtocol {
|
||||
public class StorageService: StorageServiceProtocol {
|
||||
|
||||
private let container: NSPersistentCloudKitContainer
|
||||
|
||||
static var shared: StorageService {
|
||||
public static var shared: StorageService {
|
||||
get async throws {
|
||||
print("!!!!!!!!!!!!!!!!!!!!!!!!! StorageService init")
|
||||
let service = StorageService()
|
||||
@ -59,11 +59,11 @@ class StorageService: StorageServiceProtocol {
|
||||
|
||||
// MARK: - StorageServiceProtocol
|
||||
|
||||
var context: NSManagedObjectContext {
|
||||
public var context: NSManagedObjectContext {
|
||||
container.viewContext
|
||||
}
|
||||
|
||||
func store(vehicle: Vehicle) throws -> CDVehicle {
|
||||
public func store(vehicle: Vehicle) throws -> CDVehicle {
|
||||
|
||||
let cdVehicle = CDVehicle(vehicle: vehicle, context: context)
|
||||
try save()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user