WWDC2010 Session 119

Transcript

>> 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.
Alright okay.
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.