当前位置: 首页 > news >正文

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中最重要的就是事务&#xff0c;其四大特性让我们维持了数据的平衡&#xff0c;一致。那么事务究竟是什么&#xff0c;与什么相关&#xff0c;他的使用步骤&#xff0c;以及使用过程中我们会遇到什么问题呢&#xff1f;下面我们一起学习交流! 1.MySQL的存储引擎&#xff…...

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文件自动备份

前言 最近接到项目&#xff0c;数据量不大但对运行数据的安全性要求极高&#xff0c;为避免因不可抗拒因素导致的数据丢失&#xff0c;选择机械硬盘作为数据存储盘&#xff0c;并使用脚本方式对文件进行备份 一、脚本 下面为自动备份文件的 脚本&#xff0c;可根据自身情况进…...

基于Java多线程处理数据

基于Java多线程处理数据 背景代码实现 背景 在日常工作中&#xff0c;有一个同步企微客户-学员关系接口的定时任务在执行中随着数据量的不断增长&#xff0c;定时任务的执行结束时间也出现了当天执行不完的情况&#xff0c;影响到了正常业务的运行。基于这种情况&#xff0c;在…...

日常知识点之遇到问题结构体按位构造协议时和期望不一致,研究记录一下

遇到一个问题&#xff0c;在做业务的时候&#xff0c;涉及到协议相关&#xff0c;按位进行设计&#xff0c;用结构体来模拟协议时&#xff0c;发现内存存储和实际目的不一致&#xff0c;知道是大小端以及计算机底层存储逻辑相关&#xff0c;所以研究了一下。 1&#xff1a;简单…...

spring mvc 文件下载

在web中下载的方式大多基于servlet&#xff0c;在web.xml中配置下载路径&#xff0c;这里再介绍json(转成base64字符串)和blob的使用方式 servlet WEB-INF/web.xml <!--url映射--> <servlet-mapping><servlet-name>DowloadServlet</servlet-name>&l…...

Qt WebEngine基于WebEngineScript注入js脚本

在之前的文章中&#xff0c;我们介绍了Qt WebEngine注入js的用法&#xff0c;及runJavaScript()的用法&#xff0c;该方法主要是用在页面加载完成后&#xff0c;为了和网页做一些交互时使用。有时候需要监听网页加载完成的一些状态或信息&#xff0c;则需要网页加载前注入js来实…...

案例分享-国外UI设计界面赏析

国外UI设计倾向于简洁的布局和清晰的排版&#xff0c;减少视觉干扰&#xff0c;提升用户体验。通过合理的色彩搭配和图标设计&#xff0c;营造舒适愉悦的使用氛围。 设计师不拘泥于传统框架&#xff0c;勇于尝试新元素和理念&#xff0c;使界面独特有趣。同时&#xff0c;强调以…...

用PyTorch 从零开始构建 BitNet 1.58bit

我们手动实现BitNet的编写&#xff0c;并进行的一系列小实验证实&#xff0c;看看1.58bit 模型是否与全精度的大型语言模型相媲美&#xff01; 什么是量化以及为什么需要它&#xff1f; 量化是用更少的比特数表示浮点数的过程。当两个数字使用不同的比特数进行量化时&#xf…...

信创安全 | 新一代内网安全方案—零信任沙盒

在当今数字化时代&#xff0c;访问安全和数据安全成为企业面临的重要挑战。传统的边界防御已经无法满足日益复杂的内网办公环境&#xff0c;层出不穷的攻击手段已经让市场单一的防御手段黔驴技穷。当企业面临越来越复杂的网络威胁和数据泄密风险时&#xff0c;更需要一种综合的…...

Redis的回收策略(淘汰策略)

volatile-lru &#xff1a;从已设置过期时间的数据集&#xff08; server.db[i].expires &#xff09;中挑选最近最少使用的数据淘汰 volatile-ttl &#xff1a; 从已设置过期时间的数据集&#xff08; server.db[i].expires &#xff09; 中挑选将要过期的数据淘汰 volatile…...

Electron-builder 打包

项目比较简单&#xff0c;仅使用了 Electron 原生js 安装 electron-builder npm install electron-builder --dev配置 package.json 中的打包命令 {"script":{// ..."dev": "electron .","pack": "electron-builder"} }添…...

笔试练习day3

目录 BC149 简写单词题目解析代码 dd爱框框题目解析解析代码方法一暴力解法方法二同向双指针(滑动窗口) 除2!题目解析解法模拟贪心堆 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 &#x1f412;&#x1f412;&#x1f412; 个人主页 &#x1f978;&#x1…...

企业想要将大模型技术应用到企业管理中需具备什么条件?

#企业 #企业管理 #大模型 企业想要将大模型技术应用到企业管理中&#xff0c;需要考虑以下几个关键条件&#xff1a; 1.明确的需求定位&#xff1a;企业应首先诊断自身的业务场景、数据、算法、基础设施预算以及战略等能力&#xff0c;明确大模型能够为企业带来的具体赋…...

go 事件机制(观察者设计模式)

背景&#xff1a; 公司目前有个业务&#xff0c;收到数据后&#xff0c;要分发给所有的客户端或者是业务模块&#xff0c;类似消息通知这样的需求&#xff0c;自然而然就想到了事件&#xff0c;观察者比较简单就自己实现以下&#xff0c;确保最小功能使用支持即可&#xff0c;其…...

RISC-V竞赛|第二届 RISC-V 软件移植及优化锦标赛报名正式开始!

目录 赛事背景 赛道方向 适配夺旗赛 优化竞速赛 比赛赛题&#xff08;总奖金池8万元&#xff01;&#xff09; &#x1f525;竞速赛 - OceanBase 移植与优化 比赛赛程&#xff08;暂定&#xff09; 赛事说明 「赛事背景」 为了推动 RISC-V 软件生态更快地发展&#xff0…...

【VTK】ubuntu手动编译VTK9.3 Generating qmltypes file 失败

环境 硬件&#xff1a;Jetson Xavier NX 套件 系统&#xff1a;Ubuntu 20.04 软件 &#xff1a;QT5.15.6 解决 0、问题 最近在Jetson Xavier NX 套件上编译VTK库&#xff0c;因为想要配合QQuick使用&#xff0c;所以cmake配置时勾选了VTK_MODULE_ENABLE_VTK_GUISupportQtQu…...

学习java的日子 Day64 学生管理系统 web2.0 web版本

MVC设计模式 概念 - 代码的分层 MVC&#xff1a;项目分层的思想 字母表示层理解MModle模型层业务的具体实现VView视图层展示数据CController控制器层控制业务流程&#xff08;跳转&#xff09; 1.细化理解层数 Controller&#xff1a;控制器层&#xff0c;用于存放Servlet&…...

【第14章】Spring Cloud之Gateway路由断言(IP黑名单)

文章目录 前言一、内置路由断言1. 案例&#xff08;Weight&#xff09;2. 更多断言 二、自定义路由断言1. 黑名单断言2. 全局异常处理3. 应用配置4. 单元测试 总结 前言 Spring Cloud Gateway可以让我们根据请求内容精确匹配到对应路由服务,官方已经内置了很多路由断言,我们也…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek

文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama&#xff08;有网络的电脑&#xff09;2.2.3 安装Ollama&#xff08;无网络的电脑&#xff09;2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...