added NSProgress support for migrations

This commit is contained in:
John Rommel Estropia
2015-07-12 00:49:53 +09:00
parent 33268eeea1
commit 8cfe8e2500
15 changed files with 729 additions and 406 deletions

View File

@@ -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>

View File

@@ -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()
}
}