Alexandre Aybes: Good afternoon everyone.
I'm Alexandre Aybes I'm a software engineer on the iPhone Team.
Last week I was busy filling in your mailboxes.
Today I'm going to focus on Address Book.
More and more, nowadays, people want social features in their applications, in your applications so we're going to talk about a few easy ways you can actually put people in your application and then include some of those social features in there.
So what are we going to cover today?
Four things: We're going to start off with a little overview of Address Book.
For those of you who have never seen Address Book we're going to make sure we're talking about the same things, highlight the main objects in there.
For those of you who have used Address Book, whether it be on the desktop, Mac OS X or on previous version of iPhone iOS we're going to I'm going to highlight a few new features of iOS 4.
Once we're done with the overview, we're actually going to put that in practice and write, we've written a really cool little demo that we're going to show you.
Once we're done with the iPhone demo we're going to take a look at some of the things you need to do for the iPad and then finally talk about a few user experience improvements we can make to the app, namely responsiveness and now the exciting new world of multitasking.
Some of the things you need to do in that context.
So that's what I'm going to talk about.
I'm not going to go over every single bit of API in the framework, so no long API listings in my slides, you'll see a lot of code in the demo though but what that means is that I'm going to need you to read the fantastic documentation that's available online, also available in Xcode.
So with that let's actually get started.
So what's Address Book?
There are two parts to Address Book.
At the lower level we have the Address Book framework.
It's a C framework based on Core Foundation.
We have a huge C frameworks on the iPhone whether it be core graphics, Core Foundation obviously and Address Book.
If you're not too familiar with C or Core Foundation most of the objects returned by Address Book can be tie cast to their objective C equivalent and be used that way in objective C so it's really easy.
On top of that framework, we have the Address Book UI framework, so two separate frameworks.
The Address Book UI framework provides a lot of U controllers you can just plug directly into your app and we're going to cover those in just a bit.
So with that let's get started the Address Book framework.
At the beginning there is the Address Book.
From that you're going to find sources.
Sources or a source it's something new we added in iOS 4.
I'm just going to tell you where the contacts come from but I'll get back to that in a minute.
Inside the source, you're going to find a number of groups, this case my friends and my co-workers.
In each of those groups you're going to find people, three friends and one co-worker, actually two co-workers.
You can see we have people who are in multiple groups as well.
You can also have people who are in no groups at all directly attached to the source.
So they're the four main groups of object you're going to find in the Address Book framework.
Let's take a look at that first one: the Address Book.
So what is the Address Book?
Well it's your starting point for anything that has to do with people in iOS.
It's your connection to the database.
Without it you can't access the contacts.
You can actually have multiple Address Book instances.
The Address Book object you can create multiple ones of those and they all access the same database, the same set of contacts on the device.
So that's the Address Book.
The second one in there is a source.
As I mentioned the source is new to iOS 4.
It represents, it indicates where contacts come from, it's the source of contacts.
In this particular screen shot we have two sources highlighted.
On my iPhone on top an exchange at the bottom.
We have a number of different source types available in iOS 4, those include the local one, in this case on my iPhone, Mobile Me is another type of source, Exchange and CardDAV.
CardDAV is the technology behind the Mac OS X server Address Book server.
We also have a couple other like the global address list and exchange and LDAT I believe.
There's one thing to note about sources.
There is a one too many relationship between the source and the people.
What this means is that if you delete a source all the people associated with that source also get deleted so there's a strong relationship between those two.
So that's the source.
The next thing we can look at is the person.
So what is a person?
You've all seen it on the phone in this case in the contacts application this is the view for Kate.
The person object in the Address Book framework can represent either an individual, in this case Kate, or an organization like Apple.
It's a collection of properties; those properties can either have a single value, like in the case of the name at the top, the birthday down at the bottom, or even the image.
All of those are single value properties.
You'll see a little later in the demos how to access those.
You can also have multi-value properties.
In this case Kate has two phone numbers, a mobile and a main phone number so that's pretty much what I cover for a particular person.
We'll see more in the demos.
There's one more thing, I've mentioned sources, I mentioned person, well there's something new in iOS 4 that I want to highlight now and it's linking.
What is linking?
As I said you can have a corporate source where you get contacts from your exchange server.
Let's say I'm also friends with Kate so I also have her personal information in my MobileMe account.
There you go the personal version.
So in iOS4 now we will actually link those two records and present the user with a unified version of the cards.
So what does that mean for you?
Like I said you have multiple records, this is important, you have the corporate source, the exchange source bringing you one record and you have the MobileMe one bringing you another record.
Those two are automatically linked by the framework.
The user can also link them manually if they chose to.
How do you access those?
There's a simple API call that I'll show in more detail in the demos which is essentially just this: AD person copy array of all linked people.
You pass a person get all the main people.
So in the demos we'll go over this in a little more detail.
So that's linking.
The last final object I want to mention in the Address Book framework is the group.
You're probably all familiar with it, this is again the same screen shot as earlier.
The top level contacts application.
In this case we have two groups: The friends and the co-workers.
The group, excuse me, the group is a many-to-many relationship.
Like I mentioned early on you can multiple people in a group obviously, otherwise they wouldn't be a group and you can have people who are in multiple groups.
There's no ownership between the person and the group.
If you delete all the people from a group, the groups still there, if you delete the group the people are still in your Address Book.
There's one thing I want to mention, I want to highlight rather, is that not all source types support groups.
For example it's the exchange source type does not have any groups, instead we represent if you're familiar with exchange you have folders in exchange, those folders are represented by individual sources.
The reason for that is that in exchange you cannot have an actual record be in multiple sources at once.
It ends up being a copy of that record.
If you change one the other one doesn't automatically get updated so to represent that we made folders sources.
Alright that's pretty much all I wanted to cover in the Address Book framework.
Let's take a look at the UI layer, the Address Book UI framework.
In that framework we provide to you a lot of view controllers that you can just plug into your app and reuse really easily.
I'm going to highlight three of those.
The first one is the PeoplePickerNavigationController.
It's there it's pretty much the entire list of contacts.
It's there for you to allow the user to pick a particular person or to pick a particular phone number for example.
The second one is the Person View Controller.
It allows you to present a contact, present their information and a little editing so that the user can make changes and the final one is the Unknown Person View Controller.
You've probably seen this, this exact one in mail when you're actually getting an email from somebody who's not in your Address Book if you tap the little chevron you'll be presented with a name, an email, and options to add to the Address Book.
So this is done using the ABUnknownPersonViewController.
Alright that's pretty much the end of the overview, now we're actually going to put this together into a little demo.
So we wrote these really cool apps that's all about photo cutouts with a lot of help from our intern who apparently is not here, oh he's here, I lost him.
So photo cutouts, photo cutouts you might be familiar with them, you see them in fairs and carnivals, big giant cardboard images of silly things with the hole to stick your head through so your friends can take silly pictures of you and then black mail you later with them.
It looks something like this.
So what are we going to actually do in this demo?
We're going to let the user pick a cutout then take an actual contact, then take the contacts image, put it in the cutout and then finally we're going to present the contact information to your user.
And to do this I'd like to introduce Clare on stage.
She'll do this.
Thank you [ applause ]
Clare Kasemset: Hi everyone.
My name is Clare Kasemset and I'm going to be showing you how to use the Address Book in your app in three ways.
First, we'll see how to use the People Picker to display a contact list inside your app and also take user input.
Second, we'll see how to use the Person View Controller to display contact information within your app and third we'll take a look at the new API provided in iPhone OS 4 yes to take advantage of data from linked contacts.
So let's get started.
So we've already written some code for this application but we're missing many of the Address Book portions so I'm going to build and run what we have so far.
As you can see there's a button in the top right and when I tap it I'm given the choice between many frames so I can swipe between them and I can tap one to select it.
So at this point in the app we like to have it so when the user taps the cutout a contact list slides up so they can choose one of their friends to put inside the cutout.
So let's write the code to do that.
Going back into Xcode, now the last screen we just saw was a cutout view controller and we're viewing the .M file for that right now.
There's a method called PhotoTap which gets called when the user taps the cutout.
So here's where we want to create the people picker so we do that using the usual alloc init incantation.
Next, we'll set the Address Book on the People Picker to the Address Book that we're using in our app and that way when the user chooses people.
The People Picker can tell us about people from our Address Book.
Next, we'll present the people picker so sliding it up modally and finally let's not forget to release it so that we don't leak memory.
So that's the code to present the People Picker but now to do something meaningful with the People Picker, we need to have a way for us to communicate with it, so in order to do that we'll declare ourselves as a people picker delegate.
To do that I'll open up the header file for this class and declare that we implement the People Picker delegate protocol.
Once we've done that let's go back to the .M file and set ourselves as the People Picker's delegate.
Now we've just promised to implement the People Picker delegate protocol which means we need to write three methods, so let's go ahead and write those now.
We set aside a section just for those methods to keep our code organized.
The first method is the easiest to write.
This method gets called when the user cancels the People Picker and in that case all we need to do is dismiss the People Picker since we presented it.
The second method gets called when the user selects a person from their contact list.
Now you'll notice that this method returns a boolean and that's because really this is a question.
The People Picker is asking us should I continue after the user selects a person?
If we say yes then the People Picker will slide a card for that person onto the screen but if we say no then it's going to stop where it is and let us handle it.
So in our case we don't want to show the person's card, we only care about the photo on the person's card which we're going to put in the cutout so here we would return no.
This is also our opportunity to take whatever data we need from the person so you can see that the person that the user chose is passes an argument to the callback so in our case we'd like to copy the image data off of that person using the Address Book framework call AV person copy image data.
Now if the person that the user chose does have a photo we can do something meaningful here, we can set a couple of the properties on the cutout view controller that will take care of displaying the image on the screen and letting the user move it or scale it.
Just as before, we also need to remember to dismiss the People Picker when we're done with it.
Now in the case where the user chooses a person who doesn't have a photo, we can simply display an alert telling the user that they should choose someone else.
So that's two out of the three People Picker delegate methods.
The third one is not actually important in our case.
So the third one would get called if the user were viewing a card in the People Picker and decided to tap a phone number or an email address in it.
But since we're not showing cards in our People Picker we don't have to do anything special here we just need to implement the method so that we fulfill our promise.
So there we've just implemented the People Picker delegate protocol.
Now let's build and run the app to see what we have.
Again I'm going to tap the plus button, I'm going to swipe until I find a frame I like and then I'll tap that.
Now this time when I tap to add a photo a contact list slides up and if I chose my good friend Ana, her photo will go on the screen.
I can scale it, using two fingers and move it into place and there is our first cutout.
So that's how you use the People Picker.
Now the second thing we're going to do is display contact information directly within our app and to do that we'll use the person view controller.
So let's go back into Xcode.
We'd like to have the person do controller slide in when the user taps the cutout, so let's go back to that photo tap method we were looking at before.
You might notice from the structure of this code that there are two states on our cutout view controller.
Either it's editable which means the user is in the middle of creating a cutout and that's where we show the People Picker but this time when we're looking at a finished cutout we want to bring up the contact information so let's create a Person View Controller.
Next, we need to set the displayed person property on it that way the Person View Controller knows whose information to show on the card.
Next, we can set the allows editing property on the Person View Controller.
So this is pretty cool: With no work on our part we can get the person view controller to show an edit button in the top right that the user can use to edit this contact information within our app.
Next, we'll display the Person View Controller by pushing it onto the navigation stack and finally, as usual, we need to release the person view controller when we're done with it.
So as you can see we've written exactly five lines of code.
Now let's build and run the app to see what that buys us.
So I'll tap the plus button and swipe till I find a frame I like and tap that one, I'll tap to choose a friend, this time I'll choose David.
I'll scale the picture and move it into place and this time after I tap Save I'm going to tap the cutout and David Taylor's contact information slides in.
The UI looks just like what you'd expect from the phone or from the contacts app and I can even tap the Edit button and maybe I want to change his phone number and when I press Done that change gets saved to my data base.
So that's how you use a Person View Controller and think looking pretty good but now let's do the third thing which is taking advantage of least contact data in our app.
So going back to Xcode there are two ways we can do this in our app.
The first way is have it so when the user chooses one of their friends from the People Picker maybe that friend has multiple contacts in their data base that have different photos so we'd like to let the user chose which one to put in the cutout.
So to do that let's go back to that People Picker delegate method, should continue after selecting person.
Now originally we wrote code to copy the image off of the person that's passed to us by the People Picker.
But this time let's copy images not just from that person but from all of its linked contacts.
We've written a helper method here called AllImagesPerPerson which can do that for us.
Now let's take a look at it to see what it's doing.
First, it's calling ABPersonCopyArrayOfAllLinkedPeople which gets us a list of the linked contacts for the person and after that it basically does the same thing we were doing before where it copies the image data.
It just now this time it takes images from all of the contacts and throws them into an array.
So going back to our delegate method so on the first line we get all of the linked images, next we'll count them and if it's at least one we can do something meaningful here, so we can set the person property and there are two cases to deal with now, either they're exactly one photo in which case we can do basically what we've been doing up till now, that is setting the person image property and dismissing the people figure.
But if there's more than one image let's present the user with a choice so we can do that using a class we've written especially for this app, which is the same class you saw earlier when you were selecting one of the frames.
So that's the way we can take advantage of linked contacts the first way.
The second way, is using the Person View Controller we can actually display information not just from the person we set as a display person but all the linked contacts as well so let's go back to where we recreate the person view controller in photo taps so how do we get it to pull information from multiple records?
I mean there's only a display person property here but we can do this pretty easily by setting another property that should show linked people property to yes and that tells the Person View Controller look for a displayed persons linked contacts as well and display all their information in a single card.
So that's how you use linked contacts.
Now let's build and run to see what we have.
Again I'm going to tap the + button and at this point I'm sure some of you are wishing that we could save what we've done before, so let's tap this frame and I'll tap to add a photo.
This time out through the contacts who I know has 2 contacts in my Address Book, so Kate Bell, so when I tap Kate Bell I now get a choice between her sad professional photo and her fun photo.
If I tap that photo it goes onto the cutout view controller and I can scale it and move it as usual and press Save.
Now when I tap the cutout you can see that this Person View Controller is showing unified info which means that the information is coming from multiple records and if I scroll down the card I can even see from which records this information is coming.
So there you have it, our app is looking pretty good.
It takes advantage of the People Picker, the Person View Controller and linked contacts to add some great functionality.
Thank you [ applause ]
Alexandre Aybes: Go back to the slides here.
Alright so that was a pretty cool demo.
Just to highlight a few things.
Like I've mentioned earlier we have a lot of view controllers built into the Address Book UI framework that you can just plug into your app.
Whether it be the People Picker to present a list of contacts and allow the user to pick something or the Person View Controller that allows you to just present information for a contact and even lets you easily let the user edit that person.
It will take care of all the saving, all the editing, all the formatting and everything.
The other thing Clare mentioned is linking.
It's a new feature in iOS 4, pretty sure everyone with excuse me just been informed my microphone fell out.
So the linked people, it's a new feature in iOS 4 and I'm pretty sure most people with multiple sources, multiple accounts will actually really enjoy it so I encourage you to actually take advantage of it and again there's just a simple function code ABPersonCopyArrayOfAllLinkedPeople.
So that was the first part of our demo.
Pretty cool little app but there are a few things we could add.
As you might have noticed when Clare was demoing every time she launches the app all the previous cutouts she's built are gone so we should definitely take a look at saving those beautiful cutouts we create, So we're going to take a look at what it takes to save record related and contact related information for in your local storage, in your application.
The next thing we're going to do it's more for more people so we're going to actually look at sharing those user creations, sending them to somebody else.
What is involved when you want to share contact information to another device?
And to do this I'd like to invite Eric on stage, Eric.
[ pause in speaking ]
Eric Gillum: Thank you.
Hi everybody my name is Eric Gillum and I'm going to be talking to you about saving and sharing.
So we've already been using you know address framework and Address Book UI framework and these allow us to create cutouts for our users and display the users contact information and we want to take it a little bit further.
We want to be able to save the cutouts and share the cutouts.
So I'm going to be talking to you about the bits you need to write to disk when you're saving a cutout and the bits you need to send across the wire when you're sharing a cutout.
So let's get started in Xcode.
Now no surprise we're taking an object oriented approach here and we've created a class called cutout that represents a cutout.
So let's take a look at the header file and you can see it's a basic NS object here and we've got a person object that we'll be working with, that's usually chosen by the People Picker and we've got the image which is the combined person photo and the cutout background, super imposed upon each other, and we've got the thumbnail which is a miniature version of that, you'll see that in a bit, and then finally an image name which is a path on the device to that image data.
So when our application wants to save a cutout we need a representation that's suitable to be put on disk so what we're going to do is use a basic dictionary in our case and have the cutout know how to represent itself in dictionary format, so we're going to implement this method together, I'm going to jump to it so now we're in cutout.m. The first thing we're going to need to do is get a dictionary.
So we are locking it ourselves a dictionary and now we need to figure out what we want to save from that person object as far as getting it on disk.
Well the first thing that's a good thing to hang onto is the record ID of a person.
So here you see we call ABRecordGetRecordID for the person object we're working with.
We wrap that up in an NS number and then we set that on our dictionary and the record ID is basically something that every saved person object in the Address Book has, it's a unique identifier with which you can pull out that person information from the Address Book you're working with.
However, you don't want to rely only on the record ID.
For instance what if your user deletes that contact?
You don't want to be dead in the water with your cutout object and no longer able to associate contact information with it so we'll save a little bit more information to be able to help us there and one thing, it's a good thing to hold onto is a composite name of a person.
ABRecordCopyCompositeName will give us a string format of basically the first name, the last name, the middle name, if it was set, several name properties that could have been set on this person object in as I said in a string format so all we have to do is set that on our dictionary as well and then we'll break this part up a bit, we'll go ahead and get the fist name in a similar fashion with a slightly different call, ABRecordCopyValue and then we pass in the specific property we're interested in, the first name property and we set that on our dictionary and the last name as well.
These are both probably in the composite name but you'll see why we want to break it up momentarily but same sort of deal.
Last name, grab it form the record, set it on the dictionary, and we want to take a little time to save one more bit of information and for our applications purposes the emails will do very nicely.
So here I'm creating an array to hold all of the emails and Clare and Alex have mentioned linked people so we're going to get all of the emails for all of the people linked to this person object so we go ahead and do that function call ABPersonCopyArrayOfAllLinkedPeople and for each one of them we're going to work with the emails.
Now a record can have more than one email.
So it should return a multi value when you call ABRecordCopyValue and pass in the email property.
So preparing ourselves to work with a multi-value we're going to do something that makes it a little simpler and stay in objective C land by calling this function, ABMultivalveCopyArrayOfAllValues and casting to an NS array which is toll free bridged with a CF array so once we have those we can add all of them to the existing array of emails that we're keeping track of and in this way we've got all of the emails for all of the linked contacts and then last step there we set it on the dictionary.
Now I'm going to do three more things that because we're working with image data have to be done but they're not all that interesting from an Address Book point of view.
We're basically going to get the image if we have that and set that on our dictionary, get the thumbnail as well set that on our dictionary and finally that image name, set that on the dictionary.
So now we have a nice representation of a cutout object in dictionary format and we can save that to disk.
All we have to do is to allow the application or whoever is responsible for saving call dictionary representation on this cutout object but that's only half of the puzzle.
If you know how to save you also need to know how to load and it won't be too surprising I'm sure if loading consists of basically doing the reverse right?
Now that we've saved dictionary representations onto disk, we'll pull them off of disk and create cutouts from them.
So that's what this method does here.
Still in cutout.m with dictionary representation and you see we're also passing along the Address Book that we're working with.
Why? Because the first thing we're going to do is pull up the record ID from that dictionary representation.
Remember it was wrapped in an NS number so we have to unwrap it but then we call this function: AB Address Book get person with record ID and we pass in the Address Book that we're working with.
This will basically look up that person object by ID and give it right back to us so it's a straight forward way to load up a cutout with the person information we're interested in and then because we're dealing with image data we go ahead and grab the image and the thumbnail and we reconstruct the image portions of this cutout object.
But as far as saving and loading that should be it.
Put it into a representation, write that to disk, pull it out of the representation and you've got a cutout object in memory.
So let's build and run and see this in action.
So our familiar home screen with nothing saved.
Tap +, chose a cutout, tap to add a photo, let's go ahead and use Ana, make it look nice and tap Save now the true test here will be if the user say shuts down their phone, here I've just killed the app but say the user shuts down their phone and then launches it and launches your app again we've still got the saved cutout and moreover it's still attached to the relevant contact information.
So that's saving.
A great way to extend your app, your users will really appreciate that and I'm also going to talk to you about sharing.
Basically sending a cutout from one device to another one and so the first ting we're going to need right away is a share button so I'm going to jump to the cutout view controller which we've seen before and we've basically got a stubbed out method where we can add the share button, update save share button I've got a nice little slot where I can just put in a share button.
That'll replace the save button in the case that the user has already saved their cutout and now they want to share it and as far as what we need to do to share well again it shouldn't be too much of a surprise, I'm going to jump to a class called the gallery view controller which that's actually the home screen table view that we always launch to in our app and you can see here our cutout view controller will say it's ready to share the cutout and it passes the person object that it's working with.
Well all we need to do to send that out across the wire is create a dictionary representation of it with two important things that we need to keep track of here.
We don't want to send along the image name because that's on the device, on the sending device, it's not specific to the receiving device at all so we pull that out of our representation and don't deal with it when sending across the network, likewise we don't want to send the record ID because that came from the Address Book on the sending device.
The receiving device has a completely different Address Book and record IDs are not transferrable between devices.
So we don't mess with those items in a representation.
We go ahead and strip them out but that's it as far as sending.
It's very straight forward.
But now imagine we've just sent a cutout and we're on the receiving end well our application is responsible for pulling those bits in and showing a cutout and you'll remember in the cutout object.
We were only prepared to work with record numbers so far.
Well now since we've specifically stripped out the record number it won't come to us on the receiving side, we need to be prepared to do something else to associate the contact information with the cutout.
So if we don't have a record number to work with we can pull other information from that representation and work with that.
In this case we've got the composite name and the emails and with those we'll be able to match against the Address Book that we're working with on the receiving side.
So I've got a helper function here, copy person, matching name, emails in Address Book.
Let's jump to that and see how we would implement that.
So still in the cutout object we start without a match and right away we can call this handy function, ABAddressBook CpyPeopleWithName and that'll give us an array of people all of which will match the name that we pass in and since we've passed in composite name you know first, last or whatever properties were set on that contact we'll likely get a match.
So given that we have some people to work with if we've got 1 match we can be fairly certain that this is the person that we're trying to match and just return that out of this function.
The possibility that there are multiple people means what we should do is try and hone that search and in this case what we can do is use the emails.
So for each person that we're working with that match that name go ahead and work with the emails which again are multi-values so we grab the emails from that record and in objective C land we call this function ABMultiValueCopyArrayOfAllValues, that gives us the emails and an array format and then from there it's just array by array matching so these couple of lines here we basically go through all the emails in that array, try and match against the emails sent across the wire and if we've got an email match given that we've also got a name match, excuse me, we can be pretty certain that that's the person that we're thinking about.
So jumping back to the init method.
There we are we've got a person by matching the composite name and emails.
There's one more case to consider.
What if I've just made a cut out of my mom and I send it to my dad's sisters cousins you know wife, twice removed on her mother's side?
She knows my mother but my mother is probably not in her Address Book so we would like to allow the user to ultimately add this person into their Address Book without having to you know jump away from your app and go into the contacts app and you know it should all be done right from your app.
So in the case that we didn't match a person because it wasn't actually in the Address Book on the receiving side, we can create a person.
So if we haven't got a person what we can do is use again some information from that dictionary representation to construct a person.
In this case we'll be using the first and last name specially and the emails and here's another helper function that we're going to implement that creates a new person with those properties.
So let's jump to that and see what we can do.
So the first thing we need to do is create a person object and this function does just that.
It gives us a valid person object that isn't necessarily associated with an Address Book yet but we can set properties on it, so we set the first and last name, fairly straight forward, set the first name property with the relevant data and the last name same way and of course the emails.
Since emails are given to us as multi values we should be working with multi values when setting emails on a record we create ourselves a mutable multi value of string property type because emails are represented as strings and then set each email in the array to that multi value and then once they're all in the multi value we set the actual multi value on the person passing in the email property.
So now we've got a person object in memory that has s first and last name and some emails.
So summing up here: No matter how we get to this method, no matter who is asking us to create a cutout with a representation, we're always working with a person object, whether it's by looking it up by ID, matching it by name and email, or creating a new one entirely and the only thing we have left to do really is allow the user to add this person to their Address Book.
So in this specific case here we want them to be able to update their contact information with this new information sent across the wire.
So if we go back to the cutout view controller what we'll want to do is give the user a means to add to their Address Book and we'll do that with an Unknown Person View Controller.
So back to this photo tapped method where you can see Clare's wonderful 6 lines of code that you know handle the known person case with a Person View Controller.
I'm going to wrap that in an if else clause, so here it is, same 6 lines but now it's for the case that we know that we're working with a person from our Address Book.
If we call ABRecordGetRecordID on a person object and it's equal to the invalid record ID then we can be sure that this person is not associated with our Address Book and we should show an unknown Person View Controller.
So let's create ourselves one and right away we should set the allows adding to Address Book property to yes because at the point of this exercise is to allow the user to update their contact information, then much like with the person view controller, set the displayed person on our unknown Person View Controller to that person that has the first name and the last name and the emails, set ourselves as the delegate and then push that view controller just like we pushed a Person View Controller.
And a word on this as the delegate we're responsible for at least one method and we've implemented it here.
Its Unknown Person View Controller did result to person which passes a valid person object and in that case what we're responsible for doing is again setting some properties on our cutout view controller but moreover simply saving just like if we were creating our own cutout view controller locally.
All we need to do is go through the same motion of saving that person object, which will go through the routine of creating a representation associating that record ID with it because now that they've been added to the Address Book they have a record ID, packaging it up and then it'll be saved on the receiving device.
So that's sharing.
I'm going to demo this for you and in order to be able to demo it, I'm going to switch to a device because what we've done is implement the sharing stuff with email attachments and to be able to use email I'm going to switch to this device here.
Can everybody see that ok?
I guess my shadows in the way.
Anyway first I'll show you how to share so I open our app and here you can see Anna Haro which we saved earlier.
Tap on her, notice the Share button in the top right here.
If I tap Share we slide up a mail controller which allows you to send an email to somebody with an attachment, which his basically a cutout representation.
So it wouldn't make much sense to send it to myself for the purposes of this demo, instead we've got some emails, use that, we've got some emails sent.
If I look at this one John Appleseed, well he's in my Address Book.
If I tap that and open that attachment in my application, photo book we'll see it loads up the cutout and there's John inside of the cutout, if I tap the cutout it'll show John's contact information.
That was the matching with the composite name and the emails.
Now if I go back to mail and back to my inbox and check out Tina Fam well I know her she's a friend of a friend so if I tap that email and again open the attachment in my application, here it is, the cutouts loaded and here's Tina and if I tap on her cutout I'm given an unknown Person View Controller where I have the option to create a new contact and that's exactly what I as a user want to do because I know Tina but she's not yet in my Address Book.
So create new contact and now we see that because we set the displayed person on the unknown Person View Controller we already have her first name and last name filled in as well as her email so as a user I don't need to do anything else really I can just tap done and the Address Book UI takes care of saving that to my Address Book so now when I tap Tina it shows her contact information with a Person View Controller this time and I can edit it as I want, she's in my data base.
So that's sharing, another way to extend your app.
Thanks [ applause ]
Alexandre Aybes: Thank you Eric.
Can be outside.
Alright so we have a pretty cool app now and just to recap some of the things Eric just showed you.
The first thing he did was save, so save some information.
What do you need to save when you're trying to save contact information?
Like he said the record ID is the main way you can get back at an actual record in Address Book so save the record ID.
He also mentioned that's not quite enough you might want to save additional information.
The main reason is that the user could delete that contact from their Address Book and you'd end up being stuck with just this number.
So saving extra information helps.
In our case we save the name as well as the email addresses.
In your application, maybe you want to save phone numbers, or street address, depends on what you're actually doing in there.
So that's worth saving locally.
When you want to send information, send contact related information, you need to not send the record ID.
The record ID is as Eric mentioned valid only on one device so when you're sending it do not send that across, it's not going to make sense in the receiving Address Book.
So instead you want to send this extra information you saved and on the receiving side you want to match, just try to find that contact in the Address Book.
One good way to match is through the name, records ID don't' sent them.
So match using the name.
How does that work?
There's one handy function to do this in the Address Book copy people with name, that'll get you all the people matching a particular name.
We'll do our best to actually find people even with partial names so if you only have the first name and last name but this local Address Book as a prefix, a suffix, the title, etc. will still match those.
So once you've matched using the name, if in case you get multiple people, you can refine that search using the extra information you've saved and sent across like email addresses in our case.
So that's good now you can be pretty sure of finding that record on the receiving side.
But in case that record is just not on the receivers Address Book, the ABUnknownPersonViewController is there so that you can allow your N user the user to actually add that record and all the information you've packaged and sent to their own Address Book and the Address Book UI framework will take care of all the details of saving, adding, allow the user to edit etc. It's really easy to use.
This is good.
We have a good iPhone app.
Let's take a very quick look at some of the things we want to do for the iPad.
What is it going to look like on the iPad?
The sample code associated with the session already has all these changes including the iPad changes so you can definitely I recommend you check it out.
It looks something like this and the main thing with change with regards to Address Book is that now when we're presenting the Person View Controller, this person information we're presenting it in a popover, so it looks something like this.
The rest as you can see it's still the unified info, the rest is very similar, but rather than presenting full screen and card Person View Controller defiantly use the popovers.
So overall it's very few changes as far as Address Book is concerned.
There are a few changes for the UI, a couple of different nibs but as far as Address Book there's very few changes.
The main one being using popovers, the rest the Address Book UI framework, the Address Book framework will take care of; it's mostly the same thing.
We'll even take care of some of the details of how the Person View Controller behaves once its inside a popover.
Alright so that's the iPad, it's pretty easy.
The last thing I want to talk about today is some user experience and some improvements we can make in that area.
The first one is going to be responsiveness.
There's nothing worse than launching an app, waiting, waiting, waiting, and being back at the home screen because the app got killed because it took too long to launch.
So we're going to take a look at some ways you can improve that and avoid that preferably.
The other thing we're going to look at is like I mentioned earlier the multitasking world means your application is going to stay around, suspended, eventually for a much longer time.
So that means that other applications could change the Address Book while you're running so you need to respond to background changes.
So let's take a look at that first one, responsiveness.
What is the lengthiest thing we're doing in this demo?
In this particular case it's matching against the Address Book.
It's all fine and dandy when you're on your own device and you're testing at work with your 100 contacts.
When you're a corporate user with this massive contact data base of 150,000 people, I've seen a data base like that it's frightening, when you're trying to match against that it will take a little bit longer.
So one way to avoid getting killed immediately on launch is to do the matching in the background, so on a background thread.
What is involved?
There's one trick to matching in the background and in the Address Book framework and the main thing you have to be aware of is that the Address Book object, the AB Address Book is not thread safe in the sense that you cannot use it on one thread and then continue using it at same time on another thread.
Instead, you need to create a new instance of Address Book so that you can have one let's say in the main thread and one in the background thread.
This is true of the Address Book, this is also true of records, any record you pull out of that Address Book any record you match, you cannot pass that record to the other thread instead you need to pass record IDs.
The record ID is just a number and you can use it to find that record in the main thread.
You can also pass actual values if you want like the first name, the last name or the email addresses.
Those are also ok just not the record.
So what does is look like in code?
The first thing we're going to do is detach a new thread with a particular selector in this case our background matching method is going to run in the background, makes sense.
What does the background matching look like?
First thing we're going to create an Address Book to use in that background thread, then we're going to call this handy function to match people with that particular Address Book and this is all code that's similar to what we saw earlier, inside that match people with Address Book.
So that will return to us an array of records, an actual Address Book records so what we want to do with those extract all the record ID so we could go through all of those records, pull the record IDs and build an array out of that.
Again once we have those record IDs we can send them back to the main thread.
Those are safe to pass around threads and then once we're done passing it back to the main thread, release the Address Book instance, we're done with it, we don't need to worry about it anymore.
On the main thread you're best friends going to be AB Address Book, get person with record ID passing the main threads Address Book.
That way you will get records you can use in the main thread.
So that's good.
Now we're matching in the background, we can take all the time we want to match those 700 million contacts in that data base and we're good, we're still not going to get killed on launch, that's good.
So the other thing I mentioned I wanted to talk about is multitasking.
How does this affect you now that iOS 4 supports multitasking?
Your apps live longer and stay around so that means that you need to be aware of changes that happen in the background and for that we have a simple function to allow you to register for callbacks when something changes.
That functions pretty simple.
AB Address Book register, external change callback.
Keep passing the function pointer that gets called whenever something changes in another application.
This is also true by the way in different threads, when you have different threads operating on Address Book, you can register for changes from one thread to the other, so you can get call backs when something changes on different thread.
Once you get that callback what do you want to do?
Revert. There's one simple call, ABAddressBookRevert.
What does this do?
Well it will drop all the caches that are already in memory and force Address Book to reload from the data base next time you ask for any of the properties.
This means that you get fresh data out of the data base when you query for it.
So once we've reverted, the next thing we want to do in our case is redo the people matching in the background, it's good.
Once we're done with the people matching if we had changes we'd probably want to refresh the UI.
This one thing I want to mention about ABAddressBookRevert that's important to remember is that not only does it drop the caches but any unsaved information you have in that Address Book will also get reverted so if you do have unsaved changes, you might not want to revert.
Instead you can actually save, save those changes.
Address Book framework will do its best to actually handle any conflicts that might have happened.
In 99% of the cases it'll be just fine, the rest we'll do our best, be sure the last one wins.
The call to save ABAddressBook Save could return you an error if something wrong happens.
Alright so that's all I wanted to mention about multitasking.
I'm just going to summarize a couple of things.
The first thing this new really cool new feature: Linking.
Really I want to encourage you to take advantage of it.
It's a subtle change but for those people with many accounts or many records from multiple accounts, it's really going to make their life as an N user better so I really encourage you to play nice with the linking.
Multitasking of course it was a highly requested feature, now it's there and now you need to pay attention to it.
So background changes, you know make sure to register for those.
And the last thing I want to point out is that we have a lot of functionality in there, a lot of view controls that we provide, a lot of APIs for Address Book so that you can fairly easily we've seen some cases fine line the code you can edit a contact, you can integrate those into your application really easily, really makes your app feel at home on the phone and lets you use the users contacts and everything, it's really, really nice.
For more info I encourage you to email Mark, our Evangelist, he loves to get emails.
Check out the documentation, big slide on documentation, it's really good.
It's available on the website, it's also available in Xcode and finally you're all in the developer forums so you can ask each other questions and even ask us questions on the developer forums.
A couple of sessions: Multitasking, I love to talk about multitasking Friday in the morning, if you're still awake after the beer bash at 9 a.m. you can go check out multitasking repeat if you haven't already seen the one I believe it was yesterday or this morning so two repeats of the multitasking sessions.