EventKit - multiple methods named 'location' - ios

I am trying to list out the Name, Location, and Notes from calendar events. Reading and writing the Name and Notes work as expected but I run into problems with the Location field.
Specifically, the following line "meetingLocation = [element location];" produces the error
"Multiple methods named 'location' found with mismatched result, parameter type or attributes."
What is wrong here? Code is included below.
-(IBAction)reloadEvents:(id)sender {
NSString *meetingName;
NSString *meetingLocation;
NSString *meetingNotes;
// Define a range of event dates we want to display
NSDate *startDate = [NSDate dateWithTimeIntervalSinceNow:(-1*60*60*.5)]; // .5 hour in the past
NSDate *endDate = [NSDate dateWithTimeIntervalSinceNow:(60*60*24*1)]; // 1 day from now
//NSDate *endDate = [NSDate dateWithTimeIntervalSinceNow:(60*60*24*7)]; // 7 days from now
// Create a predicate to search all celndars with our date range using the start date/time of the event
NSPredicate *predicate = [self.eventStore predicateForEventsWithStartDate:startDate endDate:endDate calendars:nil];
// Query the event store using the predicate.
NSArray *results = [self.eventStore eventsMatchingPredicate:predicate];
// Convert the results to a mutable array and store so we can implement swipe to delete
//NSMutableArray *events = [[NSMutableArray alloc] initWithArray:results];
//self.events = events;
NSEnumerator * enumerator = [results objectEnumerator];
id element;
while(element = [enumerator nextObject])
{
// Set the meeting name
meetingName = [element title];
NSLog(#"Name=%#",meetingName);
// Set the meeting location
meetingLocation = [element location];
NSLog(#"Location=%#",meetingLocation);
// Set the meeting notes
meetingNotes = [element notes];
NSLog(#"Notes=%#",meetingNotes);
}
}

Try like this
while(element = [enumerator nextObject])
{
EKEvent *event = element;
meetingName = event.location;
}

Similar problem converting some old iOS 5 to iOS7:
if ([[thisEvent.recurrenceRules objectAtIndex:i] frequency] == EKRecurrenceFrequencyDaily ){
resulted in
Multiple methods names "frequency" found with mismatched result.
Resolved by typecasting and then doing the if statement
EKRecurrenceRule *thisRecurranceRule = (EKRecurrenceRule *)[thisEvent.recurrenceRules objectAtIndex:i] ;
if ([thisRecurranceRule frequency] == EKRecurrenceFrequencyDaily ){

Related

iOS - How to create recurring calendar events with exclusion occurrences (date)?

I'm trying to create a recurrent event into calendar through JSON API, but with exclusion occurences (/date) I don't know how to do it. I think i create a recurrent event, then I delete occurences.
update:
For example, the event repeats every weekend. However, I removed some of the weekends from the time line, creating an exception to a recurrence rule.
How can I get these excluded dates through the API?
my code:
1. CreateEvent from api json:
NSDictionary *dicEvent = [self.arrayEvents objectAtIndex:index];
EKEventStore *eventStore = [[EKEventStore alloc] init];
EKEvent *event = [EKEvent eventWithEventStore:eventStore];
event.title = [dicEvent objectForKey:#"RecurrenceRule"];
[event setCalendar:[eventStore defaultCalendarForNewEvents]];
event.startDate = [dicEvent objectForKey:#"startDate"];
event.endDate = [dicEvent objectForKey:#"endDate"];
EKSpan span = EKSpanFutureEvents;
[self.eventStore saveEvent:self.savedEvent span:span commit:YES error:&error];
2. then with exclusion occurrences, I think I delete occurences.
EventStore *eventStore = [[EKEventStore alloc] init];
NSPredicate *predicate = [eventStore predicateForEventsWithStartDate:startDate endDate:endDate calendars:calendars];
NSArray *results = [eventStore eventsMatchingPredicate:predicate];
for (int i = 0; i < results.count; i++) {
EKEvent *event = [results objectAtIndex:i]
if ([event.occurencesIdentifier isEqualToString: eventoccurencesIdentifier]) {
// delete occurencesIdentifier
break;
}
Please help me where I had gone wrong.
Thanks!

mutable array value getting empty

I am having an array which contains a date. this is my array.
"2015-03-01",
"2015-03-04",
"2015-03-05",
"2015-03-06",
"2015-03-07",
"2015-03-08",
"2015-03-14",
"2015-03-15"
list the value according to this date.my coding is
NSArray * datevalue = [tempArr valueForKey:#"match_formatted_date"];
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"self" ascending:YES];
NSArray *descriptors = [NSArray arrayWithObject: descriptor];
NSArray *reverseOrder = [datevalue sortedArrayUsingDescriptors:descriptors];
NSPredicate *findFutureDates = [NSPredicate predicateWithBlock: ^BOOL(id obj, NSDictionary *bind){
NSDateFormatter *df = [[NSDateFormatter alloc]init];
[df setDateFormat:#"yyyy-MM-dd"];
[df setTimeZone:[NSTimeZone systemTimeZone]];
NSDate *dd = [df dateFromString:(NSString *)obj ];
return ([[NSDate date] compare:dd] == NSOrderedAscending);
}];
NSArray * arrFutureDates = [reverseOrder filteredArrayUsingPredicate: findFutureDates];
NSLog(#"arrFutureDates:%#",arrFutureDates);
for (id item in arrFutureDates)
{
if (![dataArr containsObject:item])
[dataArr addObject:item];
}
[dataArr sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
for (int i= 0; i<[dataArr count]-1; i++) {
for (id item in tempArr)
{
if([#"Mexico: Copa Mexico - Clausura" isEqualToString:[item valueForKey:#"league_name"]]
||[#"Mexico: Liga De Ascenso - Clausura" isEqualToString:[item valueForKey:#"league_name"]]
||[#"Mexico: Primera Division - Clausura" isEqualToString:[item valueForKey:#"league_name"]])
if([[dataArr objectAtIndex:i]isEqualToString:[item valueForKey:#"match_formatted_date"]])
{
NSMutableDictionary *tempDic =[[NSMutableDictionary alloc]init];
[tempDic setValue: [item valueForKey:#"match_formatted_date"] forKey:#"match_formatted_date"];
[tempDic setValue: [item valueForKey:#"league_name"] forKey:#"league_name"];
if (![titleheader containsObject:tempDic])
{
[titleheader addObject:tempDic];
}}}}
my problem is: In title header null value is coming. were I made the mistake, can anyone help me.
Check your code, you didnt initialize titleheader anywhere. In that case it will be nil only.
Before checking condition, initialize and assign some value to titleheader.
Or else i dont know you missed to paste the code.
Unreadable formatting aside, there are few issues in your code, that may cause your problem:
NSArray* datevalue = [tempArr valueForKey:#"match_formatted_date"];
Name suggests, that tempArr is NSArray, however you are accessing it as NSDictionary. There is difference between methods -valueForKey: and -objectForKey:. Former is NSObject method related to KVC, while latter is NSDictionary method for accessing stored objects. They are frequently confused, because called on NSDictionary they behave in the same way.
for (int i= 0; i<[dataArr count]-1; i++) {
This for loop skips last object in dataArr, which - I assume - was not intended. This can be fixed by i < dataArr.count or i <= dataArr.count-1.
Another issue - not related to problem, but opportunity to learn:
NSMutableDictionary *tempDic =[[NSMutableDictionary alloc]init];
[tempDic setValue: [item valueForKey:#"match_formatted_date"] forKey:#"match_formatted_date"];
[tempDic setValue: [item valueForKey:#"league_name"] forKey:#"league_name"];
if (![titleheader containsObject:tempDic])
Objects in containers are stored and compared (by default) as references, thus -containsObject will always return NO - even if there were another NSDictionary with the same key-value pairs.

Sorting NSMutableArray based on the content of its objects

I have an NSMutableArray called self.objectArray, that contains custom objects. Each object holds an NSDictionary and two other string objects. Actually I need to work only with the dictionary. Every dictionary contains a key named keyDate which holds an NSString that look like this: MM/dd/yy HH:mm:ss.
I would like to sort the array based on their keyDate. The object with the oldest date should be the first object and so on. I've found some questions, that looked helpful and I could create the code that you can see below, but I get an error everytime I run it. As I think NSSortDescriptor won't be the right tool since my keys aren't key value compliant.
PNMessage 0x125c0590> valueForUndefinedKey:]: this class is not key value coding-compliant for the key keyDate.'
NSSortDescriptor *dateDescriptor = [NSSortDescriptor
sortDescriptorWithKey:#"keyDate"
ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:dateDescriptor];
NSArray *sortedEventArray = [self.objectArray
sortedArrayUsingDescriptors:sortDescriptors];
self.finallySorted = [sortedEventArray mutableCopy];
If it's possible I would do it with sort descriptor, however I think there should be some other options, but can't figure out its proper implementation.
So I can also catch every object's keyDate with a for loop, but don't know how can I sort them based on the value. I would really appreciate if somebody could show me the right way.
for(PNMessage *mg in self.objectArray)
{
NSLog(#" test log %#", mg.message[#"keyDate"]);
}
I already checked this answer:
How to sort an NSMutableArray with custom objects in it?
but the structure of my object is different.
My first code based on this question, but it doesn't worked.
How to sort an NSMutableArray with custom objects in it?
UPDATE: my try based on Kaan's answer (doesn't works yet)
static NSDateFormatter *formatter = nil;
if(!formatter) {
formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MM/dd/yy HH:mm:ss"];
}
NSArray *sortedArray = [self.object sortedArrayUsingComparator:^NSComparisonResult(PNMessage *obj1, PNMessage *obj2) {
NSString *date1String = obj1.message[#"keyDate"];
NSString *date2String = obj1.message[#"keyDate"];
NSDate *date1 = [formatter dateFromString:date1String];
NSDate *date2 = [formatter dateFromString:date2String];
if ( date1 < date2 ) {
return (NSComparisonResult)NSOrderedAscending;
} else if ( date1 > date2 ) {
return (NSComparisonResult)NSOrderedDescending;
}
return (NSComparisonResult)NSOrderedSame;
}];
I would consider using the sortedArrayUsingComparator method
Assuming your custom class is called PNMessage:
static NSDateFormatter *formatter = nil;
if(!formatter) {
formatter = [[NSDateFormatter alloc] init];
[formatter setFormat:#"MM/dd/yy HH:mm:ss"];
}
NSArray *sortedArray = [self.objectArray sortedArrayUsingComparator:^NSComparisonResult(PNMessage *obj1, PNMessage *obj2) {
NSString *date1String = obj1[#"keyDate"];
NSString *date2String = obj1[#"keyDate"];
NSDate *date1 = [formatter dateFromString:date1String];
NSDate *date2 = [formatter dateFromString:date2String];
return [date1 compare:date2];
}];
Tip: If you decide on following this, make sure you declare your NSDateFormatter instance as static outside of the sorting body, since allocating Formatters in iOS can be very expensive and cause serious performance penalties.

display two arrays on uitableview sorted by date

I have two arrays one of which is a tweets array and contains twitter tweets. Another of which is a instapics array and contains Instagram pictures. Both of these Arrays have different keys for date. The twitter one had created_at and the instagram one has created_time. I want to display both of them on a single UITableView and have them organized by date. Here is what I am doing so far, the problem with this however is that it only shows Instagram Pictures:
- (void)sortArrayBasedOndate {
NSDateFormatter *fmtDate = [[NSDateFormatter alloc] init];
[fmtDate setDateFormat:#"yyyy-MM-dd"];
NSDateFormatter *fmtTime = [[NSDateFormatter alloc] init];
[fmtTime setDateFormat:#"HH:mm"];
totalFeed = [totalFeed sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
// Instagram Date Retrieval
NSDictionary *instagram = self.instaPics;
NSString *createdAt = instagram[#"created_time"];
int createdAtN = [createdAt intValue];
NSTimeInterval timestamp = (NSTimeInterval)createdAtN;
NSDate *date1 = [NSDate dateWithTimeIntervalSince1970:timestamp];
// Twitter Date Retrieval
NSDictionary *twitter = self.tweets;
NSString *twitterCreated = twitter[#"created_at"];
int createdAtTwitter = [twitterCreated intValue];
NSTimeInterval timestampTwitter = (NSTimeInterval)createdAtTwitter;
NSDate *date2 = [NSDate dateWithTimeIntervalSince1970:timestampTwitter];
return [date1 compare:date2];
}];
}
The above is how I am trying to organize them on the array, below is how I am attempting to display them:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
id object = [totalFeed objectAtIndex:indexPath.row];
if ([tweets containsObject:object]) {
static NSString *Twitter = #"TweetCell";
UITableViewCell *twitter = [self.tableView dequeueReusableCellWithIdentifier:Twitter];
NSDictionary *totalArray = totalFeed[indexPath.row/2];;
// Creation Code Not shown
return twitter;
}else{
static NSString *Instagram = #"InstagramCell";
UITableViewCell *instagram = [self.tableView dequeueReusableCellWithIdentifier:Instagram];
NSDictionary *entry = instaPics[indexPath.row / 2];
// Creation Code not Shown
return instagram;
}
}
The easiest solution would be if you add a common "creationDate" key to all objects in the
totalFeed array. The value of this key should be an NSDate created from
the "created_at" or "created_time" key.
Then you can just sort the array according to this key:
NSSortDescriptor *sortDesc = [[NSSortDescriptor alloc] initWithKey:#"creationDate" ascending:YES]];
totalFeed = [totalFeed sortedArrayUsingDescriptors:#[sortDesc]];
If you cannot do that for some reason, you have to fix the comparator method, it does
not use the passed arguments obj1, obj2 at all.
Something like (pseudo-code):
totalFeed = [totalFeed sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSDate *date1, *date2;
if ("obj1 is a Twitter") {
date1 = "get created_at from twitter obj1"
} else {
date1 = "get created_time from instagram obj1"
}
if ("obj2 is a Twitter") {
date2 = "get created_at from twitter obj2"
} else {
date2 = "get created_time from instagram obj2"
}
return [date1 compare:date2];
}];
In any case, in cellForRowAtIndexPath you have to access totalFeed[indexPath.row]
(without dividing by 2, which does not make sense here).
More sample code:
NSArray *instaPics; // your instagrams
NSArray *tweets; // your tweets
NSMutableArray *totalFeed = [NSMutableArray array]; // the common array
// Date formatter for the tweets. The date format must exactly
// match the format used in the tweets.
NSDateFormatter *fmtDate = [[NSDateFormatter alloc] init];
[fmtDate setDateFormat:#"..."];
// Add all instagrams:
for (NSMutableDictionary *instagram in instaPics) {
NSString *createdAt = instagram[#"created_time"];
NSDate *date = [NSDate dateWithTimeIntervalSince1970:[createdAt doubleValue]];
instagram[#"creationDate"] = date;
[totalFeed addObject:instagram];
}
// Add all tweets:
for (NSMutableDictionary *twitter in tweets) {
NSString *twitterCreated = twitter[#"created_at"];
NSDate *date = [fmtDate dateFromString:twitterCreated];
twitter[#"creationDate"] = date;
[totalFeed addObject:twitter];
}
// Sort
NSSortDescriptor *sortDesc = [[NSSortDescriptor alloc] initWithKey:#"creationDate" ascending:YES];
[totalFeed sortUsingDescriptors:#[sortDesc]];

How to get all events from an EKCalendar in iOS

I've created a calendar with some events, now I want to get all events from that calendar, without knowing what their start or end date is.
Code I tried, getting all events from all calendars, so I could divide them by calendar ID later or so.. :
NSPredicate *fetchCalendarEvents = [eventStore predicateForEventsWithStartDate:[NSDate distantPast] endDate:[NSDate distantFuture] calendars:eventStore.calendars];
NSArray *allEvents = [eventStore eventsMatchingPredicate:fetchCalendarEvents];
This makes allEvents return nil while the database clearly shows events in the calendar.
Anyone could help me?
I have it working now.
This is the code I'm using:
NSDate* endDate = [NSDate dateWithTimeIntervalSinceNow:[[NSDate distantFuture] timeIntervalSinceReferenceDate]];
NSArray *calendarArray = [NSArray arrayWithObject:cal];
NSPredicate *fetchCalendarEvents = [eventStore predicateForEventsWithStartDate:[NSDate date] endDate:endDate calendars:calendarArray];
NSArray *eventList = [eventStore eventsMatchingPredicate:fetchCalendarEvents];
for(int i=0; i < eventList.count; i++){
NSLog(#"Event Title:%#", [[eventList objectAtIndex:i] title]);
}
Gives me all events from the calendar I'm using for my app from the date it is right when you call the method.
I think giving [NSDate distantPast] won't work because it's in the past or something.. setting your startDate as [NSDate date] will work.
Hope this helps people who have the same problem..
If you would like to lookup a year span greater than 4 years, the returned events would be trimmed by the system to those from the first 4 years. (see Apple's documentation). What could be a possible solution is to run the predicate matching in batches.
Here's a C# extension for Xamarin.iOS
public static class EKEventStoreExtensions
{
private const int MaxPredicateYearSpan = 4;
public static EKEvent[] GetAllEvents(this EKEventStore eventStore, DateTimeOffset startAt, DateTimeOffset endAt, params EKCalendar[] calendars)
{
var isBatched = endAt.Year - startAt.Year >= MaxPredicateYearSpan;
var result = new List<EKEvent>();
var batchStartAt = startAt;
var batchEndAt = endAt;
while (batchStartAt < endAt)
{
if (isBatched)
{
batchEndAt = batchStartAt.AddYears(1);
if (batchEndAt > endAt)
{
batchEndAt = endAt;
}
}
var events = GetEventsMatching(eventStore, batchStartAt, batchEndAt, calendars);
result.AddRange(events);
batchStartAt = batchEndAt;
}
return result.ToArray();
}
private static EKEvent[] GetEventsMatching(EKEventStore eventStore, DateTimeOffset startAt, DateTimeOffset endAt, EKCalendar[] calendars)
{
var startDate = (NSDate)startAt.LocalDateTime;
var endDate = (NSDate)endAt.LocalDateTime;
var fetchCalendarEvents = eventStore.PredicateForEvents(startDate, endDate, calendars);
return eventStore.EventsMatching(fetchCalendarEvents);
}
}

Resources