【iOS】日历行程的增删改查(完整)
前言
我们可以使用系统提供的EventKit框架来访问和操作用户的日历日程和提醒(虽然日历和提醒是两个独立的app,但是是用同一个框架来处理数据)。同样地,日历和提醒的数据的数据,都是存储在同一个叫做Calendar Database的数据库中:
EventKit不仅能获取已存在的日程和提醒,还能在自己的app中创建、编辑、删除用户的日程和提醒,还能添加提醒、监听变化等。
在iOS10+中,若要访问用户日程或提醒,需要在info.plist中分别添加NSRemindersUsageDescription和NSCalendarsUsageDescription
一. 读取日程
我们可以通过EKEventStore类来对用户的Calendar database进行查询、创建、编辑、删除等操作。我们可以使用条件来获取符合条件的一组日程,也可以用唯一标识来获取指定的一条日程。获取到的每一条日程都是一个EKEvent的实例对象,因此我们修改EKEvent对象的属性即可实现修改日程信息。
1.创建连接
#import <EventKit/EventKit.h>
...
EKEventStore *store = [[EKEventStore alloc] init];
EKEventStore对象的创建和释放会比较耗时,因此我们一般会在app加载后只创建一个event store对象。
2.通过条件获取日程
如果要获取一个时间段内的日程,可以使用EKEventStore对象的eventsMatchingPredicate: 方法。下面代码演示如何获取昨天至一年后的所有日程:
// 获取日历对象
NSCalendar *calendar = [NSCalendar currentCalendar];// 创建开始时间
NSDateComponents *oneDayAgoComponents = [[NSDateComponents alloc] init];
oneDayAgoComponents.day = -1;
NSDate *oneDayAgo = [calendar dateByAddingComponents:oneDayAgoComponentstoDate:[NSDate date]options:0];// 创建结束时间
NSDateComponents *oneYearFromNowComponents = [[NSDateComponents alloc] init];
oneYearFromNowComponents.year = 1;
NSDate *oneYearFromNow = [calendar dateByAddingComponents:oneYearFromNowComponentstoDate:[NSDate date]options:0];// 创建条件
NSPredicate *predicate = [store predicateForEventsWithStartDate:oneDayAgo endDate:oneYearFromNow calendars:nil];// 获得符合条件的所有日程
NSArray *events = [store eventsMatchingPredicate:predicate];
3.批量处理日程
如果需要批量处理得到的日程,可以用EKEventStore
实例的enumerateEventsMatchingPredicate:usingBlock:方法(同步方法,为了不阻塞主线程建议在其它线程中执行),例如打印出所有符合条件的日程标题:
[store enumerateEventsMatchingPredicate:predicate usingBlock:^(EKEvent * _Nonnull event, BOOL * _Nonnull stop) {NSLog(@"event:%@",event.title);
}];
4.通过唯一标识获取日程
每一个日程都有只读的唯一标识属性eventIdentifier,我们可以通过EKEventStore对象的eventWithIdentifier:方法,传入唯一标识获取指定的一个日程(这个标识是只读属性,由系统指定,可以通过前面的条件查询获取,也可以在创建新的日程时保存这个唯一标识),例如我们已经知道一个日程的eventIdentifier值为”D8574A98-A929-4A92-8E9F-048F46FB5DE7:717c8b40-44e3-31ab-8243-2d5918e266ef”:
EKEvent *event = [store eventWithIdentifier:@"D8574A98-A929-4A92-8E9F-048F46FB5DE7:717c8b40-44e3-31ab-8243-2d5918e266ef"];
NSLog(@"event:%@",event);
二.创建日程
1.通过代码创建
通过EKEvent对象的eventWithEventStore:来创建一个日程,并通过对应的属性编辑日程详细信息,部分属性如:
title - 日程的标题
startDate - 日程的开始日期
endDate - 日程的结束日期
calendar - 日程对应的日历
alarms - 日程的提醒时间
recurrenceRules - 重复规则
实例代码:
EKEvent *event = [EKEvent eventWithEventStore:store];
event.title = @"代码创建的日程";
event.calendar = [store defaultCalendarForNewEvents];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
components.hour = 1;
NSDate *endTime = [calendar dateByAddingComponents:components toDate:[NSDate date] options:0];
event.startDate = [NSDate date];
event.endDate = endTime;
event.notes = @"档期详情:hyaction://hunyu-music";
[event addAlarm:[EKAlarm alarmWithRelativeOffset:-10*60]];NSError *error;
[store saveEvent:event span:EKSpanFutureEvents commit:YES error:&error];
if (!error) {NSLog(@"添加成功!");
}else{NSLog(@"添加失败:%@",error);
}
2.通过系统日历ui添加日程
#import <EventKitUI/EventKitUI.h>
...EKEventEditViewController *vc = [[EKEventEditViewController alloc] init];
vc.eventStore = store;
vc.editViewDelegate = self;
[self presentViewController:vc animated:YES completion:nil];
通过实现EKEventEditViewDelegate代理事件获得结果:
- (void)eventEditViewController:(EKEventEditViewController *)controller didCompleteWithAction:(EKEventEditViewAction)action{NSLog(@"添加日程结果:%zd",action);[self dismissViewControllerAnimated:YES completion:nil];
}
三.编辑和删除日程
我们可以通过修改event的属性值来对日程进行编辑,最后需要调用EKEventStore的实例方法saveEvent:span:commit:error:进行持久化保存:
event.title = @"修改后的标题";
NSError *error;
[store saveEvent:event span:EKSpanFutureEvents commit:YES error:&error];
通过EKEventStore的实例方法removeEvent:span:commit:error:.来删除日程:
NSError *error;
[store removeEvent:event span:EKSpanFutureEvents error:&error];
四.添加提醒
我们可以给日程添加本地推送提醒,在指定的时间或地点给用户进行提醒。
1.基于时间的提醒
我们可以通过event的 addAlarm:方法为一个日程添加提醒。我们可以指定一个确切时间或一个相对时间(只能是日程开始时间之前)。通过removeAlarm: 方法可将提醒移除。
如在开始时间前10分钟提醒:
[event addAlarm:[EKAlarm alarmWithRelativeOffset:-10*60]];
2.基于地理位置的提醒
我们可以设定当用户进入或离开指定的地理位置区域时,触发日程提醒。例如当用户离开公司,提醒用户需要到超市购买日用品,作为开发者,需要确定一个经纬度以及一个半径范围。
EKAlarm *alarm = [[EKAlarm alloc] init];EKStructuredLocation *location = [EKStructuredLocationlocationWithTitle:@"Current Location"];
location.geoLocation = [[CLLocation alloc] initWithLatitude:23.1754700000 longitude:113.4147400000];
alarm.structuredLocation = location;
alarm.proximity = EKAlarmProximityEnter;
[event addAlarm:alarm];
参考苹果官方文档:
https://developer.apple.com/library/content/documentation/DataManagement/Conceptual/EventKitProgGuide/Introduction/Introduction.html
相关文章:

ntp 、ntpdate 、chrony 时间同步
ntp服务 Rhel6时间同步服务器(默认)ntp 端口:UDP/123 搭建ntp客户端同步服务 例: 将配置文件/etc/ntp.conf中的server参数注释掉,并添加上自己的时钟同步服务器 server 0.time.qiyi.domain iburst 这里的…
贝塞尔曲线动画demo(仿美人相机效果)
效果如图: 仿美人相机,手势滑动隐藏顶部view。为了方便讲解,将屏幕分为几个区域,如图: 在拖动过程中: 1、拖动距离小于minMoveDistance,贝赛尔曲线发生形变 2、拖动大于minMoveDistance&am…

算法---001
题目:用1、2、3、4、5、6、7、8、9九个数字拼成一个九位数(每个数字恰好用一次),使得它的前三位、中间三位、最后三位的比值是1 : 2 : 3。例如192384576就是一个合法的解,因为192 : 384 : 576 1 : 2 : 3 看到这种要求…
IOS笔记 #pragma mark的用法
简单的来说就是为了方便查找和导航代码用的。 下面举例如何快速的定位到我已经标识过的代码。#pragma mark 播放节拍器- (void) Run:(NSNumber *)tick { //... } OK,那么如何查找呢,点击代码编辑器上面的导航栏即可:接着我修改一下代码:#prag…

shell脚本api接口考虑并发问题的可行性操作
当我们通过收集每台客户端数据后通过api接口上传到云服务器时,可能会由于客户端过多,几千以至于几万,这时不得不考虑个问题: 并发的问题,同时并发上传文件,可能导致api接口挂掉,但如果我们让文件…

ZOJ 2110 Tempter of the Bone(DFS)
点我看题目 题意 : 一个NM的迷宫,D是门的位置,门会在第T秒开启,而开启时间小于1秒,问能否在T秒的时候到达门的位置,如果能输出YES,否则NO。 思路 :DFS一下就可以,不过要注…

java 16 -12 静态导入
静态导入: 格式:import static 包名….类名.方法名; 可以直接导入到方法的级别 静态导入的注意事项: A:方法必须是静态的 B:如果有多个同名的静态方法,容易不知道使用谁?这个时候要使用&…
Quartz 2D Programming Guide笔记
###Graphics Contexts图形上下文### 图形上下文(graphics context)是绘制目标,可以理解为画布,包含着绘图时的参数和设备信息。类型为CGContextRef。获取graphics context后,调用Quartz 2D的函数进行绘制、旋转等操作&…
有关运维面试重点
数据库分为:关系型数据库(mysql、mariadb)和非关系型数据库(redis等) mysql主从复制的原理: 主从复制: master开启binlog日志master和slave的server-id不同slave主动连接master mysql复制是将…
微信应用号开发知识贮备之altjs官方实例初探
天地会珠海分舵注:随着微信应用号的呼之欲出,相信新一轮的APP变革即将发生。从获得微信应用号邀请的业内人士发出来的一张开发工具源码截图可以看到,reacjs及其相应的FLUX框架altjs很有可能会成为前端开发主流。作为行业内人士,自己之前从来没…

Oracle DMP 操作笔记之根据DMP逆向推导出导出的表空间名称
最近在带着一群.NET新兵们在开发和升级一套系统,本人虽然工作好几年,但是也是属于啥都懂一点,啥都不会的队伍,碰到新兵更是蛋都碎了,还特别拘谨,为啥新兵们都是基础知识很不错的,看来要好好练习…
【iOS】中间透明的引导蒙层
需求 如图口袋蜜蜂app一键海报的新手指引图,需求是遮罩层中间透明的,把底层的第一张海报显示出来,如图: 实现 通过UIBezierPath和CAShapeLayer绘制一张中间为透明的黑色半透明遮罩层。 步奏1、新建类PCOnePosterGuide继承自…

python连接数据库,处理数据结果后生成excel文件
# _*_coding:utf-8 _*_ import time import xlwt import os import pymysql import sys import datetime from datetime import datetime, timedelta class writefile: file r"D:\Users\xx\Desktop" #查询数据库结果 def datacommon(self,mounth,day,n,abj)…

WhyGL:一套学习OpenGL的框架,及翻写Nehe的OpenGL教程
最近在重学OpenGL,之所以说重学是因为上次接触OpenGL还是在学校里,工作之后就一直在搞D3D,一转眼已经毕业6年了.OpenGL这门手艺早就完全荒废了,现在只能是重学.学习程序最有效的办法是动手写,光看书是不行了,因为看书的时候很容易陷入对人类两大难题的思考中,以至于进展缓慢.这…

iOS与JS交互的4种方法
iOS与JS交互的方法: 1.拦截url(适用于UIWebView和WKWebView) 2.JavaScriptCore(只适用于UIWebView,iOS7) 3.WKScriptMessageHandler(只适用于WKWebView,iOS8) 4.WebV…

UDP打洞原理
1. NAT分类根据Stun协议(RFC3489),NAT大致分为下面四类1) Full Cone这种NAT内部的机器A连接过外网机器C后,NAT会打开一个端口.然后外网的任何发到这个打开的端口的UDP数据报都可以到达A.不管是不是C发过来的.例如 A:192.168.8.100 NAT:202.100.100.100 C:292.88.88.88A(192.168…

五款常用协议分析处理工具推荐
工欲善其事,必先利其器,一款好的工具,能取到事半功倍的效果。进行协议分析,好的辅助工具必不可少,本文推荐五款最常用且易用的协议分析工具给大家,包括两款综合抓包及分析工具,一款协议重放工具…
【转】android电池(四):电池 电量计(MAX17040)驱动分析篇
关键词:android 电池 电量计 MAX17040 任务初始化宏 power_supply 平台信息:内核:linux2.6/linux3.0系统:android/android4.0 平台:samsung exynos 4210、exynos 4412 、exynos 5250 作者:xubin341719(欢迎转载&…

hihoCoder#1384 : Genius ACM
对于一个固定的区间$[l,r]$,显然只要将里面的数字从小到大排序后将最小的$m$个和最大的$m$个配对即可。 如果固定左端点,那么随着右端点的右移,$SPD$值单调不降,所以尽量把右端点往右移,贪心分割即可。 为了使得扫过的…

微信小程序开发 笔记
1.[wxss]设置带透明度的rgb颜色:rgb(0,0,0,0.5); 2.小程序使用类似于iOS的NSNotification:(第三方:https://github.com/icindy/WxNotificationCenter) (1)在需要收发通知的页面引入WxNotificationCenter: var WxNotifi…

简单两行,实现无线WiFi共享上网,手机抓包再也不用愁了
你是否为WiFi共享而发愁,各个无线共享软件,某某共享精灵,某某免费WiFi,某某共享大师,某某随身WiFi,一个比一个难用,一个比一个私货多,一个比一个广告多,如果装上了它们&a…

用C#实现的条形码和二维码编码解码器
本篇介绍可以在C#中使用的1D/2D编码解码器。条形码的应用已经非常普遍,几乎所有超市里面的商品上面都印有条形码;二维码也开始应用到很多场合,如火车票有二维码识别、网易的首页有二维码图标,用户只需要用手机扫描一下就可以看到手…
【iOS】通过NSURLProtocol提高Web加载速度
一.项目需求 项目中有个海报功能,是用UIWebView加载h5网页的形式。因为海报的使用率比较高,如果网页加载得比较慢会严重影响用户体验,因此我们想了一个方法,在用户启动APP后,如果连接了Wi-Fi,就将一些css和…

rand()和srand()关系很简单——一看就明白(通过一个可移植的源码)
1 函数rand和srand实现及描述 #include <stdlib.h> //供rand()使用的种子数,初值为1 unsigned long int next 1; /* * 描述:函数rand() 用于生成介于 0和RAND_MAX之间的伪随机整数序列 * 其中RAND_MAX是在头文件<stdlib.h> 中定义的…

Windows下Python 3.6 安装BeautifulSoup库
“ 介绍Python库BeautifulSoup安装。”01—BeautifulSoup库介绍Beautiful Soup是Python的一个库,支持Python 2和Python 3,最主要的功能是从网页抓取数据,即爬虫,官网介绍如下:Beautiful Soup provides a few simple methods and Pythonic idi…

struts2配置详解
01.Struts 2基本结构 使用Struts2框架实现用登录的功能,使用struts2标签和ognl表达式简化了试图的开发,并且利用struts2提供的特性对输入的数据进行验证,以及访问ServletAPI时实现用户会话跟踪,其简单的程序运行流程图如下 Struts…
Xcode调试技巧
1、给断点设定触发条件 如下代码,右键断点,选择Edit Breakpoint,设定只有i8时,才触发断点。 此时只有i8时,才触发断点。 2、断点调试时修改变量 上面代码i8成立时,触发短点,此时右击变量窗口…

MiniGUI - UNIX Domain Socket 封装
/* Returns fd if all OK, -1 on error. */ int serv_listen (const char* name);服务器调用该函数建立一个监听套接字,并返回套接字文件描述符。建议将服务器监听套接字建立在 /var/tmp/ 目录下。MAX_NR_LISTEN_FD 宏定义了系统能够监听的最多文件描述符数…

RSA加密算法破解及原理
“ RSA加密算法是一种非对称加密算法,目前被广泛应用。本文介绍RSA算法的基本原理和破解方法。”RSA在互联网上被广泛应用,典型的如各个网站的证书。很多应用数据的加密也是使用RSA。本文介绍RSA算法的原理,并介绍其破解方法和工具。01—RSA算…

SpringMvc之@RequestParam详解
RequestParam是传递参数的. RequestParam用于将请求参数区数据映射到功能处理方法的参数上。 public String queryUserName(RequestParam String userName) 在url中输入:localhost:8080/**/?userNamezhangsan 请求中包含username参数(如/requestparam1?userNamezh…