使用后台线程在日历上创build多个事件

我必须根据服务器的响应(事件)更新日历。 我做了一个数组来保存所有的事件对象,并迭代它来保存日历上的事件。 它的工作但问题是它只创build一个随机事件不是全部​​。

  1. 我必须显示所有的事件(most important right now)
  2. 如何使用后台队列来更新日历。
  3. 我必须每5分钟更新一次日历,所以方法必须每5分钟在后台执行一次。
  4. 打电话给服务器创build事件,当我的用户login到应用程序,在主页viewDidLoad方法。 日历是否需要时间才能创build事件,如果用户login并立即退出应用程序,会发生什么情况。 日历会被更新或没有? 我认为直到日历上的所有事件被创build之后,主页才会被加载。

这是代码。

 - (void)calUpdateWebService { NSString *urlString = @"http://www.xxxx.com"; NSURL *url = [NSURL URLWithString:urlString]; NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url]; NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject]; NSURLSessionDataTask * dataTask = [defaultSession dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (!error) { NSDictionary *responseJson = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]; NSMutableArray *eventArray = responseJson[@"result"]; eventData = [NSMutableArray new]; for(NSDictionary *eventDict in eventArray) { NSDictionary *eventDic =@{@"startDate":[eventDict valueForKey:@"start_date"],@"endDate":[eventDict valueForKey:@"end_date"],@"eventSlot":[eventDict valueForKey:@"slot"],@"eventTitle":[eventDict valueForKey:@"package_title"]}; [eventData addObject:eventDic] ; } /** call method to create events**/ [self addBooking]; } }]; [dataTask resume]; } /** method to create events **/ -(void)addBooking { EKEventStore *eventStore = [[EKEventStore alloc]init]; [eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) { if (granted) { addEventGranted =1; EKEvent *event =[EKEvent eventWithEventStore:eventStore]; for (int i = 0; i<[eventData count]; ++i) { [event setTitle:[[eventData objectAtIndex:i] valueForKey:@"eventTitle"]]; NSString *startDate = [[eventData objectAtIndex:i] valueForKey:@"startDate"]; NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init]; [dateFormatter setDateFormat:@"yyyy-MM-dd"]; NSDate *eventStrtdate = [dateFormatter dateFromString:startDate]; [event setStartDate:eventStrtdate]; [event setEndDate:[[NSDate alloc]initWithTimeInterval:1200 sinceDate:event.startDate]]; [event setCalendar:[eventStore defaultCalendarForNewEvents]]; NSError *err; [eventStore saveEvent:event span:EKSpanThisEvent error:&err]; } } }]; }@end 

关键的问题是,在循环之前,你正在实例化事件一次,因此反复更新同一个事件,而你想在循环中实例化一个新的事件:

 // don't instantiate this here // // EKEvent *event =[EKEvent eventWithEventStore:eventStore]; for (int i = 0; i<[eventData count]; ++i) { // but rather do it here EKEvent *event = [EKEvent eventWithEventStore:eventStore]; // now carry on updating the event and saving it } 

在build立一个过程中,这个过程是否每五分钟在后台运行(我假设你的意思是应用程序没有运行),这在iOS中通常是不可能的。 苹果公司只允许在非常狭窄的环境下进行这种连续的后台操作(导航应用程序,VoIP,音乐应用程序等),因为这种模式会杀死用户的电池(想象一下,如果所有的应用程序都这样做了!)。

请参阅适用于iOS应用程序编程指南中的后台执行章节

但是,有两种方法可以用来实现你所需要的。

  1. 后台抓取:这在前面提到的应用程序编程指南中讨论过。 您无法控制操作系统执行后台获取的频率,但肯定不是每五分钟一次(更可能是每天)。 操作系统会查看用户使用您的应用的频率,新数据的可用频率,设备是否插入wifi等等,以确定检查更新的频率。 但它完成了类似于你所要求的东西,尽pipe不太经常。

  2. 推送通知。 如果您参考本地和远程通知编程指南 ,您将看到您可以configuration您的服务器,以将通知推送到客户端应用程序,而不是每五分钟一直轮询服务器更新服务器。 这是更高效的devise,避免了在没有任何数据的情况下对服务器进行浪费的查询。