1+ /*
2+ File: RootViewController.m
3+ Abstract: Table view controller used to display the events associated with the default calendar.
4+
5+ Version: 1.0
6+
7+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
8+ Inc. ("Apple") in consideration of your agreement to the following
9+ terms, and your use, installation, modification or redistribution of
10+ this Apple software constitutes acceptance of these terms. If you do
11+ not agree with these terms, please do not use, install, modify or
12+ redistribute this Apple software.
13+
14+ In consideration of your agreement to abide by the following terms, and
15+ subject to these terms, Apple grants you a personal, non-exclusive
16+ license, under Apple's copyrights in this original Apple software (the
17+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
18+ Software, with or without modifications, in source and/or binary forms;
19+ provided that if you redistribute the Apple Software in its entirety and
20+ without modifications, you must retain this notice and the following
21+ text and disclaimers in all such redistributions of the Apple Software.
22+ Neither the name, trademarks, service marks or logos of Apple Inc. may
23+ be used to endorse or promote products derived from the Apple Software
24+ without specific prior written permission from Apple. Except as
25+ expressly stated in this notice, no other rights or licenses, express or
26+ implied, are granted by Apple herein, including but not limited to any
27+ patent rights that may be infringed by your derivative works or by other
28+ works in which the Apple Software may be incorporated.
29+
30+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
31+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
32+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
33+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
34+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
35+
36+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
37+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
40+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
41+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
42+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
43+ POSSIBILITY OF SUCH DAMAGE.
44+
45+ Copyright (C) 2010 Apple Inc. All Rights Reserved.
46+
47+ */
48+
49+
50+ #import " RootViewController.h"
51+
52+ @implementation RootViewController
53+
54+ @synthesize eventsList, eventStore, defaultCalendar, detailViewController;
55+
56+
57+ #pragma mark -
58+ #pragma mark Memory management
59+
60+ - (void )dealloc {
61+ [eventStore release ];
62+ [eventsList release ];
63+ [defaultCalendar release ];
64+ [detailViewController release ];
65+
66+ [super dealloc ];
67+ }
68+
69+
70+ #pragma mark -
71+ #pragma mark View lifecycle
72+
73+ - (void )viewDidLoad {
74+ self.title = @" Events List" ;
75+
76+ // Initialize an event store object with the init method. Initilize the array for events.
77+ self.eventStore = [[EKEventStore alloc ] init ];
78+
79+ self.eventsList = [[NSMutableArray alloc ] initWithArray: 0 ];
80+
81+ // Get the default calendar from store.
82+ self.defaultCalendar = [self .eventStore defaultCalendarForNewEvents ];
83+
84+ // Create an Add button
85+ UIBarButtonItem *addButtonItem = [[UIBarButtonItem alloc ] initWithBarButtonSystemItem:
86+ UIBarButtonSystemItemAdd target: self action: @selector (addEvent: )];
87+ self.navigationItem .rightBarButtonItem = addButtonItem;
88+ [addButtonItem release ];
89+
90+
91+ self.navigationController .delegate = self;
92+
93+ // Fetch today's event on selected calendar and put them into the eventsList array
94+ [self .eventsList addObjectsFromArray: [self fetchEventsForToday ]];
95+
96+ [self .tableView reloadData ];
97+
98+ }
99+
100+
101+ - (void )viewDidUnload {
102+ self.eventsList = nil ;
103+ }
104+
105+
106+ - (void )viewWillAppear : (BOOL )animated {
107+ [self .tableView deselectRowAtIndexPath: self .tableView.indexPathForSelectedRow animated: NO ];
108+ }
109+
110+
111+ // Support all orientations except for Portrait Upside-down.
112+ - (BOOL )shouldAutorotateToInterfaceOrientation : (UIInterfaceOrientation)interfaceOrientation {
113+ return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
114+ }
115+
116+
117+ #pragma mark -
118+ #pragma mark Table view data source
119+
120+ // Fetching events happening in the next 24 hours with a predicate, limiting to the default calendar
121+ - (NSArray *)fetchEventsForToday {
122+
123+ NSDate *startDate = [NSDate date ];
124+
125+ // endDate is 1 day = 60*60*24 seconds = 86400 seconds from startDate
126+ NSDate *endDate = [NSDate dateWithTimeIntervalSinceNow: 86400 ];
127+
128+ // Create the predicate. Pass it the default calendar.
129+ NSArray *calendarArray = [NSArray arrayWithObject: defaultCalendar];
130+ NSPredicate *predicate = [self .eventStore predicateForEventsWithStartDate: startDate endDate: endDate
131+ calendars: calendarArray];
132+
133+ // Fetch all events that match the predicate.
134+ NSArray *events = [self .eventStore eventsMatchingPredicate: predicate];
135+
136+ return events;
137+ }
138+
139+
140+ #pragma mark -
141+ #pragma mark Table View
142+
143+ - (NSInteger )tableView : (UITableView *)tableView numberOfRowsInSection : (NSInteger )section {
144+ return eventsList.count ;
145+ }
146+
147+
148+ - (UITableViewCell *)tableView : (UITableView *)tableView cellForRowAtIndexPath : (NSIndexPath *)indexPath {
149+
150+ static NSString *CellIdentifier = @" Cell" ;
151+
152+ // Add disclosure triangle to cell
153+ UITableViewCellAccessoryType editableCellAccessoryType =UITableViewCellAccessoryDisclosureIndicator;
154+
155+
156+ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
157+ if (cell == nil ) {
158+ cell = [[[UITableViewCell alloc ] initWithStyle: UITableViewCellStyleDefault
159+ reuseIdentifier: CellIdentifier] autorelease ];
160+ }
161+
162+ cell.accessoryType = editableCellAccessoryType;
163+
164+ // Get the event at the row selected and display it's title
165+ cell.textLabel .text = [[self .eventsList objectAtIndex: indexPath.row] title ];
166+
167+ return cell;
168+ }
169+
170+
171+ #pragma mark -
172+ #pragma mark Table view delegate
173+
174+ - (void )tableView : (UITableView *)tableView didSelectRowAtIndexPath : (NSIndexPath *)indexPath {
175+ // Upon selecting an event, create an EKEventViewController to display the event.
176+ self.detailViewController = [[EKEventViewController alloc ] initWithNibName: nil bundle: nil ];
177+ detailViewController.event = [self .eventsList objectAtIndex: indexPath.row];
178+
179+ // Allow event editing.
180+ detailViewController.allowsEditing = YES ;
181+
182+ // Push detailViewController onto the navigation controller stack
183+ // If the underlying event gets deleted, detailViewController will remove itself from
184+ // the stack and clear its event property.
185+ [self .navigationController pushViewController: detailViewController animated: YES ];
186+
187+ }
188+
189+
190+ #pragma mark -
191+ #pragma mark Navigation Controller delegate
192+
193+ - (void )navigationController : (UINavigationController *)navigationController
194+ willShowViewController : (UIViewController *)viewController animated : (BOOL )animated {
195+ // if we are navigating back to the rootViewController, and the detailViewController's event
196+ // has been deleted - will title being NULL, then remove the events from the eventsList
197+ // and reload the table view. This takes care of reloading the table view after adding an event too.
198+ if (viewController == self && self.detailViewController .event .title == NULL ) {
199+ [self .eventsList removeObject: self .detailViewController.event];
200+ [self .tableView reloadData ];
201+ }
202+ }
203+
204+
205+ #pragma mark -
206+ #pragma mark Add a new event
207+
208+ // If event is nil, a new event is created and added to the specified event store. New events are
209+ // added to the default calendar. An exception is raised if set to an event that is not in the
210+ // specified event store.
211+ - (void )addEvent : (id )sender {
212+ // When add button is pushed, create an EKEventEditViewController to display the event.
213+ EKEventEditViewController *addController = [[EKEventEditViewController alloc ] initWithNibName: nil bundle: nil ];
214+
215+ // set the addController's event store to the current event store.
216+ addController.eventStore = self.eventStore ;
217+
218+ // present EventsAddViewController as a modal view controller
219+ [self presentModalViewController: addController animated: YES ];
220+
221+ addController.editViewDelegate = self;
222+ [addController release ];
223+ }
224+
225+
226+ #pragma mark -
227+ #pragma mark EKEventEditViewDelegate
228+
229+ // Overriding EKEventEditViewDelegate method to update event store according to user actions.
230+ - (void )eventEditViewController : (EKEventEditViewController *)controller
231+ didCompleteWithAction : (EKEventEditViewAction)action {
232+
233+ NSError *error = nil ;
234+ EKEvent *thisEvent = controller.event ;
235+
236+ switch (action) {
237+ case EKEventEditViewActionCanceled:
238+ // Edit action canceled, do nothing.
239+ break ;
240+
241+ case EKEventEditViewActionSaved:
242+ // When user hit "Done" button, save the newly created event to the event store,
243+ // and reload table view.
244+ // If the new event is being added to the default calendar, then update its
245+ // eventsList.
246+ if (self.defaultCalendar == thisEvent.calendar ) {
247+ [self .eventsList addObject: thisEvent];
248+ }
249+ [controller.eventStore saveEvent: controller.event span: EKSpanThisEvent error: &error];
250+ [self .tableView reloadData ];
251+ break ;
252+
253+ case EKEventEditViewActionDeleted:
254+ // When deleting an event, remove the event from the event store,
255+ // and reload table view.
256+ // If deleting an event from the currenly default calendar, then update its
257+ // eventsList.
258+ if (self.defaultCalendar == thisEvent.calendar ) {
259+ [self .eventsList removeObject: thisEvent];
260+ }
261+ [controller.eventStore removeEvent: thisEvent span: EKSpanThisEvent error: &error];
262+ [self .tableView reloadData ];
263+ break ;
264+
265+ default :
266+ break ;
267+ }
268+ // Dismiss the modal view controller
269+ [controller dismissModalViewControllerAnimated: YES ];
270+
271+ }
272+
273+
274+ // Set the calendar edited by EKEventEditViewController to our chosen calendar - the default calendar.
275+ - (EKCalendar *)eventEditViewControllerDefaultCalendarForNewEvents : (EKEventEditViewController *)controller {
276+ EKCalendar *calendarForEdit = self.defaultCalendar ;
277+ return calendarForEdit;
278+ }
279+
280+
281+ @end
0 commit comments