Merged PR 260439: Fix DatePickerController dismiss bug
Added a new optional delegate method to `MSDateTimePickerDelegate` that allows a consumer to turn off modal auto-dismiss when the done button is pressed. This allows the user to validate or do asynchronous work before either dismissing themselves via `MSDateTimePicker.dismiss()`, or not dismiss altogether, effectively canceling a dismiss. If the delegate method is not implemented, auto-dismiss when done is pressed defaults to on. Also added an example of this to the demo with a switch to turn on said validation.
This commit is contained in:
Родитель
0287fbb3e2
Коммит
ea6b5773a9
|
@ -10,6 +10,9 @@ class MSDateTimePickerDemoController: DemoController {
|
|||
private let dateLabel = MSLabel(style: .headline)
|
||||
private let dateTimePicker = MSDateTimePicker()
|
||||
|
||||
private let validationSwitch = UISwitch()
|
||||
private var isValidating: Bool { return validationSwitch.isOn }
|
||||
|
||||
private var startDate: Date?
|
||||
private var endDate: Date?
|
||||
|
||||
|
@ -18,15 +21,31 @@ class MSDateTimePickerDemoController: DemoController {
|
|||
dateTimePicker.delegate = self
|
||||
dateLabel.text = "No date selected"
|
||||
dateLabel.adjustsFontSizeToFitWidth = true
|
||||
|
||||
container.addArrangedSubview(dateLabel)
|
||||
container.addArrangedSubview(createButton(title: "Show date picker", action: #selector(presentDatePicker)))
|
||||
container.addArrangedSubview(createButton(title: "Show date time picker", action: #selector(presentDateTimePicker)))
|
||||
container.addArrangedSubview(createButton(title: "Show date range picker", action: #selector(presentDateRangePicker)))
|
||||
container.addArrangedSubview(createButton(title: "Show date time range picker", action: #selector(presentDateTimeRangePicker)))
|
||||
container.addArrangedSubview(UIView())
|
||||
container.addArrangedSubview(createValidationUI())
|
||||
container.addArrangedSubview(createButton(title: "Reset selected dates", action: #selector(resetDates)))
|
||||
}
|
||||
|
||||
func createValidationUI() -> UIStackView {
|
||||
let validationRow = UIStackView()
|
||||
validationRow.axis = .horizontal
|
||||
validationRow.alignment = .center
|
||||
validationRow.distribution = .equalSpacing
|
||||
|
||||
let validationLabel = MSLabel(style: .subhead, colorStyle: .regular)
|
||||
validationLabel.text = "Validate for date in future"
|
||||
|
||||
validationRow.addArrangedSubview(validationLabel)
|
||||
validationRow.addArrangedSubview(validationSwitch)
|
||||
return validationRow
|
||||
}
|
||||
|
||||
@objc func presentDatePicker() {
|
||||
dateTimePicker.present(from: self, with: .date, startDate: startDate ?? Date())
|
||||
}
|
||||
|
@ -61,7 +80,9 @@ extension MSDateTimePickerDemoController: MSDateTimePickerDelegate {
|
|||
guard let mode = dateTimePicker.mode else {
|
||||
fatalError("Received delegate call when mode = nil")
|
||||
}
|
||||
|
||||
self.startDate = startDate
|
||||
|
||||
let compactness: MSDateStringCompactness
|
||||
if mode.singleSelection {
|
||||
if mode.includesTime {
|
||||
|
@ -79,7 +100,16 @@ extension MSDateTimePickerDemoController: MSDateTimePickerDelegate {
|
|||
}
|
||||
dateLabel.text = String.dateString(from: startDate, compactness: compactness) + " - " + String.dateString(from: endDate, compactness: compactness)
|
||||
}
|
||||
}
|
||||
|
||||
dateTimePicker.dismiss()
|
||||
func dateTimePicker(_ dateTimePicker: MSDateTimePicker, shouldEndPickingStartDate startDate: Date, endDate: Date) -> Bool {
|
||||
if isValidating && startDate.timeIntervalSinceNow < 0 {
|
||||
// Start date is in the past, cancel selection and don't dismiss the picker
|
||||
let alert = UIAlertController(title: "Error", message: "Can't pick a date in the past", preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: .default))
|
||||
presentedViewController?.present(alert, animated: true)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
B4EF53C3215AF1AB00573E8F /* MSPersona.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4EF53C2215AF1AB00573E8F /* MSPersona.swift */; };
|
||||
FD053A352224CA33009B6378 /* MSDatePickerControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD053A342224CA33009B6378 /* MSDatePickerControllerTests.swift */; };
|
||||
FD0D29D62151A3D700E8655E /* MSCardPresenterNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD0D29D52151A3D700E8655E /* MSCardPresenterNavigationController.swift */; };
|
||||
FD1FAE1B2272464B00A5DBA4 /* DateTimePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD1FAE1A2272464B00A5DBA4 /* DateTimePicker.swift */; };
|
||||
FD256C5B2183B90B00EC9588 /* MSDatePickerSelectionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD256C5A2183B90B00EC9588 /* MSDatePickerSelectionManager.swift */; };
|
||||
FD36F1A9216C0A6900CECBC6 /* MSCardPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDA1AF9221487225001AE720 /* MSCardPresentationController.swift */; };
|
||||
FD4F2A1B2148937100C437D6 /* MSPageCardPresenterController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD4F2A1A2148937100C437D6 /* MSPageCardPresenterController.swift */; };
|
||||
|
@ -176,6 +177,7 @@
|
|||
B4EF53C2215AF1AB00573E8F /* MSPersona.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSPersona.swift; sourceTree = "<group>"; };
|
||||
FD053A342224CA33009B6378 /* MSDatePickerControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSDatePickerControllerTests.swift; sourceTree = "<group>"; };
|
||||
FD0D29D52151A3D700E8655E /* MSCardPresenterNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSCardPresenterNavigationController.swift; sourceTree = "<group>"; };
|
||||
FD1FAE1A2272464B00A5DBA4 /* DateTimePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTimePicker.swift; sourceTree = "<group>"; };
|
||||
FD256C5A2183B90B00EC9588 /* MSDatePickerSelectionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSDatePickerSelectionManager.swift; sourceTree = "<group>"; };
|
||||
FD4F2A1A2148937100C437D6 /* MSPageCardPresenterController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSPageCardPresenterController.swift; sourceTree = "<group>"; };
|
||||
FD4F2A1F214AE20400C437D6 /* MSDatePickerController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MSDatePickerController.swift; sourceTree = "<group>"; };
|
||||
|
@ -542,6 +544,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
FD77752F21A490BA00033D58 /* MSDateTimePicker.swift */,
|
||||
FD1FAE1A2272464B00A5DBA4 /* DateTimePicker.swift */,
|
||||
FD4F2A1C214ADBBF00C437D6 /* Date Picker */,
|
||||
FD5C8C2A2190C3470063562C /* Date Time Picker */,
|
||||
);
|
||||
|
@ -833,6 +836,7 @@
|
|||
B46D3F932151D95F0029772C /* MSPersonaCell.swift in Sources */,
|
||||
B444D6B12181403C0002B4D4 /* UITableViewCell+Extension.swift in Sources */,
|
||||
FD777529219E3F6C00033D58 /* MSDayOfMonth.swift in Sources */,
|
||||
FD1FAE1B2272464B00A5DBA4 /* DateTimePicker.swift in Sources */,
|
||||
A54D97DA217A5FC10072681A /* CALayer+Extensions.swift in Sources */,
|
||||
FD777527219E305F00033D58 /* Locale+Extensions.swift in Sources */,
|
||||
B483323721DEB5A00022B4CC /* MSTouchForwardingView.swift in Sources */,
|
||||
|
|
|
@ -38,5 +38,9 @@ public class OfficeUIFabricFramework: NSObject {
|
|||
titleAttributes = barButtonItem.titleTextAttributes(for: .normal) ?? [:]
|
||||
titleAttributes[.font] = MSFonts.body
|
||||
barButtonItem.setTitleTextAttributes(titleAttributes, for: .normal)
|
||||
|
||||
// UISwitch
|
||||
let `switch` = UISwitch.appearance()
|
||||
`switch`.onTintColor = MSColors.primary
|
||||
}
|
||||
}
|
||||
|
|
|
@ -227,7 +227,7 @@ class MSDatePickerController: UIViewController, DateTimePicker {
|
|||
}
|
||||
|
||||
@objc private func handleDidTapDone() {
|
||||
delegate?.dateTimePicker(self, didPickStartDate: startDate, endDate: endDate)
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -161,11 +161,6 @@ class MSDateTimePickerController: UIViewController, DateTimePicker {
|
|||
}
|
||||
}
|
||||
|
||||
private func dismiss() {
|
||||
delegate?.dateTimePicker(self, didPickStartDate: startDate, endDate: endDate)
|
||||
presentingViewController?.dismiss(animated: true)
|
||||
}
|
||||
|
||||
@objc private func handleDidSelectDate(_ datePicker: MSDateTimePickerView) {
|
||||
switch mode {
|
||||
case .single:
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// MARK: DateTimePicker
|
||||
|
||||
protocol DateTimePicker: class {
|
||||
var startDate: Date { get set }
|
||||
var endDate: Date { get set }
|
||||
var delegate: DateTimePickerDelegate? { get set }
|
||||
}
|
||||
|
||||
extension DateTimePicker where Self: UIViewController {
|
||||
func dismiss() {
|
||||
if delegate?.dateTimePicker(self, shouldEndPickingStartDate: startDate, endDate: endDate) ?? true {
|
||||
delegate?.dateTimePicker(self, didPickStartDate: startDate, endDate: endDate)
|
||||
presentingViewController?.dismiss(animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - DateTimePickerDelegate
|
||||
|
||||
protocol DateTimePickerDelegate: class {
|
||||
func dateTimePicker(_ dateTimePicker: DateTimePicker, didPickStartDate startDate: Date, endDate: Date)
|
||||
func dateTimePicker(_ dateTimePicker: DateTimePicker, didSelectStartDate startDate: Date, endDate: Date)
|
||||
func dateTimePicker(_ dateTimePicker: DateTimePicker, shouldEndPickingStartDate startDate: Date, endDate: Date) -> Bool
|
||||
}
|
|
@ -22,21 +22,8 @@ import Foundation
|
|||
@objc public protocol MSDateTimePickerDelegate: class {
|
||||
/// Allows a class to be notified when a user confirms their selected date
|
||||
func dateTimePicker(_ dateTimePicker: MSDateTimePicker, didPickStartDate startDate: Date, endDate: Date)
|
||||
}
|
||||
|
||||
// MARK: - DateTimePicker
|
||||
|
||||
protocol DateTimePicker: class {
|
||||
var startDate: Date { get set }
|
||||
var endDate: Date { get set }
|
||||
var delegate: DateTimePickerDelegate? { get set }
|
||||
}
|
||||
|
||||
// MARK: - DateTimePickerDelegate
|
||||
|
||||
protocol DateTimePickerDelegate: class {
|
||||
func dateTimePicker(_ dateTimePicker: DateTimePicker, didPickStartDate startDate: Date, endDate: Date)
|
||||
func dateTimePicker(_ dateTimePicker: DateTimePicker, didSelectStartDate startDate: Date, endDate: Date)
|
||||
/// Allows for some validation and cancellation of picking behavior, including the dismissal of DateTimePicker classes when Done is pressed. If false is returned, the dismissal and `didPickStartDate` delegate calls will not occur. This is not called when dismissing the modal without selection, such as when tapping outside to dismiss.
|
||||
@objc optional func dateTimePicker(_ dateTimePicker: MSDateTimePicker, shouldEndPickingStartDate startDate: Date, endDate: Date) -> Bool
|
||||
}
|
||||
|
||||
// MARK: - MSDateTimePicker
|
||||
|
@ -156,4 +143,8 @@ extension MSDateTimePicker: DateTimePickerDelegate {
|
|||
picker.endDate = endDate
|
||||
}
|
||||
}
|
||||
|
||||
func dateTimePicker(_ dateTimePicker: DateTimePicker, shouldEndPickingStartDate startDate: Date, endDate: Date) -> Bool {
|
||||
return delegate?.dateTimePicker?(self, shouldEndPickingStartDate: startDate, endDate: endDate) ?? true
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче