可展开日期选择器 0.10.0

可展开日期选择器 0.10.0

测试已测试
Lang语言 SwiftSwift
许可证 MIT
发布上次发布2017年11月
SwiftSwift 版本3.0.2
SPM支持 SPM

Scott Grosch 维护。



  • Scott Grosch

使用方法

可展开日期选择器是一个用 Swift 编写的库,它使显示下拉 UIDatePicker 变得更加简单。它还包括
一个用于选择应与日期一起使用的时区的表格行,这在创建日历项时特别有用。

对于您想要点击以便出现和消失两个新行的单元格,您只需添加 ShowsDatePicker 协议即可。
该协议中不需要实现任何内容,它只需要在 UITableViewCell 子类中存在。如果您只想有一个简单的 "右细节" 细胞,
您可以使用提供的 ExpandableDatePickerSelectionCell 类。

Demo

将内容添加到现有的视图控制器中

  • 导入 ExpandableDatePicker 模块
  • 将 ExpandableDatePicker 协议添加到您的视图控制器中
  • 添加协议定义的三个变量(TableView 可能已经存在...)
  • 将您的 UITableViewDelegateUITableViewDataSource 中的所有 indexPath 实例替换为 edpUpdatedModelIndexPath(for:)

viewDidLoad()

调用 tableView.registerExpandableDatePicker()。这注册了内部使用的单元格,并将 UITableViewestimatedRowHeight 设置为 44.0,将 rowHeight 设置为 UITableViewAutomaticDimension,因为 UIDatePicker 需要可展开的单元格。

tableView(_:cellForRowAt:)

此方法的开头应先检查 edpShouldShowDatePicker(at:)edpShouldShowTimeZoneRow(at:),然后根据返回值进行适当的操作。下面是全面的示例。

对于应该返回当前日期值和点击以展开日期选择器和时区选择器的行,除非您需要更定制的选项,否则应返回 ExpandableDatePickerSelectionCell。简单地获取一个可重复使用的单元格,设置 detailTextLabel 并返回单元格。下面有示例。

tableView(_:accessoryButtonTappedForRowWith:) 和 tableView(_:didSelectRowAt:)

您绝对需要先调用 edpTableCellWasSelected(at:) 并检查输出。您将返回 nil 或更新的 IndexPath 值。如果它是 nil,说明他们点击了用于选择时区的行。您只需将 ExpandableDatePickerTimeZoneTableViewController(哎呀!)推送到您的 UINavigationController 上。您的回调将提供一个 TimeZone 对象,您应将其存储在本地数据模型中,然后更新您的 UITableView。如果您需要将导航栏中的段放置为不同于 Apple 默认使用的颜色,则可以将可选的 segmentTintColor 作为参数传递给构造函数。

tableView(_:numberOfRowsInSection)

edpDatePickerRowsShowing 添加到您的输出中。这将根据额外行是否显示而分别为 0、1 或 2。

示例实现

您可以将以下类作为起点,因为它实现了协议所需的全部组件。

import UIKit
import ExpandableDatePicker

class ViewController: UITableViewController, ExpandableDatePicker {
    // Not used directly by you, but is part of the protocol so the framework can use it.
    var edpIndexPath: IndexPath?

    // Whether or not the expansion should include a TimeZone row selector.
    var edpShowTimeZoneRow = true

    fileprivate var rowThatTogglesDatePicker: Int!

    fileprivate var selectedDate = Date()
    fileprivate var selectedTimeZone = TimeZone.autoupdatingCurrent

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.registerExpandableDatePicker()
    }
}

// MARK: - UITableViewDataSource
extension ViewController {
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if edpShouldShowDatePicker(at: indexPath) {
            let cell = ExpandableDatePickerCell.reusableCell(for: indexPath, in: tableView)
            cell.onDateChanged = {
                [unowned self] date in
                self.selectedDate = date
                self.tableView.reloadRows(at: [self.edpLabelIndexPath!], with: .automatic)
            }

            cell.datePicker.date = selectedDate

            return cell
        } else if edpShouldShowTimeZoneRow(at: indexPath) {
            return ExpandableDatePickerTimeZoneCell.reusableCell(for: indexPath, in: tableView, timeZone: selectedTimeZone)
        }

        let modelIndexPath = edpUpdatedModelIndexPath(for: indexPath)

        if modelIndexPath.row == rowThatExpandsToDatePicker {
            let cell = ExpandableDatePickerSelectionCell.reusableCell(for: indexPath, in: tableView)
            cell.detailTextLabel!.text = DateFormatter.localizedString(from: selectedDate, dateStyle: .short, timeStyle: .none)

            return cell
        }

        let cell = tableView.dequeueReusableCell(withIdentifier: "normal", for: indexPath)
        cell.textLabel!.text = tableData[modelIndexPath.row]
        return cell
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return tableData.count + edpDatePickerRowsShowing
    }
}

// MARK: - UITableViewDelegate
extension ViewController {
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        guard let modelIndexPath = edpTableCellWasSelected(at: indexPath) else {
            // If tableCellWasSelected(at:) returns nil, they clicked on the time zone selector row.
            let vc = ExpandableDatePickerTimeZoneTableViewController {
                [unowned self] timeZone in
                self.selectedTimeZone = timeZone
                tableView.reloadRows(at: [indexPath], with: .automatic)
            }

            navigationController!.pushViewController(vc, animated: true)

            return
        }

        // modelIndexPath is the new indexPath you use for which row was selected.
    }
}

子类化

如果您想子类化 ExpandableDatePickerCellExpandableDatePickerTimeZoneCell,只需在调用 registerExpandableDatePicker() 后自行注册单元格即可。
这两个类都提供了一个静态 identifier 属性,您可以使用它来注册您的单元格。

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.registerExpandableDatePicker()

        tableView.register(MyCoolTimeZoneSubclassCell.self, forCellReuseIdentifier: ExpandableDatePickerTimeZoneCell.identifier)
    }

安装

CocoaPods

CocoaPods 是 Cocoa 项目的依赖关系管理器。您可以使用以下命令安装它:

$ gem install cocoapods

要使用 CocoaPods 将 ExpandableDatePicker 集成到您的 Xcode 项目中,请在您的 Podfile 中指定它

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'
use_frameworks!

target '<Your Target Name>' do
    pod 'ExpandableDatePicker'
end

然后,运行以下命令

$ pod install