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 may have transcription errors.

Good morning, and welcome to "Address Book for iPhone." My name is Alex Abis. 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 exposing 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 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 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 gonna show you. So we're gonna 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, and 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 will 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 KPIs 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? 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 AB_PERSON view controller. So we're going to use that. We're going to set its displayedPerson 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. because this is the first thing that shows up when the user launches the app. 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's 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 the 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 PersonViewController. So again, looking back at the code, we have... Three, five, six, seven, eight, nine. 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 do 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 AB 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-- a native application to your users. 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.

in the cloud. You have people on the phone, or rather, you users have people on their iPhone already. 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. So 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. I'm going to talk a little more about the address book create in a second. But I'm going to just Mentioned 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 -- It 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 have been typed. 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 match that name. All right.

The first line, it's pretty simple, but there's quite a bit to cover in there. So let's go ahead and look at AB Address Book and this AB 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. Maybe 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 AB 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 AB address book. And every time you call this function, AB 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 AB 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 will toll-free bridge to the equivalent Objective-C object. 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 To get the value, we'll use 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 -- 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 setting 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 start 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. All right, single-value properties, fairly simple. Let's take a look at the multivalue properties I talked about earlier-- phone numbers, email addresses, URLs, et cetera.

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 gonna say that all the time.

that ABMultivalue 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 ABMultivalue ref that's for phone numbers. This ABMultivalue ref has a number of-- values and labels in it. In this case, three. One of--the labels are home and work in this case. One important thing to note, though, is that you have two home labels. 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-- entries for the home number in there. It's important to keep in mind.

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, abmultivalue.getCount 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 multivalue, 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 by the index. 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, you can pass in the built-in ones, or you can pass in any string you want. The last item that I haven't actually talked about yet is the identifier. Each entry in the multivalue actually has an identifier associated with it.

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 re-- 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-- 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. 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, when, like, as I had 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, you know, in a reasonable order rather than whatever order they were added in on the-- in the server.

So we need to sort them. Then we need to actually get a name that we can display. to the user. And then finally, we need to actually display it. And this is mostly going to be, in this case, just a table view with cells in the table view. Let's take a closer look at the first item in there, the sorting.

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 gonna 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 gonna 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, AB person sort ordering, the sort ordering, AB 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 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, Abus, 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 actually exactly the same, except, as I mentioned earlier, CF types can actually be cast into their foundation-- foundation equivalent. In this case, CFStringRef can actually be used as an NSString, so 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 context. 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 gonna focus mostly on the address book API for this. So we have our AppDelegate. All the AppDelegate does is use the SocialPeople 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 have -- 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. AB 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 AB address book reference. And we pass in the full name we just created. Again, cf ns, you can cast one to the other. All right.

Once we're done with the people, we're actually gonna 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-- update that person. 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 abmultivalue create mutable 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, ABmultivalue, add value on 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 gonna 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, passing the person, passing the property we're setting. Again, it has to be the same one we just copied it from, the URL property. Passing the mutable multivalue. All right. When we're 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, 'cause if we don't, they're gonna 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 B address book framework. A, B person compare people by name. And 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.

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 a row at 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.

They're actually really nice containers for people and properties. All right. Once we've created the person, we're going to set the first name, the last name. Again, this is very similar to the first demo we saw. AB record set value. Pass in the property we want to set. Pass in the name.

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 a mutable multivalue of string type. Then we That is not all we need because we don't want to leak memory. So we're going to auto-release that person. Again, you can use the same Objective-C functions or CF functions, Objective-C methods or CF functions. So auto-release the person. This person is then going to be added to our array of people.

And that's all we need in this case, because there will be automatically-- since they're the same A/B person type, they're actually going to be used by the cell, and you can copy their composite name, and we'll do all the right things. All right, so when we run this, we actually have the full list of people-- my full list of friends-- yes, I only have five friends-- that I downloaded from the web. And again, we see John and Anna. They're actually in my address book. And those are the three people that are not in my address book on the phone. All right, great. Except for the first-- or the second demo, rather. So what did we just see?

Searching for people by name, really simple. One function call, you'll get a bunch of people that you found. Then we used the multivalues to actually update data in those people on the address book on the phone with the data we got from the web. And then finally, sorting and displaying the people.

For that, again, we provide really handy little functions for you to do it. So this is nice. But we probably want to do a little more than just displaying a list of contacts. So let's actually-- go a little deeper, and we want to really show more than just the name.

We want to show the details. In this case, John, which, as you saw, is already in my address book. And you can see on the-- we're going to actually display the full card for that person, the full person view for that person. As you can see here, his social URL is already in there. So how are we gonna do that?

For this, we have the person view controller. We actually saw it briefly in the very first demo, but we're going to use it again here. So the address book UI framework creates this AB person view controller. And it has three properties that I want to talk about right now. The display person, that's where you actually set the person you're going to display in that view controller. The display properties. This is an array of properties if you want to filter the properties you're actually displaying for that person.

In this case, if you just want to have URLs, for example, you could do that. In our particular example, we want to display the full list of properties. And finally, the allows_editing, the really simple Boolean flag to actually let people edit those contacts. You might want that. It might not work in your particular app flow, so you have the ability to turn it on or off.

All right, that's good for people who are in my address book. For the people I downloaded from the web who are not in my address book, I probably want to let the user actually add them to their local address book. Let's take a look at this. In this case, Paul is not in my address book.

So for Paul, we're going to display a slightly different view. It's, again, going to have all the information that I downloaded from the web. In this particular case, we're just downloading first name, last name, and URL. But you could have a lot more information in there. And it's now going to have a couple extra buttons that create new contact and add to existing contact. This will let the user merge that data into their own local address book.

And this is actually going to be very simple to do. We have an unknown person view controller, the AB, unknown person view controller, that has also three properties I want to talk about. The display person works the same way the display person worked for the AB person view controller. It just tells the view controller what properties to display, or rather the data to display.

The second property, the allows adding to address book, is sort of parallel as the unknown version, unknown person view controller version of the allows editing. It tells the view controller whether or not to put those two buttons at the bottom that we saw. In some cases, you might not want to have them. So again, you have the ability to turn it on or off. And finally, the delegate.

going to be a callback for the unknown person view controller. And this is what it looks like. Unknown person view controller did resolve to person. This is called when the user is done actually creating a new contact or adding that information to an existing contact. This will pass in the second argument to that method is the actual person that was either created or the person that was already in the address book that the user added all the information to. So let's actually take a look at how to do this. Back to a little demo here. So back to address book.

So to do this, we're going to have to display little blue arrows on the side, the little chevrons. Again, this is where we left it. We have this list of people, and that's it. You can select them. It won't do anything. So in the code, we're actually going to add a couple methods that the table view needs to display those chevrons. Again, I'm not going to go into details about what they actually do.

If you've seen the table view session, you already know. If you haven't, check it out on video later. So this tool of methods, if we now run it, we have the blue chevrons in there. They don't actually do anything yet, because that's the next step in our little demo. So to make those blue chevrons do something, We have to implement this table view accessory button tap for row with index path.

So in there, I'm actually going to add some code. This is a lot of code, but we'll walk through it. Don't worry. Again, we get the person out of our array of people for that particular row that was tapped on by just calling self people objected index and passing the row. This is very similar to what we did to display the cell right here.

All right, once we have that, we're actually going to check that the person is actually in the address book. Remember, we have two sets of people in that array. One type of person that's actually in the address book that we got using the Azure Searching, and the other type that we actually just created. A newly created person has an invalid record ID. So we're going to check whether it's a person in the address book or not that way.

We're going to get the record ID. If it is not invalid, meaning it's valid, We're going to display it as a regular person. So again, create a person view controller with AB_PERSON_VIEW_CONTROLLER, alloc in it. Set the person. In this case, we're going to allow editing, because why not? And then we're gonna push that view controller onto the navigation controller stack. Again, this is view controller stuff. You can brush up on that later, including later this afternoon. All right, once we've done this, release the person view controller. Next, we actually want to deal with also people who are not in the address book yet, letting the user actually add them.

For that, we're going to use the ABUnknownPersonViewController I just talked about. Very similarly, allocate that particular instance, and then set to displayPerson. And then set allows adding to address book. If you don't actually set that to yes, the buttons will not show up. Once we've done that, push it into our navigation controller with animation, and we're done. Let's actually run this. Yes, I do want to save. Now, we have the blue chevron, and remember, John is actually in my address book. So when I go see John, there we go. We have his full card with the URL and everything. We can even edit it.

Back in there, we're actually going to see Paul. Paul I mentioned, Paul is not in my address book. But really, he's a really good friend, one of my five. So I'm actually going to add him to address book. And with that, we have the unknown card viewer. And remember, all we did was push the unknown card viewer onto the navigation stack. And now we're going to get a new contact display. Or if we want to actually add this information to an existing contact in our address book, we can actually just get it right there. And we can browse the entire address book. Again, all I needed to do was push an unknown view controller in there, an unknown person view controller in there. All right. That's how to display contacts. Thank you.

So what do we just take a look at? If you have people you want to display and possibly edit, use the AB Person View Controller to let your users add record information to the address book, AB Unknown Person View Controller. Again, very simple, self-contained. You just push that onto your navigation The thing that we need to still worry about. We're talking about networking, web services, things that could potentially be slow. The connection is not always the fastest.

So how are we going to do this? This is something where you would really want to consider doing things in the background. You can use the basic APIs, the NSThread APIs that are available in Foundation. Or if you're more familiar with the Pthread APIs, those are available as well on the phone. I'm not going to go into details about how to do this. However, I do want to talk about how this relates to Address Book, and particularly the Address Book threading model.

In Address Book, each A/B Address Book instance needs to be used on only one thread, meaning that if you have multiple thread, each and every one of those threads should have its own A/B Address Book instance. This goes back to what I mentioned earlier. This is why we allow you to create multiple instances.

And it's important to remember, this is actually very similar to what we do on the desktop, either in Leopard on Address Book on the desktop, or if you're familiar with Core Data, This is also very similar to what Core Data does. You have multiple managed object contexts that you use on every single thread, and then you get objects individually from those contexts on the individual threads.

So you cannot pass address book references across threads. Neither can you pass any records you actually got from the address book. They also should be used only on one thread at a time. However, what you can pass between threads are values. Anything you copy from the address book, whether it be the name or even the phone numbers, you can pass those bits and pieces across threads. The other thing you can pass if you do need to actually transfer data from one thread to another are the record IDs. You can pass the record ID from thread A to thread B. And then in thread B, once you have that record ID, you can look up that record using the thread B's address book instance.

With that, that's all we really needed to do. We got our three steps for the social networking website. We--application, rather. We downloaded the people, updated those people with informa-- we downloaded the people, searched the people locally, updated them, and then displayed them. Great. So let's take a look now at this other example we're gonna talk about. Adding people to an existing application. You want to connect your users to their application. So we're going to add their friends into there.

For this, I'm going to use this ongoing example we've had, the recipes application. Don't worry if you have not seen it yet. There are still chances for you to see it. This is the third time we actually used that example. We used it in the ViewController session, in the TableView session. We're going to use it more this afternoon and tomorrow. So basically, if you've missed the sessions, this is a Recipes application. It displays recipes. So let's take a look at this new version of Recipes.

In version 1.6, because we did 1.0, 1.5, and 1.6, and this afternoon we're doing 2.0. In this recipe application, now we're going to add recipe sharing. We're going to allow the user to send an email with the particular recipe. In addition to that, we're going to add recommendations. Once my friend tell me that they really, really like this recipe, I'm going to be able to add them as people who recommended this recipe. You can see here on the right, We have a new item called the Share button, and we have this little section called Recommended By, and John apparently recommended the chocolate cake.

Again, if you're not familiar with the recipes application, you can actually download it. It's attached to the session and the attendee site. So you can play with it. All right, let's take a look at the first-- new feature, the emailing the recipe to my friends. For that, we need to add the Share button.

I'm not going to go into details about how to add the button in the table view. But once that button is there, when the user clicks it, we're going to pick a person. Once we have a person, and more so once we have an email, we're going to build an email URL and open it. And this will just launch the mail application, refill the contents, and the user is free to email them. All right, let's take a look at the second item in there. That's really the big address book part of that. So picking people.

This is what it's going to look like. We have the list. Press the Share button. And we're going to bring this picker. So the AB PeoplePickerNavigationController. This is also a ViewController class, a ViewController subclass that the address book UI framework exposes. And it's all ready to use. And we're going to see how to use it.

This is a navigation controller. So you can't really push it onto the navigation controller stack. In all existing applications-- and this is probably what you want to do too-- you're going to present that navigation controller on top of your existing navigation stack. I'm not going to go into detail about what this means, but--because it's going to be covered this afternoon, the Mastering iPhone View Controllers session at 2:00 p.m. in Procedure. I'll be there. But essentially, what it boils down to is that when you have the card view presented already, we're going to--as you saw in the previous one-- we're going to present the PeoplePicker morally on top of it.

That's for presenting it. The next important thing we're gonna look at is the delegate. The people picker needs a delegate. And there are three methods on the delegate that are gonna be called. The first one is when the user presses the cancel button. you're going to get a message. All right. Cancel. So you're essentially just going to dismiss the people picker at that point. The second method that's going to be called is the selection. Whenever a person is selected in the picker, you're going to get a call back. And you're actually going to be asked a very simple question. We'll see that in a minute.

And the last item, the last method, is called when the user selects an individual entry, an individual value in the picker, in the view for that particular person. We'll take a closer look in the demo at what those methods look like and what type of things we want to do. Now, this is all we really need to do for the sharing. Let's take a look at the other feature we want to add.

Adding recommendations. So a few steps. We're going to add this little section. Again, I'm not going to go into too much detail about that. Table view controllers. Awesome. The next thing, we're again going to allow the user to add a particular recommendation. So there's going to be a button, and we're going to bring a picker, very similar to what we just saw earlier. Then we're going to get a person. With that person, we actually need to store that person our recipe format. So let's actually take a look at how we're going to do that particular part.

To store a person, what do you need to do? You get this record. The best thing to actually put in any kind of data storage you have is the record identifier. That record identifier is an integer. So you're going to get the record identifier, and then you're going to need to serialize it. Serializing it, we'll see. You can do it with archivers or however you actually prefer to do it. Then you need, when you come back, you need to deserialize it.

We'll take a quick look as well how to do that. And then finally, once you have the record ID, you can look it up in address book. The way this works in code, to serialize it, You have a person called ab_record_get_record_id. I mentioned that earlier in one of the demos. I will get you an ab_record_id.

With that record ID, you can create, for example, an NSNumber and then use the archiver method to actually serialize that number to a file, a data blob, however you actually want to put that in there. You can also just store it in your SQLite database just as an integer. All right. Deserializing it, very similar. You actually do the deserialization, pull that out of your file format, then you can If it was stored as an NSNumber, get the integer value out of it, so-called int value. You're gonna get an AB record ID, which again, just an integer. And then we're going to look up that record in the address book. The AB address book get person with record ID will actually get you a record with that particular record ID.

This is good, and this will work in most cases, but what if the address book has actually changed since the last time you ran your application? Maybe that friend isn't a friend anymore. So before you actually display and use that record you got from the address book, you want to make sure you actually got a record from the address book. You're not guaranteed that this record ID is still valid. So you need to make sure that corresponds to a record still.

In addition, in some cases, you'll actually still want to information for that contact, regardless of whether they are in the address book or not. So you might want to consider storing extra information. This does not apply to every application. In some cases, as I mentioned, you don't want to keep records that are not in the address book in your application. So in that case, you'll just discard that particular record ID. But in our case, if John one day said he wanted to recommend this recipe, and he's no longer in my address book for some reason, I still want to say that John recommend the recipe.

So we're going to store a little bit of extra information. And the code, very simple, very similar to what we just saw. You're going to get the record ID, look up the person. And the way you actually make sure that you have that record is just by checking that it's not null. If it's not null, that means you actually got a real record. The record is still in the address book database. So you're going to use the person. If the record is null, then you're gonna fall back to your other data or remove that record ID from your data storage. All right, with that, let's actually put people in the recipes application.

Back to Xcode, I'm going to close the social book and open the recipes application. There's quite a bit of code there already. That's code that's been built up over the last couple of sessions and a couple of extra things I've actually added. Let's run the recipes application. Again, this is the recipe list at the beginning. If I click on a recipe, I see the ingredients, the instructions, and I've already added the Share button and the Add Recommendation section and button. Currently, they don't actually do anything. So let's actually go ahead and implement the Share button. Let's go back to Xcode.

In the table view, didSelectRowAtIndexPath, which is the method that's actually called when the user selects a particular row, we're going to add some code to show the people picker. Here we have the code from the previous sessions about the type section and the instructions, et cetera. At the end, we're going to first declare a people picker. Next, we're going to actually create a people picker if the section that was hit is the actual share section. Each of the sections in TableView has a particular index. So to allocate the people picker, just AB_people_picker_navigation_controller, allocate it. That's all you really need to do there.

The next thing is to actually set the display properties. Again, we're trying to pick an email address. So the only property we're really interested in, in this case, is the email address. If you actually don't set that when you're actually trying to pick more than just a person, we're going to show everything, and the user's going to be allowed to click on phone numbers. Kind of hard to share the recipe.

Yeah, a phone right now. So just going to do email. The way we're going to set this is creating an array. with an NSNumber representing the particular property. In this case, the KAB_PERSON_EMAIL property. It's an integer. We need to wrap this into an NSNumber and then put that inside an NSArray. I want to assign that to the displayed properties property of the people picker.

The next thing we need to do is set the address book for that people picker. Sorry. I managed to paste that in the right place. All right, we're going to set the address book. This is important because we have a local address book in our detailed view controller. And in our view controller, we use an address book. And we want to make sure the people picker uses the same address book as we do. So this will avoid loading extra data, and will make things happier generally. All right, we set that.

The next thing we need is to actually set the delegate on the people picker. might look a little funny. We're going to reuse this people picker in a minute, so that's why I'm sort of separating those two out. So if we did already create a people picker, we're actually going to set ourself as the people picker delegate.

Then we're going to talk more about the delegate in just a second. Then we're actually going to present the PeoplePicker. We're going to call presentModalViewController. passing the people picker, and we're going to animate this. If you're not familiar with the model view controllers, again, check out the session this afternoon on mastering iPhone view controllers. We'll talk to you about model view controllers and how you present them, how you dismiss them, et cetera. For now, we're going to focus on the Edirsberg side of things.

We have most of the thing in there, but I mentioned that we are the PeoplePicker delegate. PeoplePicker delegate, well, as a PeoplePicker delegate, we actually need to implement a protocol and a couple of methods, actually three methods I mentioned earlier. So for this, we're going to go to the header, and look at that. How handy. I've already typed it. We're going to adopt the protocol, the AB PeoplePicker Navigation Controller protocol. Sorry, AB People Picker Navigation Control Delegate Protocol. It's a handful. And go back to your implementation. And then implement the few methods we need to implement. The first one is the cancellation.

PeoplePickerNavigationController did cancel. This is called, again, when the user presses the Cancel button. All we need to do in this case is dismiss the ModelViewController. And we do want to animate it because the user needs to know what's going on. All right, the next method we're going to implement is the PeoplePickerNavigationControl should continue after selecting a person. This is called when the user presses on the person.

In some cases, and including the one we're going to see just a little bit later, you don't actually want to continue. But in this particular case, we want to go ahead, and once the user has selected a person, we want to show the view for that particular person.

So we're going to return yes. This means I'm going to slide in the person view controller in the picker. Again, this is all automatic. You don't really need to do anything for that. Just return yes. And then the last method we need to implement is the PeoplePickerNavigationController. You ready for this? Should continue after selecting person, property, and identifier.

All right, what does this mean? This is actually called when the user selects an individual property in the view for the person. In this case, we don't want the picker to actually continue. Because continuing after that means, well, if they pressed on their phone number, I'm going to call that person. They pressed on an email, we're going to compose an email. Well, we do want to compose an email, but we want to compose our email, not just any email.

So we're going to return no. But before we return no, I'm actually going to do something. And here's a little bit of code to do something. All right, what are we seeing here? We first, again, the goal is to actually send an email to that person with the recipe. So the first thing we do is actually get the emails from the person. This is, again, an argument to this method. This is a really long method. Should continue to have selected person, here we have the person. So get the property. In this particular case, the property has to be emails because that is the only thing we're allowing in that picker. And then we get an identifier that we're gonna use in just a second, actually right now. So we have the emails in an AB Multivalue ref. Then we're going to get the index for the identifier that was selected by the user. For that, AB Multivalue get index for identifier. Again, gives us the index. All the access to the multivalues by index. So once you have that, you can get all the values and labels you want. So we're passing the emails, multivalue ref, the identifier, and get the index. Now, to get the actual email, we're Call ABMultiValue copy value at index. Pass in the emails, the multi-value, and the actual index.

Once this is done, we have this very handy little send recipe via email method. So we're going to call that passing the email. I'm going to show you what it actually does in a second. And then we're going to release the email. 'cause we don't need it. And I forgot to fix this in my code, and we're actually leaking the emails. So let's release the emails as well. With all this done, we don't need the model view controller anymore, so we need to dismiss it. All right. Let's actually run this.

I'm going to do a little bit of hand waving here. You'll see in a second why. This is the simulator. I don't actually have mail installed in the simulator. So we can't actually send the email. But believe me, it works. I've tried it. All right, so I'm going to press the Share button. We're going to bring out the People Picker. Again, I can navigate through the entire address book right there. Apparently, I have no work contacts. All right. So here I can see the entire address book. I can even search in it. Again, you have nothing to do to get that there. It's all in the picker.

I actually want to send the recipe to John because he's a big fan of chocolate cake. So there we go. We have John. If you remember, John's card earlier had a lot more information. Since we limited the contents to just be the e-mail address, that is the only property we're actually displaying here. So once I click on this e-mail, this is when mail opens. You didn't just see that. All right, so mail opens, and we'll compose the URL-- we'll compose the e-mail, rather. All right, with this great email sent, we're going to add the other feature into there, the recommendation section.

This is going to be very similar to what we just did in the share section. Again, right here in the didSelectRowAtIndexPath, we're going to add another little if clause right there. If the section is the recommendation section, if the actual row selected is the last one, because we're actually going to display all the people who recommended this recipe, followed by an add recommendation button.

So if this is the last row selected, we're going to-- create a people picker. And then we're going to send an internal flag in here to just tell ourselves that, well, this is the picker for recommendations. We're using the same view controller as the delegate, so it needs to know what mode it's in.

One other thing I forgot is to actually set the address book for that people picker. All right, with this done, we're We're creating a people picker, sending the address book. Then here we're setting ourselves as the delegate. And then we're presenting it. The only thing we need to change now is this delegate callbacks. Cancel, we still want to dismiss the picker when we cancel. But now what changes is the shoot continue after selecting person. In this particular case, we're only interested in selecting a person. So we're going to do that.

Here, if we're in the PeoplePicker recommendation mode, the Boolean we just said earlier, we're going to add the person to a recipe object. The recipe object is our little model object that maintains all the information by the recipe. It's the one implementing the actual storing. I'm not going to go into details. It's essentially the same code you saw in the slides. And you can actually download the sample code, the recipe sample code. It's associated with the address book session as well the other four sessions that talk about it. So you can download it and take a look at the code in more details.

Once we've added the person to the recipe, we're going to reload our data to actually show the person in there. And then finally, we're going to dismiss the ModelViewController. Important here, we don't want the people picker to slide in the next screen in there, so we're going to return "no."

If we don't do that, as the Pitbull picker dismisses, we're going to have the slide at the same time to show the card to the person. Really not going to look good. All right, with this done, I've already implemented the displaying of the actual cells. You can look at it when you download the code, the sample. So with this done, we're going to actually run it, try it out.

So add recommendation. After I sent him the recipe, John called me back. loved it. So he's definitely recommended it-- recommending it. So I'm just gonna do that. Select John, and there we go. We have John as someone who recommended that recipe. And again, we have the blue chevron. You can actually see the details of John, 'cause why not? All right. With this... What did we just see? Presenting a PeoplePicker navigation controller modally. You're going to present it, create the PeoplePicker navigation controller, present it. Then you need to implement delegate callbacks, store record IDs. Again, that's the way to store people in there. There's one last item I want to mention here.

It's about notifications. What happens when the database changes while your application is running? Well, we have a callback mechanism. So in order to get a callback, ABIdrsBookRegisterExternalChangeCallback This is going to be a C callback. And your function is going to be called whenever the address book changes. Then what? Usually two things you want to do. Revert the address book, and then update your user interface.

And this is what it's going to look like. Here in the recipe detail view controller, the view controller we're just looking at, we're going to register for a callback using AB address book register external change callback. Pass in the address book we want to register for notifications on. passing the function we want to have called, and then finally passing a context.

In this case, the context is going to be the view controller itself. And I see why in just a second. This is the actual function. It gets back three arguments. The address book. A dictionary that contains information about the changes. Or it might contain information about the changes in the future. And the context. Again, first thing we do is revert the address book. This will actually load the new data from the address book. And then we tell our view controller to reload the data. This will cause it to relay out and redo all the right things in there.

All right, this is good. There's one last little thing I want to mention about notifications. Or a couple, actually, things I want to mention about notifications. questions. I mentioned reverting. There are some cases, although rare, where you don't actually want to revert. You can actually ignore those changes. And if you have done a number of modifications to the address book, you might not actually want to revert. This will lose all your changes.

But if you do want to refresh the UI, if you haven't made any changes, then definitely revert. The last one is, how does this work with threading? I mentioned earlier you can have multiple address book instances in different threads. Well, this is a great way, the callbacks are a great way to get notified when a particular thread changes the address book and saves it. Once that thread saves, it's actually going to message all the other threads about the fact that it's changed. you're guaranteed to get the callback in the thread where you actually registered for that callback. So it's all thread-safe in that sense, and it will notify all your different threads and address books. All right, and with this, this pretty much sums up what we had time for today. Actually, we have two minutes and eight seconds left.

So again, use the label CAPIs. Those will let you access the people in the address book. modify them, et cetera. If you're not so comfortable in the basic core foundation types, most of those types can actually be cast to Objective-C types. So you don't need to worry about it too much. And finally, we have a great set of view controllers that you can actually plug into your application and really get a lot of the flow of the address book directly into your application.

All right. And with that, we also have a great lab right after this. I'm gonna be there. A number of the other engineers will be there, so we can answer all your questions. If you have more questions after the conference, you can call Mad Rants-- or actually, just send the e-mail. And you can check out the address book preparing guide for iPhone. And it's really great documentation right there.