Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2008-529
$eventId
ID of event: wwdc2008
$eventContentId
ID of session without event part: 529
$eventShortId
Shortened ID of event: wwdc08
$year
Year of session: 2008
$extension
Extension of original filename: m4v
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC08 • Session 529

Address Book for iPhone

Integration • 1:14:20

The iPhone Address Book API gives you access to the contact database on iPhone. Find out how to read and write system-wide contact information, create new contacts, and display selected contact information with the same user interface as Apple's iPhone applications.

Speaker: Alex Aybes

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Good morning, and welcome to Address Book for iPhone. My name is Alex Aybes. I'm a software engineer on the iPhone team. I'm going to talk to you about how to put people in your application. So let's take a look at what we're going to cover today. Obviously, we're going to cover the Address Book APIs, both the low-level C APIs that are exposed in the Address Book framework and the higher-level graphical user interface bits that the Address Book UI framework exposes.

The way we're going to go through those APIs is actually through two scenarios. The first one is the social networking website scenario. Maybe some of you in the audience are working at Facebook, at LinkedIn, or at the brand-new social website that -- and you want to create a great native application for the iPhone.

Some of the challenges with this are you have people on the web, you have people on the phone, new user. New users have people on their phone. So you want to reconcile those two sets of contacts. We're going to look at a number of APIs that are available in the Address Book that will allow you to do this.

The second example we're going to look at today is the example of an existing application. You want to connect your application more to users. And what better way is there than to add their friends into your application? So we need to look at another set of APIs and actually add people to the recipes application. You might have seen it in a couple of other sessions. Before we dive into this, a little heads up for the Mac OS X developers in the audience.

The Address Book for the iPhone uses the same data as the one on the desktop. We actually synchronize all of this data, either through MobileMe or through iTunes. However, the APIs are new. Those are brand-new APIs that were built for the iPhone. They share a lot of similarities with the desktop APIs because they use the same data, and the same engineers actually wrote them.

But those are brand-new APIs, especially when it comes to all the graphical user interface bits. Those are all view-control-based, and they're, therefore, new to the iPhone. All right. Now that I've scared you a little bit, let me reassure you, it's actually really easy. Ten lines of code, you can have Address Book in your application. And for this, I'm actually going to show you. So we're going to do the first demo now.

There we have essentially the navigation controller-based template project in Xcode. If I run this, all I'm going to get is a window and a navigation controller, a navigation bar at the top. All right. Let's actually add Address Book into this. Let's go back to Xcode. Again, this is the application delegate. If you have not seen the previous ViewController sessions, don't worry about it. We'll focus mostly on the Address Book part, but I really encourage you to check out the videos when they come out of the Understanding ViewController session.

All right, so the first thing we want to do in order to put a person in our application is to create a person. I'm going to go through the address book API fairly quickly in this first demo. We'll see them in more details later on. Why is the font size not set on this machine? Ah, that's the next on the question. That's too bad.

Thank you. And 18? Yes, make a copy. Great. Name. 18. Okay. Is that better? All right. Thank you. That's one thing I didn't notice when I was running through this earlier today. All right. So first thing we do here is create a person. Again, don't worry too much about the APIs. We'll cover them in more detail later.

So we create a person. Then we're going to set its name and its last name, our dear friend John Appleseed, always there. Now that we have a person, we need to create a view controller to present that person. The Address Book UI framework exposes the A/B person view controller. So we're going to use that. We're going to set its displayed person property to be the person we just created.

And that's really all we need for the View Controller. Next, we're going to need to push it onto our Navigation Controller. I mentioned this is a Navigation Controller-based application. And you can see the Navigation Controller is actually created right there. So we're going to push the Person View Controller onto our Navigation Controller.

And for some reason, I decided to animate this. This is probably not right. We don't want to animate it. So, navigation controller, push view controller. Once that's done, release our memory. The person view controller is owned by the navigation controller. We don't need it anymore. And the person has actually been set on a view controller. So let's run this. And there we go. We have a card, a person view in our application. You can drag it around. It's kind of cute.

It's kind of cute, but at the same time, I mean, if you've written table views, it's not that hard to do. Let's see one other thing we can actually do with that person view controller. Another property of the person view controller is the allows editing. It's a Boolean that tells the view controller whether or not the user should be allowed to edit that person. We set this and we run. Notice there's a little edit button there.

When you press that button, we actually bring in change the content of the person view controller, and you can actually go ahead and enter a new phone number if you'd like. Select the label. You can cancel out of this. You can select a photo. I'm going to actually put a photo on John's card if I can find one.

There we go. And you get all this behavior for free with the Person View Controller. So again, looking back at the code, we have... 356789. Nine lines of address book-related code, and that's all we need. And we have a lot of the A lot of the flow of the Address Book application directly into your application. All right. Let's go back to slides.

So what did we just see here? Again, the very simple, simple hello world of the Address Book. You create a person, set a couple of properties, create an A/B person view controller, set the person you're going to display in that view controller, and then you push it onto the navigation stack.

And if you want to allow editing, well, you get that for free. The user has access to the same flow we expose in the contacts application, in the phone application. All right, great. That was cute. A little 10 lines of code, a little hello world. Let's go a little beyond that.

Let's go back to our social networking example. Again, you work for a social networking website. You want to bring a So we're going to look at a lot of address book APIs that are also relevant if you're not doing social networking. Don't worry. You don't need to leave the room quite yet. So social networking website. You have people on the Web. So we're going to look at what it takes to reconcile those two groups of people and actually display them in your application.

In this case, we're going to display a list of the people, both the ones from the web and the ones that were already on the phone. Let's look at the different steps we need to go through to do this. The first one is going to be downloading those people from the web.

I'm not going to go into too much detail. Actually, I'm going to skip that part entirely, because it's not really relevant to the actual Address Book API. So I'm going to let you do that one. The next step is going to be to search. What I mean by that is we have people from the web. We're going to search the local address book, the user's address book on the iPhone, for people who match those people we found from the web.

Once we have that, We're going to update the people we found locally on the phone. We're going to update them with extra information that came from the social networking site, from our little web service. Once we update those people, we actually need to display them and show them to the user. Let's take a look at the first step. Again, the first step is actually the second step on that slide, searching.

In order to search the address book, all you really need to do is to get the address book and then search through it. It's pretty simple. And then two lines of code to do it. Exactly that. You create an address book instance, and then you use this long method to actually search for people in that address book. A/B address book copy people with name.

Alex Aybes I'm going to talk a little more about the address book create in a second, but I'm going to just mention a couple things about this search function right there. It's actually really meant to -- this is what we use when you're typing in the search field.

The name in this case is something -- is a language string that the user might have typed. So it could be multiple words. And we'll try to match that and do our best to figure out who in the address book actually matched all those words that I've done. So it's really simple to use. You don't really need to worry about what it does. You pass in the name, and we'll give you a list of people who actually matched that name.

The first line is pretty simple, but there's quite a bit to cover in there. So let's go ahead and look at A/B Address Book and this A/B Address Book Create. So the way we represent the address book on the phone is through this object, AB Address Book. It's a core foundation type.

CF type, for short, the address book ref. If you're not too familiar with core foundation and you're more familiar with the foundation side, the Objective-C side of it, just remember core foundation types are actually bridged to foundation types. So you can actually use them as if they were Objective-C types for things like retaining, releasing, auto-releasing.

All right, so what does this API Address Book object give you? It's actually the central point for accessing people. It's really whenever you need to deal with people, this is the object you need to use. : You're going to get people from it, search the address book for people, et cetera, et If you're familiar with the naming conventions of Core Foundation, you probably noticed here that we're actually creating a new instance of A/B Address Book. And every time you call this function, A/B Address Book create, we're actually going to create a new instance of it.

The important thing to remember in this case is that it always accesses the same address book database, the user's address book database. There are reasons why you would want to actually create multiple instances of it, and we'll go over those reasons a little later, but just remember, it's always the same user database of contacts.

All right. I just mentioned contacts. So we have an address book. Now we actually need to get people. How do we represent people on the phone? To represent a person, we have another CF type, the AB Record. The A/B record is a container for properties, things like the first name, the last name, also the image associated with that contact, as well as other properties like phone numbers, email addresses, all you expect for a contact to be able to, you know, call them, email them, et cetera. So let's take a look at those properties in a little more detail.

All the properties that we expose on the record can have a number of different types. For example, the name properties are all strings, obviously. The date properties, like the birthday, are date types. And things like images are data, CFData objects. And dictionaries we use to represent addresses. All those different properties actually give you CF types again. CFString, CFDate, CFDictionary. And if you are more comfortable in Objective-C, they're all toll-free bridge to the equivalent Objective-C objects. So NSString, NSDate, NSDictionary, etc., etc.

So this is good for the simple properties. Some properties actually have multiple values. You obviously can have multiple phone numbers. I think I have a stack of like 12 iPhones on my desk, and I need to keep track of every single phone number in there. So we're going to talk to you about this a little more.

If you want the exhaustive list of all the properties available in the person, go check out the header. You actually have all the properties listed in there, as well as the types, whether they're strings, dates, et cetera. Let's take a closer look at the simple properties, the single value properties.

Some examples, again, first name, last name, birthday, there's a lot more. Core Foundation types. So retain and release them. The way you access them in the code is by To get the value, pull this function, ab_record_copy_value. And this is what it looks like in code. In this case, we call ab_record_copy_value, passing in the person and the name of the property we want to actually access.

In this case, the kab_person_first_name property that will give you the first name. And it's a string. So we'll get that string out of there. In order to set a value, A very similar function, AB record set value. And what this looks like in code, here we are sending the birthday.

So the first thing we're going to do, create a date. Apparently, this person is born today, right now. So and then we set the value. AB record set value. We pass in the person. We pass in the actual property we want to set, the birthday in this case. We pass in the date we want to set as the birthday.

And the last argument is an error. You can get an error back in case something went wrong or in case the actual data storage we're using for this particular contact does not support a particular property. This is relevant when you're talking to Exchange. It supports only a certain number of email addresses, for example.

Single-Value Properties, fairly simple. Let's take a look at the Multi-Value Properties I talked about earlier. Phone numbers, email addresses, URLs, etc. Really, you access them the same way you access single-value properties, using AB record copy value and AB record set value. The difference, the big difference here is that instead of sending a string directly, you're actually going to be getting and setting this AB multivalue ref object. Again, core foundation type. I'm going to say that all the time.

That AB Multivalue is actually a container for labels and values. What do I mean by that? If you look at the little diagram here, we have an AB Multivalue ref that's for phone numbers. This AB Multivalue ref has a number of

[Transcript missing]

So you have two home phone numbers. The label is not a key in the multivalue in the database sense.

You can have however many is the founder of the Google Home Office. He's been working on a lot of new features, including All right, so how do we actually access the multivalue? There are four different important functions to use in the multivalue. The first one, I mentioned, we have multiple items in the multivalue, so you probably want to get the count of values in that multivalue. For that, simple function, AB Multivalue Get Count will give you back a CF index, which is just an integer.

The next thing we probably want to look at is the actual value. So to get the value, ABMultiValue, copy value at index. Again, fairly simple. You pass in the multi-value, pass in the index you're interested in, and you get a value. This value is a CF type, meaning depending on the actual property you asked for, you're going to get strings or dates, et cetera.

The next item we saw in there was the label. To get the label, very similar to the way we got the value. AB Multi-Value Copy Label-Write Index. : Hi, guys. I'm Alex Aybes. I'm the founder of Google. And I'm going to talk about how to use Google's mobile phone to create a new contact information. So, let's get started. So, let's start with the first item, which is the identifier. And the label is always a string.

There's a number of predefined labels, like home, work, other. And depending on the actual property, we have some extra ones, like mobile phone, et cetera. So, passing the label, This is important because the index is not actually guaranteed to change. It could be changed by sync. It could be changed in a number of different situations.

The multivalues will be -- the entries in the multivalue might actually be reordered. So if you want to keep track of a particular entry in that multivalue, use the identifier. And the way this works, very similar, AB Multivalue get identifier at index. The identifier is actually just an integer, but that one is actually guaranteed to stay constant across saves, et cetera.

All right. With that, we have a lot of the tools we need to actually do the second step, the updating. But there's a couple things we actually need to do on top of what we've just seen. The first thing we need to do in order to update that local record with the data we got from our web service is to mutate the multivalue. Multivalues, when you get them from the address book, are not actually mutable. You cannot add or remove labels from them.

So you actually need to, like I said, mutate the value. Once you've mutated the value, you-- I'm sorry. Once you've mutated the multivalue, you can add a value to it, add an entry. The next step is actually important. You actually need to get this multivalue and set it back on the person. Otherwise, you're just changing a copy of the data in that person. You actually need to set it back on the person. Once you've done that, you probably want to save so that users can access the data in other applications.

Alex Aybes The way this looks in code, you can see at the bottom, the first thing we do is get the value from the existing person, just in case they already had, in this particular case, URLs. As I mentioned, we create a mutable copy with abmultivalue create mutable copy, passing the original multivalue, get a mutable multivalue. On that mutable multivalue, we called abmultivalue add value and label.

Pass in the mutable multivalue, the actual URL we want to set, we want to add, the label, And the last argument in this case we actually ignore. It's an identifier that can be passed back to you. This is the identifier that you can hold onto when you want to access that particular entry again. After that, we set the value on the person and save.

So that's it. That's all we need to do for step two. Step three, if you remember, It's displaying. Kind of useful. In order to display this list of contacts, We need to first sort them. We probably do want to put them in a reasonable order rather than whatever order they were added in on the server. So we need to sort them. Then we need to actually get a name that we can display.

[Transcript missing]

It's really simple. We made it really simple. We'll actually do most of the sorting for you. And we'll take care of different languages, et cetera, et cetera. So to do this, two simple functions. The A/B person gets sort ordering. That will actually get you the user's preference for what order to sort people in. This is what they will actually set in the preferences for their address book.

The second function is actually a CF comparator function, which means that it can be reused in the ways we're going to see in the code in a second. That will actually compare two persons and tell you which one's name comes first in the ordering. The way this looks like in code, you get immutable array of people. Then we're going to create a range because that's what we need to use later.

And then, this is the first interesting bit, we need to actually get the sort ordering. For that, A/B person sort ordering, the sort ordering, A/B person get sort ordering. Again, that gives you the user's preference for the sort ordering. Then, and this is where the actual sorting happens, call this handy function in CF, CFArraySwordValues.

You pass in the people, the mutable array we just got earlier, the range of people you actually want to sort in that array. In this particular case, we want to sort all the people in the array, so we're going to pass the full range. And then you pass in the CF comparative function. Again, this is the address book -- this is the function the address book framework exposes.

You can use it as is. And last but not least, it's actually really important, the context. This is a context that will be passed back into the A/B person to compare people by name. That context has to be the sort ordering. It can be the user's preference for a sort ordering, or it can be whatever sort ordering. If for some reason you actually want to have your app display different sort ordering, you can pass the sort ordering you want. But it has to be the sort ordering.

That's sorting. Now, actually, one more thing. If you are allergic to C and prefer to use Objective-C, this is what it looks like. You can pass the same function to the sort using function method on an SMutable array. Again, the context still needs to be the sort ordering.

All right. That's it for sorting. So now let's take a look at displaying and getting the name. So to do that, again, we have a simple function that will extract all the bits and pieces you need to build what we call the composite name. It's, you know, the Alex Abas Senior Junior whatever. So it will take all the different bits and pieces, put them in the right order.

We'll also use the user's preference for name formatting, meaning if the user wants to have the last name first, it will do the right thing. The way this looks in code, very simple. You have a person, get the name with AB record, copy composite name, then do something clever with it.

The Objective-C version is exactly the same, except as I mentioned earlier, CF types can be cast into their foundation equivalent. In this case, CFStringRef can be used as an NSString. You can cast it directly to be an NSString. And then you should still do something clever with that name. All right, the next step in actually the display process is to actually display the contacts. So we're actually just going to do that. Rather than showing you code, we're going to implement it.

So we're back here. I'm going to close the quick application project and my social book application. So here we have a little application. It's got an application delegate, very simple, a navigation controller-based application. Again, if you have not seen the view control session, I encourage you to download the videos when they're available and take a look. But we're going to focus mostly on the Address Book API for this. So we have our AppDelegate. All the AppDelegate does is use the social people table view controller and push it onto the navigation stack.

So let's actually take a look at the social people table view controller. This particular subclass of table view controller, I've already filled in a little bit of code. The main thing you're going to see is that the number of rows in the table view are essentially the number of people.

We have this little people method that we're going to put in a lot of code to actually download the contacts from the web service and do all those things we were talking about. So if I run it right now-- We get just a table view. It's got a title. And that's it. Let's actually start downloading the people from the web. So we're going to put all that code, as I mentioned, in the people method.

Here, people is actually just a instance variable off our TableViewController, as you can see here. And it's mutable, right? Also have a handy little web service class that will do the downloading. All right. So first thing we need to do is ask our web service for the web people. Web people are represented by this little web person class.

It's actually just -- a very simple class with three properties: first name, last name, URL string. Good enough for the demo. You probably have more information than that in your application. All right. We're going to get the people from the Web and iterate over all those people. Once we have a Web person, as I mentioned, the first thing we're going to do is actually search for that person in the local address book. So let's do that.

Here, we're going to build a full name. Again, this is to be passed to the copy people with name function, and it's just going to be the first name, a space, and the last name. You don't need to worry too much about that actual string. It just needs to be a number of words separated by spaces. And we'll do the right thing and find the people who actually match that name exactly.

So the next thing is to actually find the people in the address book. A/B address book copy people with name, pass in our address book that's actually created in the initialized method here, the init method. We're actually creating an A/B address book reference. And we pass in the full name we just created. Again, CFNS, you can cast one to the other. All right.

Once we're done with the people, we're actually going to release them. But before that, we need to do a couple of things. So we need to actually check if we have -- if we found people in the Local Address Book that matched the name of the people we downloaded from the Web. So check that we actually got an array, and then get the count for that array.

In this particular case, we're only going to get the first person we matched in the address book. It's a bit of a shortcut I'm taking for the demo, and you probably want to do a little more work than that. If you have multiple matches, that means you don't have a clear match on the local address book. You might want to ask the user or just not assume they're the same thing, the same person. All right. Once we have a person, we need to-- So for that, this is similar to the code I showed in the slides.

We're going to first get the URLs for the person. Then we need to mutate the multivalue. So if we did actually get one, because some people might not have URLs in their record yet. So we're going to create a mutable copy of that URL. of the multivalue, rather. Next, if there were no URLs on that person, we're actually going to create a mutable multivalue. To do this, we're just going to call ABMultiValueCreateMutable and pass in the string property type because the URL is all the strings.

Okay. We got a mutable multivalue. Next thing we need to do, actually add the value. In this case, AB Multivalue, add value and label, pass in the mutable multivalue, pass in the string we actually want to set in there, and the label. In this case, we're going to use social.

The last argument, in this case we're ignoring, that's the identifier for the multivalue entry that's going to be created. Once we have that, we actually need to set that multivalue back onto the person. So, AB record set value, pass in the person, pass in the property we're setting. Again, it has to be the same one we just copied it from, the URL property. Pass in the mutable multivalue. . When we are done with that, release the mutable URLs.

And then we probably want to save the address book. I'm going to cheat here and not actually do it for the purpose of the demo. All right. With this, we have our array of people. We need to still sort them, because if we don't, they're going to come back in whatever order they were in on the server, which might not be the best order for once they're on the phone. So we're going to go ahead and sort the people.

Again, this is an S-mutable array. We're going to sort using function. There's a bit of a strange typecasting here because there are CF types and Objective-C types. So this is actually -- the function works just fine in Objective-C. You might just have to typecast it a little bit.

Then you pass in this function that's defining the address book framework. Here we're going to pass as context the sort ordering. Again, we're not really interested in changing the sort ordering the user is going to see, so whatever their preference is, that's what we're going to use. Alex Aybes All right. It's a pretty long method, but we have people that we downloaded from the web.

All right. Now we're going to display them. In the TableView cell for root index path, this is where the TableView actually creates the cells to display. If you have not -- I've missed the iPhone TableView session and are not too familiar with the TableView, don't worry about it too much. It's pretty simple. But again, I'd recommend watching the videos later on.

So we're going to actually set the text of the cell to the name of the person. For that, we're going to get the people, get the actual person at that particular index in the table. Again, don't worry about that one too much. And then we're actually going to get the name. For this, we're going to use AB record copy composite name, pass in the person, and we're going to get a name.

Then once we have that, set it as the text of the cell. And release the name since it's been set on the cell. And then we return the cell. With all that, we can actually run the application. And there we go. We have Anna and John. Those are the two people that are on the Web as well as on my phone. We probably want to see more than just the people that actually intersect those two groups. So let's go back to the code.

Here you see that I'm really only creating a person. This is where I actually get a person, if I have matches in there. If I don't have matches, I probably also want to have a person representing that web person. So here we're actually just going to create a person.

This is a person that's going to live outside of the address book. It's not a person that's in the user's database yet. And that's perfectly acceptable. You can create EBRecord objects that do not live in the address book.

[Transcript missing]

Next, we're going to add the URL in there as well. For that, very similar to what we did just above here. We create immutable multivalue of string type.