1

I want to get the email address of the attendee of an event in the EKEventKit.

I have the following code:

if ( event.attendees.count > 0)
{
    NSArray *people = event.attendees;
    for(EKParticipant *person in people)
    {
        if ( person.participantType == EKParticipantTypePerson && person.URL.resourceSpecifier.length > 0)
        {
            NSString *dataString = [NSString stringWithFormat:@"event_id=%ld&name=%@&is_me=%d&email=%@&role=%@",event_id,person.name, person.isCurrentUser,person.URL.resourceSpecifier, @"attendee"];
            //<DO SOMETHING USEFUL WITH dataString>;
        }
    }
}

When I run the code person populates with the following data:

EKAttendee <0x17809acc0> {UUID = 4F657EA4-452A-412B-A9AA-FEC5551DC096; name = A. Real Person; email = realperson@therightdomain.com; status = 0; role = 0; type = 1}

How to I access the email field?

I tried (as above) to use URL.resourceSpecifier, but that frequently is some strange string that is definitely NOT an email address.

SchroedingersCat
  • 487
  • 8
  • 21

3 Answers3

2

The "Description" of the EKParticipant object is a property list of sorts. I tried several different methods of parsing that list into something containing key:value pairs unsuccessfully. So I wrote the following:

                            // This is re-useable code that converts any class description field into a dictionary that can be parsed for info
                    NSMutableDictionary *descriptionData = [NSMutableDictionary dictionary];
                    for (NSString *pairString in [person.description componentsSeparatedByString:@";"])
                    {
                        NSArray *pair = [pairString componentsSeparatedByString:@"="];
                        if ( [pair count] != 2)
                            continue;
                        [descriptionData setObject:[[pair objectAtIndex:1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] forKey:[[pair objectAtIndex:0]stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
                    }

With this I simply get the email address with

    [descriptionData valueForKey:@"email"]
SchroedingersCat
  • 487
  • 8
  • 21
  • It works as expected, i was facing an issue in iOS 12 and unable to get email field, your code worked for me. – GvSharma Sep 24 '18 at 11:12
1

I tried to answer this same question in "how to get ekevent EKparticipant email?" thread:

What you need to do is use EKPrincipal:ABRecordWithAddressBook and then extract email from there. Like this:

NSString *email = nil;
ABAddressBookRef book = ABAddressBookCreateWithOptions(nil, nil);
ABRecordRef record = [self.appleParticipant ABRecordWithAddressBook:book];
if (record) {
    ABMultiValueRef value = ABRecordCopyValue(record, kABPersonEmailProperty);
    if (value
        && ABMultiValueGetCount(value) > 0) {
        email = (__bridge id)ABMultiValueCopyValueAtIndex(value, 0);
    }
}

Note that calling ABAddressBookCreateWithOptions is expensive so you might want to do that only once per session.

If you can't access the record, then fall back on URL.resourceSpecifier.

Community
  • 1
  • 1
ierceg
  • 418
  • 1
  • 8
  • 11
  • good answer,but when the participate is not in iPhone's addressbook,this record will be nil. – frank Aug 17 '15 at 06:19
  • @frank Thanks. Yes, this is in general an unreliable API. I think we finally settled on sending `emailAddress` selector (undocumented) to `appleParticipant`. – ierceg Aug 20 '15 at 11:28
  • @frank It shouldn't be dangerous (data loss, crashes, etc.) but it's definitely a dirty technique. – ierceg Aug 21 '15 at 12:27
1

In Swift 4:

private static func getParticipantDescriptionData(_ participant: EKParticipant) -> [String:String] {
  var descriptionData = [String: String]()
  for pairString in participant.description.components(separatedBy: ";") {
    let pair = pairString.components(separatedBy: "=")
    if pair.count != 2 {
      continue
    }
    descriptionData[pair[0].trimmingCharacters(in: .whitespacesAndNewlines)] =
      pair[1].trimmingCharacters(in: .whitespacesAndNewlines)
  }
  return descriptionData
}
tezqa
  • 139
  • 8