swift 自定义DatePacker

import Foundationenum AppDatePickerStyle {case KDatePickerDate //年月日case KDatePickerTime //年月日时分case kDatePickerMonth // 年月case KDatePickerSecond //秒}class AppDatePicker: UIView {private let jk_rootView = UIApplication.shared.keyWindow!private var jk_backgroundView: UIView!private var confirmHandler: (( _ year: Int, _ month: Int,_ day: Int) -> Void)?//选择的回调var cancelHandler: (() -> Void)?//取消的回调/// 选择器类型fileprivate var datePickerStyle: AppDatePickerStyle!/// 时间数据fileprivate var unitFlags:Set<Calendar.Component>!var pickerView = UIPickerView()//数据相关fileprivate var yearRange = 30 + 1000//年的范围fileprivate var dayRange = 0 //fileprivate var startYear = 0// 当前选中日期fileprivate var selectedYear = 0;fileprivate var selectedMonth = 0;fileprivate var selectedDay = 0;fileprivate var selectedHour = 0;fileprivate var selectedMinute = 0;fileprivate var selectedSecond = 0;override init(frame: CGRect) {super.init(frame: frame)}convenience init(title: String = "选择日期", type: AppDatePickerStyle, confirmHandler: @escaping (_ year:Int,_ month:Int,_ day:Int) -> Void) {self.init(frame: .zero)configUI()self.confirmHandler = confirmHandlerjk_titleLabel.text = titleinitDatePickerWithType(type: type)}convenience init(title: String = "选择日期", year: Int, month: Int, day: Int, confirmHandler: @escaping (_ year:Int,_ month:Int,_ day:Int) -> Void) {self.init(frame: .zero)configUI()self.confirmHandler = confirmHandlerjk_titleLabel.text = titleinitDatePickerWithType(type: .kDatePickerMonth, date: year == -1 ? nil:Date.dateFor("\(year)-\(month)-\(day)"))}private func getHeight() -> CGFloat {return CGFloat(56 + 4 * 50 + 56)}// MARK: - UIButtonAction@objc private func confimBtnAction() {if let holder = confirmHandler {holder(selectedYear, selectedMonth, selectedDay)}hide()}// MARK: - configUIfunc configUI() {// 防止多个 AlertView 重复显示if jk_rootView.subviews.filter({ $0.isKind(of: AppDatePicker.self) }).count > 0 { return }jk_backgroundView = UIView()jk_backgroundView.backgroundColor = UIColor.black.withAlphaComponent(0)jk_rootView.addSubview(jk_backgroundView)jk_rootView.addSubview(self)addSubview(jk_backView)jk_backView.addSubview(cornerBackView)cornerBackView.addSubview(jk_titleLabel)cornerBackView.addSubview(pickerView)cornerBackView.addSubview(jk_cancelBtn)cornerBackView.addSubview(conformBtn)cornerBackView.addSubview(verticalLineView)jk_backgroundView.snp.makeConstraints { (make) inmake.edges.equalTo(jk_rootView)}let height = getHeight()snp.makeConstraints { make inmake.left.right.equalToSuperview()make.height.equalTo(height + Size.safeAreaBottomGap)make.bottom.equalTo(height + Size.safeAreaBottomGap)}jk_backView.snp.makeConstraints { make inmake.edges.equalToSuperview()}cornerBackView.snp.makeConstraints { make inmake.left.top.right.equalToSuperview()make.height.equalTo(height)}jk_titleLabel.snp.makeConstraints { make inmake.height.equalTo(40)make.top.equalTo(16)make.left.right.equalToSuperview()}pickerView.snp.makeConstraints { make inmake.top.equalTo(jk_titleLabel.snp.bottom)make.left.right.equalToSuperview()make.height.equalTo(50 * 4)}jk_cancelBtn.snp.makeConstraints { make inmake.height.equalTo(56)make.top.equalTo(pickerView.snp.bottom)make.left.equalToSuperview()make.width.equalToSuperview().multipliedBy(0.5)}conformBtn.snp.makeConstraints { make inmake.right.equalToSuperview()make.centerY.height.width.equalTo(jk_cancelBtn)}verticalLineView.snp.makeConstraints { make inmake.height.equalTo(20)make.width.equalTo(1)make.centerY.equalTo(jk_cancelBtn)make.centerX.equalToSuperview()}self.jk_rootView.layoutIfNeeded()let tapGR = UITapGestureRecognizer.init(target: self, action: #selector(hideAction))jk_backgroundView.addGestureRecognizer(tapGR)jk_cancelBtn.addTarget(self, action: #selector(hideAction), for: .touchUpInside)conformBtn.addTarget(self, action: #selector(confimBtnAction), for: .touchUpInside)pickerView.delegate = selfpickerView.dataSource = self}private lazy var jk_backView: UIView = {let jk_backView = UIView()jk_backView.backgroundColor = .whitereturn jk_backView}()private lazy var cornerBackView: UIView = {let cornerBackView = UIView()cornerBackView.backgroundColor = .whitereturn cornerBackView}()private lazy var jk_titleLabel: UILabel = {let jk_titleLabel = UILabel()jk_titleLabel.textAlignment = .centerjk_titleLabel.font = kSetPingFangMedium(18)return jk_titleLabel}()private lazy var jk_cancelBtn: UIButton = {let jk_cancelBtn = UIButton()jk_cancelBtn.setTitle("取消", for: .normal)jk_cancelBtn.setTitleColor( .black, for: .normal)return jk_cancelBtn}()private lazy var verticalLineView: UIView = {let verticalLineView = UIView()verticalLineView.backgroundColor = .jky_viewBackgroundColorreturn verticalLineView}()private lazy var conformBtn: UIButton = {let conformBtn = UIButton()conformBtn.setTitle("确定", for: .normal)conformBtn.setTitleColor( .black, for: .normal)return conformBtn}()required init?(coder aDecoder: NSCoder) {super.init(coder: aDecoder)fatalError("init(coder:) has not been implemented")}
}//MARK:初始化数据
extension AppDatePicker {fileprivate func initDatePickerWithType(type: AppDatePickerStyle, date: Date? = nil) {datePickerStyle = typelet calendar0 = Calendar.init(identifier: .gregorian)//公历var comps = DateComponents()//一个封装了具体年月日、时秒分、周、季度等的类unitFlags = [.year , .month , .day]switch datePickerStyle {case .KDatePickerDate:breakcase .KDatePickerTime:unitFlags = [.year , .month , .day , .hour , .minute ]case .kDatePickerMonth:unitFlags = [.year , .month]case .KDatePickerSecond:unitFlags = [.year , .month , .day , .hour , .minute ,.second]default:break}// comps = calendar0.dateComponents(unitFlags, from: date != nil ? date! : Date())comps = calendar0.dateComponents(unitFlags, from: date != nil ? date!:Date())startYear = comps.year! - 100dayRange = self.isAllDay(year: startYear, month: 1)yearRange = 30 + 1000;selectedYear = comps.year!;selectedMonth = comps.month!;self.pickerView.selectRow(selectedYear - startYear, inComponent: 0, animated: true)self.pickerView.selectRow(selectedMonth - 1, inComponent: 1, animated: true)if datePickerStyle != .kDatePickerMonth {selectedDay = comps.day!;self.pickerView.selectRow(selectedDay - 1, inComponent: 2, animated: true)}switch datePickerStyle {case .KDatePickerDate:breakcase .KDatePickerTime:selectedHour = comps.hour!;selectedMinute = comps.minute!;self.pickerView.selectRow(selectedHour , inComponent: 3, animated: true)self.pickerView.selectRow(selectedMinute , inComponent: 4, animated: true)case .KDatePickerSecond:selectedHour = comps.hour!;selectedMinute = comps.minute!;selectedSecond = comps.second!;self.pickerView.selectRow(selectedHour , inComponent: 3, animated: true)self.pickerView.selectRow(selectedMinute , inComponent: 4, animated: true)self.pickerView.selectRow(selectedSecond, inComponent: 5, animated: true)default:break}self.pickerView.reloadAllComponents()}//MARK:计算每个月有多少天fileprivate func isAllDay(year:Int, month:Int) -> Int {var day:Int = 0switch(month){case 1,3,5,7,8,10,12:day = 31case 4,6,9,11:day = 30case 2:if(((year%4==0)&&(year%100==0))||(year%400==0)){day=29}else{day=28;}default:break;}return day;}}extension AppDatePicker : UIPickerViewDelegate,UIPickerViewDataSource {//返回UIPickerView当前的列数func numberOfComponents(in pickerView: UIPickerView) -> Int {return unitFlags == nil ? 0 : unitFlags.count}//确定每一列返回的东西func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {switch component {case 0:return yearRangecase 1:return 12case 2:return dayRangecase 3:return 24case 4:return 60case 5:return 60default:return 0}}func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {return 45}//返回一个视图,用来设置pickerView的每行显示的内容。func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {let label = UILabel(frame: CGRect(x: screenWidth * CGFloat(component) / 6 , y: 0, width: screenWidth/6, height: 50))label.font = UIFont.boldSystemFont(ofSize: CGFloat(16))label.tag = component*100+rowlabel.textAlignment = .centerswitch component {case 0:label.frame=CGRect(x:5, y:0,width:screenWidth/4.0, height:50);label.text="\(self.startYear + row)年";case 1:label.frame=CGRect(x:screenWidth/4.0, y:0,width:screenWidth/8.0, height:50);label.text="\(row + 1)月";case 2:label.frame=CGRect(x:screenWidth*3/8, y:0,width:screenWidth/8.0, height:50);label.text="\(row + 1)日";case 3:label.textAlignment = .rightlabel.text="\(row )时";case 4:label.textAlignment = .rightlabel.text="\(row )分";case 5:label.textAlignment = .rightlabel.frame=CGRect(x:screenWidth/6, y:0,width:screenWidth/6.0 - 5, height:50);label.text="\(row )秒";default:label.text="\(row )秒";}return label}//当点击UIPickerView的某一列中某一行的时候,就会调用这个方法func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {switch component {case 0:self.selectedYear = self.startYear + rowself.dayRange = self.isAllDay(year: self.startYear, month: self.selectedMonth)if datePickerStyle != .kDatePickerMonth {self.pickerView.reloadComponent(2)}case 1:self.selectedMonth = row + 1self.dayRange = self.isAllDay(year: self.startYear, month: self.selectedMonth)if datePickerStyle != .kDatePickerMonth {self.pickerView.reloadComponent(2)}case 2:selectedDay = row + 1case 3:selectedHour = rowcase 4:selectedMinute = rowcase 5:selectedSecond = rowdefault:selectedSecond = row}}}extension AppDatePicker: UIGestureRecognizerDelegate {func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {if let view = touch.view, view.isDescendant(of: pickerView) {return false}return true}func show() {self.jk_backView.layerCornerRadius(16, [.topLeft,.topRight])UIView.animate(withDuration: 0.2, animations: {self.jk_backgroundView.backgroundColor = UIColor.black.withAlphaComponent(0.5)self.snp.updateConstraints { make inmake.bottom.equalTo(0)}self.jk_rootView.layoutIfNeeded()})}@objc private func hideAction() {if let holder = cancelHandler {holder()}hide()}private func hide(completion: (() -> Void)? = nil) {UIView.animate(withDuration: 0.2, animations: {self.jk_backgroundView.backgroundColor = UIColor.black.withAlphaComponent(0)self.snp.updateConstraints { make inmake.bottom.equalTo(self.getHeight() + Size.safeAreaBottomGap)}self.jk_rootView.layoutIfNeeded()}) { finished inguard finished else { return }self.removeFromSuperview()self.jk_backgroundView.removeFromSuperview()}}}相关文章:
swift 自定义DatePacker
import Foundationenum AppDatePickerStyle {case KDatePickerDate //年月日case KDatePickerTime //年月日时分case kDatePickerMonth // 年月case KDatePickerSecond //秒}class AppDatePicker: UIView {private let jk_rootView UIApplication.shared.keyWindow!pri…...
MySQL事务,锁,MVCC总结
mysql中最重要的就是事务,其四大特性让我们维持了数据的平衡,一致。那么事务究竟是什么,与什么相关,他的使用步骤,以及使用过程中我们会遇到什么问题呢?下面我们一起学习交流! 1.MySQL的存储引擎ÿ…...
24/8/7 算法笔记 支持向量机回归问题天猫双十一
import numpy as np from sklearn.svm import SVR import matplotlib.pyplot as plt X np.linspace(0,2*np.pi,50).reshape(-1,1) y np.sin(X) plt.scatter(X,y) 建模 线性核函数 svr SVR(kernel linear) svr.fit(X,y.ravel())#变成一维y_ svr.predict(X) plt.scatter(…...
win7系统利用定时启动+脚本实现MySQL文件自动备份
前言 最近接到项目,数据量不大但对运行数据的安全性要求极高,为避免因不可抗拒因素导致的数据丢失,选择机械硬盘作为数据存储盘,并使用脚本方式对文件进行备份 一、脚本 下面为自动备份文件的 脚本,可根据自身情况进…...
基于Java多线程处理数据
基于Java多线程处理数据 背景代码实现 背景 在日常工作中,有一个同步企微客户-学员关系接口的定时任务在执行中随着数据量的不断增长,定时任务的执行结束时间也出现了当天执行不完的情况,影响到了正常业务的运行。基于这种情况,在…...
日常知识点之遇到问题结构体按位构造协议时和期望不一致,研究记录一下
遇到一个问题,在做业务的时候,涉及到协议相关,按位进行设计,用结构体来模拟协议时,发现内存存储和实际目的不一致,知道是大小端以及计算机底层存储逻辑相关,所以研究了一下。 1:简单…...
spring mvc 文件下载
在web中下载的方式大多基于servlet,在web.xml中配置下载路径,这里再介绍json(转成base64字符串)和blob的使用方式 servlet WEB-INF/web.xml <!--url映射--> <servlet-mapping><servlet-name>DowloadServlet</servlet-name>&l…...
Qt WebEngine基于WebEngineScript注入js脚本
在之前的文章中,我们介绍了Qt WebEngine注入js的用法,及runJavaScript()的用法,该方法主要是用在页面加载完成后,为了和网页做一些交互时使用。有时候需要监听网页加载完成的一些状态或信息,则需要网页加载前注入js来实…...
案例分享-国外UI设计界面赏析
国外UI设计倾向于简洁的布局和清晰的排版,减少视觉干扰,提升用户体验。通过合理的色彩搭配和图标设计,营造舒适愉悦的使用氛围。 设计师不拘泥于传统框架,勇于尝试新元素和理念,使界面独特有趣。同时,强调以…...
用PyTorch 从零开始构建 BitNet 1.58bit
我们手动实现BitNet的编写,并进行的一系列小实验证实,看看1.58bit 模型是否与全精度的大型语言模型相媲美! 什么是量化以及为什么需要它? 量化是用更少的比特数表示浮点数的过程。当两个数字使用不同的比特数进行量化时…...
信创安全 | 新一代内网安全方案—零信任沙盒
在当今数字化时代,访问安全和数据安全成为企业面临的重要挑战。传统的边界防御已经无法满足日益复杂的内网办公环境,层出不穷的攻击手段已经让市场单一的防御手段黔驴技穷。当企业面临越来越复杂的网络威胁和数据泄密风险时,更需要一种综合的…...
Redis的回收策略(淘汰策略)
volatile-lru :从已设置过期时间的数据集( server.db[i].expires )中挑选最近最少使用的数据淘汰 volatile-ttl : 从已设置过期时间的数据集( server.db[i].expires ) 中挑选将要过期的数据淘汰 volatile…...
Electron-builder 打包
项目比较简单,仅使用了 Electron 原生js 安装 electron-builder npm install electron-builder --dev配置 package.json 中的打包命令 {"script":{// ..."dev": "electron .","pack": "electron-builder"} }添…...
笔试练习day3
目录 BC149 简写单词题目解析代码 dd爱框框题目解析解析代码方法一暴力解法方法二同向双指针(滑动窗口) 除2!题目解析解法模拟贪心堆 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 🐒🐒🐒 个人主页 🥸…...
企业想要将大模型技术应用到企业管理中需具备什么条件?
#企业 #企业管理 #大模型 企业想要将大模型技术应用到企业管理中,需要考虑以下几个关键条件: 1.明确的需求定位:企业应首先诊断自身的业务场景、数据、算法、基础设施预算以及战略等能力,明确大模型能够为企业带来的具体赋…...
go 事件机制(观察者设计模式)
背景: 公司目前有个业务,收到数据后,要分发给所有的客户端或者是业务模块,类似消息通知这样的需求,自然而然就想到了事件,观察者比较简单就自己实现以下,确保最小功能使用支持即可,其…...
RISC-V竞赛|第二届 RISC-V 软件移植及优化锦标赛报名正式开始!
目录 赛事背景 赛道方向 适配夺旗赛 优化竞速赛 比赛赛题(总奖金池8万元!) 🔥竞速赛 - OceanBase 移植与优化 比赛赛程(暂定) 赛事说明 「赛事背景」 为了推动 RISC-V 软件生态更快地发展࿰…...
【VTK】ubuntu手动编译VTK9.3 Generating qmltypes file 失败
环境 硬件:Jetson Xavier NX 套件 系统:Ubuntu 20.04 软件 :QT5.15.6 解决 0、问题 最近在Jetson Xavier NX 套件上编译VTK库,因为想要配合QQuick使用,所以cmake配置时勾选了VTK_MODULE_ENABLE_VTK_GUISupportQtQu…...
学习java的日子 Day64 学生管理系统 web2.0 web版本
MVC设计模式 概念 - 代码的分层 MVC:项目分层的思想 字母表示层理解MModle模型层业务的具体实现VView视图层展示数据CController控制器层控制业务流程(跳转) 1.细化理解层数 Controller:控制器层,用于存放Servlet&…...
【第14章】Spring Cloud之Gateway路由断言(IP黑名单)
文章目录 前言一、内置路由断言1. 案例(Weight)2. 更多断言 二、自定义路由断言1. 黑名单断言2. 全局异常处理3. 应用配置4. 单元测试 总结 前言 Spring Cloud Gateway可以让我们根据请求内容精确匹配到对应路由服务,官方已经内置了很多路由断言,我们也…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
