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可以让我们根据请求内容精确匹配到对应路由服务,官方已经内置了很多路由断言,我们也…...
OpenClaw自动化测试:Gemma-3-12b-it驱动浏览器操作与结果校验
OpenClaw自动化测试:Gemma-3-12b-it驱动浏览器操作与结果校验 1. 为什么选择OpenClawGemma做自动化测试? 上周我在重构一个老旧的Web项目时,遇到了一个典型痛点:前端页面改版后,原有的Selenium测试脚本大面积失效。动…...
基于 ThinkLink 的 CJ188 冷水表无线接入方案
让传统冷水表快速接入 LoRaWAN 与物联网平台在很多住宅小区、园区楼宇、老旧水务改造项目中,现场已经部署了大量传统冷水表。 这些水表本身具备稳定计量能力,但往往存在一个共同问题:数据采集依赖人工,抄表效率低,管理…...
unknown
unknown...
C语言自学必看:最经典C语言书推荐
最经典的C语言书都在这了。 1、C Primer Plus 第6版 中文版C语言是鉴于满足程序员需求而被设计出来的,程序员借助C能够去访问硬件,能够操控内存里的位。C语言存有丰富的运算符,可使程序员得以简洁地表述自身意图。C语言不像Pascal那般严谨&am…...
Java程序设计(第3版)第二章——变量的三种定义方式2和3
变量的第二种使用方式 在声明的同时并赋值 数据类型 变量名 = 数据; int b = 12; System.out.println(b); 输出为12变量的第三种使用方式 同时定义多个同类型变量 int c,d=1,e=11,f=23,g=32,h=0…...
线性代数实战:特征值与二次型的核心应用解析
1. 特征值与特征向量的实战密码 第一次接触特征值和特征向量时,我也觉得这不过是数学课本里的抽象概念。直到在图像压缩项目中亲眼看到,用前20%的特征向量就能还原90%的图像信息,才真正理解它的威力。特征值分解就像给矩阵做X光,能…...
你的RAG应用安全吗?藏在向量数据库里的‘特洛伊木马’——外部数据注入风险详解
RAG应用安全深度剖析:如何抵御外部数据源中的"特洛伊木马" 当你在咖啡馆用手机查看银行账户时,是否想过那个看似无害的二维码可能藏着窃取密码的指令?类似的威胁正在AI领域上演——攻击者通过污染RAG(检索增强生成&…...
Python数据处理实战:列表推导式+time库+DataFrame+groupby详细代码注释
🚢 船长Talk | 每天一篇数据分析干货 关注公众号「船长Talk」,获取更多 Python / 数据分析 / SQL 实战技巧,附完整注释代码。 每篇文章都有详细代码注释,学了就能用。Python 数据处理实战:列表推导式 time库 DataFra…...
二十载面香溢加州:鲁味居(101 Noodle Express)的北美餐饮进阶启示录
近日,南加州知名中餐地标品牌“鲁味居(101 Noodle Express)”正式迎来创立二十周年。在竞争激烈的北美餐饮市场,该品牌凭借对中国纯正传统面食与非遗卤味技艺的坚守,不仅确立了其在海外华人圈层的核心地位,…...
补题记录2
牛客周赛137 C D Epta 天梯赛6 8,9,10,11...
