mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-03-25 19:01:16 +01:00
added NSProgress support for migrations
This commit is contained in:
@@ -136,31 +136,54 @@
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Organism" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="C06-r4-27K">
|
||||
<rect key="frame" x="20" y="20" width="560" height="26.5"/>
|
||||
<rect key="frame" x="20" y="90" width="560" height="26.5"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="22"/>
|
||||
<color key="textColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="attributes" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fXh-OL-4Qb">
|
||||
<rect key="frame" x="20" y="70" width="560" height="20.5"/>
|
||||
<rect key="frame" x="20" y="140" width="560" height="20.5"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="17"/>
|
||||
<color key="textColor" red="0.92549019610000005" green="0.94117647059999998" blue="0.94509803920000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="Hwa-fO-fC5">
|
||||
<rect key="frame" x="20" y="20" width="560" height="29"/>
|
||||
<segments>
|
||||
<segment title="First"/>
|
||||
<segment title="Second"/>
|
||||
<segment title=""/>
|
||||
</segments>
|
||||
<color key="tintColor" cocoaTouchSystemColor="tableCellGroupedBackgroundColor"/>
|
||||
<connections>
|
||||
<action selector="segmentedControlValueChanged:" destination="hJK-5I-1TQ" eventType="valueChanged" id="jNH-gx-mOg"/>
|
||||
</connections>
|
||||
</segmentedControl>
|
||||
<progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" progress="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="H1P-2g-DHX">
|
||||
<rect key="frame" x="20" y="68" width="560" height="2"/>
|
||||
<color key="progressTintColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="trackTintColor" white="1" alpha="0.20000000000000001" colorSpace="calibratedWhite"/>
|
||||
</progressView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.20392156859999999" green="0.28627450980000002" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="H1P-2g-DHX" firstAttribute="leading" secondItem="5Hd-jr-1nW" secondAttribute="leading" constant="20" id="2Nf-U0-bTq"/>
|
||||
<constraint firstItem="fXh-OL-4Qb" firstAttribute="top" secondItem="C06-r4-27K" secondAttribute="bottom" constant="23.5" id="6d1-A5-Zc5"/>
|
||||
<constraint firstAttribute="trailing" secondItem="C06-r4-27K" secondAttribute="trailing" constant="20" id="DC3-u7-f9M"/>
|
||||
<constraint firstItem="Hwa-fO-fC5" firstAttribute="leading" secondItem="5Hd-jr-1nW" secondAttribute="leading" constant="20" id="CDZ-qV-3eK"/>
|
||||
<constraint firstItem="H1P-2g-DHX" firstAttribute="top" secondItem="Hwa-fO-fC5" secondAttribute="bottom" constant="20" id="Dcs-Vv-Xfv"/>
|
||||
<constraint firstItem="fXh-OL-4Qb" firstAttribute="leading" secondItem="C06-r4-27K" secondAttribute="leading" id="SnQ-Ra-KkU"/>
|
||||
<constraint firstItem="C06-r4-27K" firstAttribute="top" secondItem="5Hd-jr-1nW" secondAttribute="top" constant="20" id="abW-Z0-uln"/>
|
||||
<constraint firstItem="Hwa-fO-fC5" firstAttribute="top" secondItem="5Hd-jr-1nW" secondAttribute="top" constant="20" id="Zo1-kW-kAw"/>
|
||||
<constraint firstItem="C06-r4-27K" firstAttribute="top" secondItem="H1P-2g-DHX" secondAttribute="bottom" constant="20" id="bBW-Bn-oeN"/>
|
||||
<constraint firstAttribute="trailing" secondItem="fXh-OL-4Qb" secondAttribute="trailing" constant="20" id="mhR-0c-i0n"/>
|
||||
<constraint firstAttribute="trailing" secondItem="C06-r4-27K" secondAttribute="trailing" constant="20" id="s0c-XG-e70"/>
|
||||
<constraint firstAttribute="trailing" secondItem="H1P-2g-DHX" secondAttribute="trailing" constant="20" id="swp-18-f5e"/>
|
||||
<constraint firstItem="C06-r4-27K" firstAttribute="top" secondItem="Hwa-fO-fC5" secondAttribute="bottom" constant="20" id="tYt-wb-Lk8"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Hwa-fO-fC5" secondAttribute="trailing" constant="20" id="ujX-gH-Wlm"/>
|
||||
<constraint firstItem="C06-r4-27K" firstAttribute="leading" secondItem="5Hd-jr-1nW" secondAttribute="leading" constant="20" id="yiG-c9-BZg"/>
|
||||
</constraints>
|
||||
<variation key="default">
|
||||
<mask key="constraints">
|
||||
<exclude reference="DC3-u7-f9M"/>
|
||||
<exclude reference="tYt-wb-Lk8"/>
|
||||
</mask>
|
||||
</variation>
|
||||
</view>
|
||||
@@ -206,6 +229,8 @@
|
||||
<simulatedToolbarMetrics key="simulatedBottomBarMetrics"/>
|
||||
<connections>
|
||||
<outlet property="organismLabel" destination="fXh-OL-4Qb" id="shX-fK-haw"/>
|
||||
<outlet property="progressView" destination="H1P-2g-DHX" id="Asy-fE-gXI"/>
|
||||
<outlet property="segmentedControl" destination="Hwa-fO-fC5" id="myL-tO-4ah"/>
|
||||
<outlet property="titleLabel" destination="C06-r4-27K" id="zQr-YC-moe"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
|
||||
@@ -19,7 +19,39 @@ class MigrationsDemoViewController: UITableViewController {
|
||||
override func viewDidLoad() {
|
||||
|
||||
super.viewDidLoad()
|
||||
self.selectModelVersion(self.models.first!)
|
||||
|
||||
let models = self.models
|
||||
if let segmentedControl = self.segmentedControl {
|
||||
|
||||
for (index, model) in models.enumerate() {
|
||||
|
||||
segmentedControl.setTitle(
|
||||
model.label,
|
||||
forSegmentAtIndex: index
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
let dataStack = DataStack(modelName: "MigrationDemo")
|
||||
do {
|
||||
|
||||
let migrations = try dataStack.requiredMigrationsForSQLiteStore(
|
||||
fileName: "MigrationDemo.sqlite"
|
||||
)
|
||||
|
||||
let storeVersion = migrations.first?.sourceVersion ?? dataStack.modelVersion
|
||||
for model in models {
|
||||
|
||||
if model.version == storeVersion {
|
||||
|
||||
self.selectModelVersion(model, animated: false)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
catch _ { }
|
||||
|
||||
self.selectModelVersion(self.models.first!, animated: false)
|
||||
}
|
||||
|
||||
|
||||
@@ -47,21 +79,23 @@ class MigrationsDemoViewController: UITableViewController {
|
||||
|
||||
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
|
||||
|
||||
self.selectModelVersion(self.models[indexPath.row])
|
||||
self.selectModelVersion(self.models[indexPath.row], animated: true)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private typealias ModelMetadata = (version: String, entityType: AnyClass, migrationChain: MigrationChain)
|
||||
private typealias ModelMetadata = (label: String, version: String, entityType: AnyClass, migrationChain: MigrationChain)
|
||||
|
||||
private let models: [ModelMetadata] = [
|
||||
(
|
||||
label: "Model V1",
|
||||
version: "MigrationDemo",
|
||||
entityType: OrganismV1.self,
|
||||
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
|
||||
),
|
||||
(
|
||||
label: "Model V2",
|
||||
version: "MigrationDemoV2",
|
||||
entityType: OrganismV2.self,
|
||||
migrationChain: [
|
||||
@@ -70,6 +104,7 @@ class MigrationsDemoViewController: UITableViewController {
|
||||
]
|
||||
),
|
||||
(
|
||||
label: "Model V3",
|
||||
version: "MigrationDemoV3",
|
||||
entityType: OrganismV3.self,
|
||||
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
|
||||
@@ -81,6 +116,8 @@ class MigrationsDemoViewController: UITableViewController {
|
||||
|
||||
@IBOutlet private dynamic weak var titleLabel: UILabel?
|
||||
@IBOutlet private dynamic weak var organismLabel: UILabel?
|
||||
@IBOutlet private dynamic weak var segmentedControl: UISegmentedControl?
|
||||
@IBOutlet private dynamic weak var progressView: UIProgressView?
|
||||
|
||||
@IBAction private dynamic func mutateBarButtonTapped(sender: AnyObject?) {
|
||||
|
||||
@@ -93,11 +130,21 @@ class MigrationsDemoViewController: UITableViewController {
|
||||
|
||||
transaction.commit()
|
||||
}
|
||||
self.updateDisplay()
|
||||
self.updateDisplayWithCompletion()
|
||||
}
|
||||
}
|
||||
|
||||
private func selectModelVersion(model: ModelMetadata) {
|
||||
@IBAction private dynamic func segmentedControlValueChanged(sender: AnyObject?) {
|
||||
|
||||
guard let index = self.segmentedControl?.selectedSegmentIndex else {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
self.selectModelVersion(self.models[index], animated: true)
|
||||
}
|
||||
|
||||
private func selectModelVersion(model: ModelMetadata, animated: Bool) {
|
||||
|
||||
if self.organism?.entity.managedObjectClassName == "\(model.entityType)" {
|
||||
|
||||
@@ -112,8 +159,8 @@ class MigrationsDemoViewController: UITableViewController {
|
||||
migrationChain: model.migrationChain
|
||||
)
|
||||
|
||||
self.setEnabled(false)
|
||||
dataStack.addSQLiteStore(
|
||||
self.setEnabled(false, animated: animated)
|
||||
let progress = try! dataStack.addSQLiteStore(
|
||||
fileName: "MigrationDemo.sqlite",
|
||||
completion: { [weak self] (result) -> Void in
|
||||
|
||||
@@ -124,7 +171,7 @@ class MigrationsDemoViewController: UITableViewController {
|
||||
|
||||
guard case .Success = result else {
|
||||
|
||||
strongSelf.setEnabled(true)
|
||||
strongSelf.setEnabled(true, animated: animated)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -137,32 +184,44 @@ class MigrationsDemoViewController: UITableViewController {
|
||||
|
||||
dataStack.beginSynchronous { (transaction) -> Void in
|
||||
|
||||
let organism = transaction.create(Into(model.entityType))
|
||||
(organism as! OrganismProtocol).mutate()
|
||||
for _ in 0 ..< 100000 {
|
||||
|
||||
let organism = transaction.create(Into(model.entityType))
|
||||
(organism as! OrganismProtocol).mutate()
|
||||
}
|
||||
|
||||
transaction.commit()
|
||||
}
|
||||
strongSelf.organism = dataStack.fetchOne(From(model.entityType))!
|
||||
}
|
||||
|
||||
strongSelf.updateDisplay()
|
||||
strongSelf.updateDisplayWithCompletion()
|
||||
|
||||
let indexOfModel = strongSelf.models.map { $0.version }.indexOf(model.version)!
|
||||
strongSelf.tableView.selectRowAtIndexPath(
|
||||
NSIndexPath(
|
||||
forRow: strongSelf.models.map { $0.version }.indexOf(model.version)!,
|
||||
inSection: 0
|
||||
),
|
||||
NSIndexPath(forRow: indexOfModel, inSection: 0),
|
||||
animated: false,
|
||||
scrollPosition: .None
|
||||
)
|
||||
strongSelf.setEnabled(true)
|
||||
strongSelf.segmentedControl?.selectedSegmentIndex = indexOfModel
|
||||
strongSelf.setEnabled(true, animated: animated)
|
||||
}
|
||||
)
|
||||
|
||||
if let progress = progress {
|
||||
|
||||
self.updateDisplayWithProgress(progress)
|
||||
progress.setProgressHandler { [weak self] (progress) -> Void in
|
||||
|
||||
self?.updateDisplayWithProgress(progress)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setEnabled(enabled: Bool) {
|
||||
func setEnabled(enabled: Bool, animated: Bool) {
|
||||
|
||||
UIView.animateKeyframesWithDuration(
|
||||
0.2,
|
||||
animated ? 0.2 : 0,
|
||||
delay: 0,
|
||||
options: .BeginFromCurrentState,
|
||||
animations: { () -> Void in
|
||||
@@ -182,7 +241,14 @@ class MigrationsDemoViewController: UITableViewController {
|
||||
)
|
||||
}
|
||||
|
||||
func updateDisplay() {
|
||||
func updateDisplayWithProgress(progress: NSProgress) {
|
||||
|
||||
self.progressView?.setProgress(Float(progress.fractionCompleted), animated: true)
|
||||
self.titleLabel?.text = "Migrating: \(progress.localizedDescription)"
|
||||
self.organismLabel?.text = "Incremental step \(progress.localizedAdditionalDescription)"
|
||||
}
|
||||
|
||||
func updateDisplayWithCompletion() {
|
||||
|
||||
var lines = [String]()
|
||||
var organismType = ""
|
||||
@@ -193,11 +259,12 @@ class MigrationsDemoViewController: UITableViewController {
|
||||
let value: AnyObject = organism.valueForKey(property.name) ?? NSNull()
|
||||
lines.append("\(property.name): \(value)")
|
||||
}
|
||||
organismType = "\(objc_getClass(organism.entity.managedObjectClassName))"
|
||||
organismType = organism.entity.managedObjectClassName
|
||||
}
|
||||
|
||||
self.titleLabel?.text = organismType
|
||||
self.organismLabel?.text = "\n".join(lines)
|
||||
self.progressView?.progress = 0
|
||||
self.tableView.tableHeaderView?.setNeedsLayout()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user