Configure player

Close

WWDC Index does not host video files

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

URL pattern

preview

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

$id
ID of session: wwdc2009-104
$eventId
ID of event: wwdc2009
$eventContentId
ID of session without event part: 104
$eventShortId
Shortened ID of event: wwdc09
$year
Year of session: 2009
$extension
Extension of original filename: m4v
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2009] [Session 104] What's New ...

WWDC09 • Session 104

What's New in Cocoa Touch

iPhone • 43:46

iPhone OS 3.0 includes many enhancements to the UIKit framework that accelerate your development and improve your iPhone application's user experience. Familiarize yourself with new additions including In-App email, new table cell styles, an improved user interface for search, and much more.

Speaker: Chris Parker

Unlisted on Apple Developer site

Downloads from Apple

SD Video (111.5 MB)

Transcript

This transcript has potential transcription errors. We are working on an improved version.

My name is Chris Parker. I work on the iPhone Frameworks Team; and today I'm going to be spending about the next hour telling you about everything that we've put into UIKit and some other frameworks to help you guys write better Apps. So it's a lot of API.

Starting out just on UIApplication canOpenURL is a companion API to OpenURL and this just checks to see whether or not the URL that you're passing us-- remember when you're installing a bunch of applications on the device you can register for different URL schemes. This tells you whether or not an application has registered for the scheme for that URL so this will allow you to be able to control the UI for when you're launching other applications via URL. There are some new delegate methods on UIApplication.

Application didFinishLaunchingWithOptions is the new delegate method for finding out when you got launched and how you got launched. So this dictionary will contain a number of different key value pairs. One of them will be LaunchOptionsRemoteNotification if you were launched via the PushNotification service which is now in iPhone OS 3.0. You'll get a small dictionary as the value of this-- it contains information about the RemoteNotification that launched you.

And LaunchOptionsURLKey and LaunchOptionsSourceApplicationKey-- these indicate-- you've got launched via OpenURL and the URL will be the value of URLKey and the Bundle ID of the launching application will be the SourceApplicationKey; so now you can find out a little bit about how you got launched and who launched you.

And if you got launched via the new Spotlight screen on the home screen, this will contain a URL for that also; so we've actually seen a couple of Apps that get a little flummoxed by this, so you may want to check and make sure that your App is working correctly in the face of getting launched via Spotlight.

So the Push notification API-- I'm sure everybody is psyched to see this appear in iPhone OS 3.0 via the basic API involves registering for RemoteNotificationTypes and you can unregister for RemoteNotifications and you can also find out which ones you've actually registered for. And the types are Badge, Sound and Alert, and these methods control what you've registered for, right? So you might register your App for Badge, Sound and Alert but the user may have set it so that they're never going to receive a SoundNotification. So you'll register for certain kinds of alerts and the user will control exactly which ones they're going to allow to interrupt them.

Associated with this, the Push notification delegate methods tell you whether or not the notifications were you actually successfully registered for those notifications, and whether or not you received one. So didRegisterForRemoteNotificationsWithDeviceToken this gives you a little cookie that tells you that you actually checked in with the RemoteNotificationServer. DidFailtoRegister, this one tells you whether something went wrong. And that NSError should contain an entire set of localized recovery suggestions and things like that that will give you an error dialogue suitable for presentation to the user.

And didReceiveRemoteNotification, if you're already running and you get a RemoteNotification from the Push notification service, we don't want to have to go through the whole UI so this actually gives you an opportunity to look at that dictionary and handle that RemoteNotification yourself. Chris Marcellino and one of the engineers from the service side of this are going to be giving the Apple Push notification service talk Thursday at 5 p.m. I think that's right here in Pacific Heights so you don't have to stay here the whole time. You can go and see other talks and come back for that one; but they'll be here talking about the Push notification service so you can get more information there. Tuesday, well you can stay here all day if you want then.

Knock yourself out. Proximity monitoring-- we now have public API for getting it to Proximity sensor that's in the Device right so when you move the Device up to your ear and the screen goes out, that's controlled by the proximityMonitor. There's a non-autonomic property here for is proximityMonitoringEnabled, so that allows you to find out whether or not it's enabled and to turn it on and off, and the proximityState.

So if you get back a yes from this it means that the proximity sensor is telling you that something's close to the device. You can also register with the local notification center for the ProximityStateDidChangeNotification; this tells you as the State changes so you can go back and check that ProximityState value to find out the value after the notification.

Also we have battery monitoring on the UIDevice now so you'll be able to find out exactly what the state of the battery is. There are a couple of different uses for this-- one might be to present UI that matches your UI in your game if you're doing something specific, but also just finding out what the state is. So there two properties associated with this-- the batteryState and the batteryLevel.

And the States are these things here. Whether it's unknown, so we might not be able to tell you at all times exactly what the State is, Unplugged, Charging and Full. If the user has unplugged it, you're probably drawing power, you're on battery power at that point. Whether it's charging, it's plugged in and actually pulling power into the battery and when it goes full.

And you'll also be able to just query that batteryLevel property which is a unit so it goes from zero to one as a float, and that will tell you what percentage the battery is. There are also notifications for both of these so if you register with the local notification center, you can find out when the batteryState changed, so as the user plugs and unplugs the cable, when the batteryState changed and the Level; so as the Level decreases or increases while it's charging you'll get notifications for those as well.

And at that time you can go back and check those other properties. UIImageView gets a couple of new methods now and with highlightedImage. So highlightedImage is the Image that gets displayed when the UIImageView has a highlight, and this just lets you set up both the Image and the highlightedImage at the same time.

You have a property for getting at the highlightedImage and a property for finding out whether or not the UIImageView is in the highlighted state. This third one here, highlightedAnimationImages is kind of new. When the UIImageView is highlighted, you can actually provide an NSArray of UIImages to use for your highlighted animation.

So if you want to have a whole series of things playing while the UIImageView is highlighted, you can use this thing and it will play the images in sequence. There are some recommendations about using this. It's recommended that your UIImages are all the same size and have roughly the same color balance and stuff like that. The key thing here is that the content mode will govern how this stuff gets scaled.

So if they're not the same size, some images will be scaled up or down to fit in the UIImageView. If you set this property, it overrides the highlightedImage property. So it's one or the other; you're either using the single highlightedImage or you're using an entire NSArray of highlightedImages.

So UINavController-- we have a bunch of new methods on UINavController and this is to help give some better UI as well as to do some bulk operations. So setViewControllers animated is a way to be able to set a whole series of ViewControllers-- a whole stack at one time. And the animated property tells us whether or not to animate the top one in that stack up over in the place.

And we've also given some control over the toolbar, so you'll be able to find out whether or not the toolbar is hidden and set the toolbar in place in an animated fashion or not; and the toolbar property itself, you'll be able to get at the toolbar directly given UINavigation Controller. And you'll be able to access those toolbarItems and the Controller that they come in in an animated fashion.

And we've also built into UIResponder the Motion detection API's. So the methods that you'll get as a Responder, so remember you're in the Responder chain you're going to be able to trap a whole bunch of different events that happened on the way up the Responder chain. motionBegan withEvent; motionEnded withEvent and motionCancelled withEvent.

And those are just the indications about the user doing something with a motion that we recognize. Right now we recognize pretty much one motion, a ShakeMotion, so you're going to be able to pull a type and a subtype out of a UIEvent; and these are new methods in iPhone OS 3.0.

And they're just going to allow a little bit more control over what kinds of things are happening, so as we increase the number of motions that we recognize, you'll be able to find out more about it here in the future as well. There are two different types-- Touches or Motion, so obviously the type for the events that you've been getting recently are all UIEvent TypeTouches. UIEvent TypeMotion is for the motion events; and the subtype is where you're going to find out exactly what kind of motion it was.

And right now again the only one that we support is the ShakeMotion. So we also now have cut, copy, and paste and these also are on UIResponder; so as you implement the cut, copy, and paste methods and select and selectAll on your classes that are participating in the Responder chain, that's part of how we determine what UI to show the user when they actually go for the cut, copy, and paste UI. And on UIApplication related to this we also have applicationSupportsShakeToEdit which is going to tell us whether or not to trigger the undo motion and things like that on shaking the device.

Also canPerformAction withSender-- this is your opportunity to do some additional customization so even if objects in your responder chain respond to cut, copy, and paste, but there's some reason that some of those actions aren't appropriate, you can implement canPerformAction withSender. The action here will be one of those selectors, either cut or copy, paste, select, selectAll. And if you return no from here, that's your opportunity to say well, we do normally, but not right now. And then the action will be removed from the menu when the menu actually gets displayed.

And also on UIResponder is a new NSUndoManager. So if you've been using NSUndoManager on the desktop, this is NSUndoManager on the iPhone. It's the same class. It actually works the same way. If you haven't, it basically allows you to provide a stack of invocations that you can either play back or rewind depending on what actions the user is taking to do undos. So if you were to, for instance, do an insert Event, when the user does the insert, you might register the undo action as being a delete for that range of text for instance.

There's some ways you can group things with an undoManager, so you can begin and endUndoGrouping, you can find out what groupingLevel you're in, and the undo stack is managed by these groups. And when the user does an undo, you can tell the UndoManager to actually trigger that undo and it will rewind everything to the undoGroup, to the current undoGroup. Undo and redo work the same way. There's also some control for groupsbyEvent.

So you get a UIEvent in, you're actually going to handle that UIEvent. Any of the undo actions that you register during that UIEvent are automatically grouped into a single undoGrouping. And these methods allow you to be able to control whether or not that behavior is in force. So this is the default, groupsByEvent is yes by default. If for some reason you need finer grained control over the undo works, you can use setGroupsByEvent no and that gets you out of that mechanism. So you can't do any of this stuff without a Pasteboard so we do have a UIPasteboard class.

And there are a few methods on that-- this is just a smattering of them; but the big hitters are generalPasteboard so this gets the general cut, copy, paste, Pasteboard right from the UIPasteboard class. And this is the one that you're going to probably use the most; PasteboardWithName create allows you to set up your own Pasteboards with your own name. If you pass no to create and it's not there, you'll get back nil; if it is there you'll get back the Pasteboard.

And PasteboardWithUniqueName gives you an opportunity to be able to get Pasteboards that will not collide with other Pasteboards on the system. So we're assuming that there are going to be a lot of Apps taking advantage of cut, copy, paste whether it's implicitly-- just by using our controls or whether it's having a custom Pasteboard to do some of their own behaviors with Pasteboards so this is a good way to be able to get a Pasteboard that isn't going to collide with anybody else. If you register with the Default Notification Center, you can find out Notifications about when the UIPasteboard changes, and those will include things like types were added to the Pasteboard or types were removed from the Pasteboard.

And you can also get Notifications about the Pasteboards being removed so as Pasteboards come and go you can find out about that as well. The items that are placed in the Pasteboard are based entirely on Universal Type identifiers, so if you've been working with Pasteboards on Mac OS 10 on the desktop, this is all stuff that's in the core services framework in UIKit or in Cocoa Touch. It's in the mobile core services framework.

We support single and multiple items on the Pasteboard as well as we provide a number of convenience API's for the data extensions for common things; so Strings, URLs, Images and Colors. So a lot of things you're going to want to put on the Pasteboard to either move to other Apps or in your own App, there's already API for doing all of that stuff. You can put your own data on the Pasteboard just by producing NS data for that as well.

And as part of this the UIMenuController is the thing that actually puts up the cut, copy, paste UI-- that nice little bubble that shows up where the cursor is selected. So the sharedMenuController, there's only one, you can get it from this method, sharedMenuController, and it has a number of different configuration API's whether or not it's visible and whether to set it visible in an animated fashion. If you're using the property raw, it's just going to come in; if you use the animated version you can control that.

setTargetRect inView-- this is your opportunity to be able to actually position it in the view. So if you're using standard controls like UITextView and things like that we'll take care of positioning it correctly relative to the text. But if you've got a custom view and you've got your own data that's involved in this, this is your opportunity to be able to position that menu right where you're drawing or where the thing is that's being copied or pasted. And you can also tell it to update, so for whatever reason the State's changed in your application and if you call update, we'll walk through and figure out what responds to what and the canPerformAction withSender API.

And we'll actually update the menu automatically. Our very own Andrew Platzer will be giving the cut, copy, paste on iPhone talk in Russian Hill on Wednesday at 3:30, so if you're going to be doing a lot of cut, copy, paste or if you want to know more about it, please go to that talk.

It will be really informative on this new feature. Wow, there are still more slides. UIScrollView-- there's new methods on ScrollView that allow you to control how fast the deceleration rate happens so when the user flicks the ScrollView and the rate starts to decay on the flick, you can set this to UIScrollViewDecelerationRateNormal or RateFast; and the property's decelerationRate. We did catch a few applications trying to get their own values in here, please don't do that.

Use these methods and if you pass us any value, if you just pass us something crazy, we are going to clamp it to one of the normal or fast. So we're trying to give the user a consistent user experience here using ScrollViews, and if everybody has their own version of this where it decelerates at different rates, it's very confusing. So we'd like you to use these. We also have ZoomScale so now you can control the zooming.

In the UIScrollView programmatically you can set the ZoomScale directly in both an animated fashion and you can zoomToRect. So if you just set the scale, we'll just go ahead and scale that up and down and if you set a rectangle we'll go ahead and zoom right directly to that rectangle.

So those are pretty straightforward. There's a bunch of API new UITableView as well One of the things that with the advent of the search API's that we have is now this UITableViewIndexSearch. So remember we ask you for what index titles to put down the right hand side of that TableView.

If you return this as part of that array, UITableViewIndexSearch, we'll put the magnifying glass right there in the slot that you tell us to. We do recommend that you make this the first item in that array, so that when the user taps on it and they wind up scrolling all the way to the top the search bar actually appears right there. Don't put it at the end or something insane like that. reroadSectionIndexTitles-- really basic API. It just lets you tell us to go ahead and pull new index titles so if something is updated, you can tell us to refresh that information.

So some additional convenience API on TableView, new methods for reloadSections withRowAnimation, and reloadRowsAtIndexPaths withRowAnimation, and these guys just tell us to go through and reload the appropriate data. Now you used to have to either do a delete and an insert or go through some other machinations for this. This just tells us reload the whole section and the RowAnimations are things that you can pass to us from the RowAnimation [inaudible].

And allowsSelection is going to actually allow you to determine whether or not the TableView is going to go ahead and highlight rows when the user taps on them; so now we've given you control over that as well. Some additional new delegate methods-boy, there are a lot of new delegate methods. TableView willDeselectRowAtIndex and didDeselectRowAtIndexPath so now you actually can get involved in the deselection machinery and find out when that highlight's about to go away so you can do additional work or additional animations and things like that in your TableViewCells.

And TableView titleforDeleteConfirmationButtonForRowAtIndexPath. I don't know if you guys have seen the Cocoa talks but there's a much, much longer selector than this on NSBitmap Image Rep so this is positively short by those standards. But for such a long method, this gives you the ability to customize that button right there.

So for everybody who's been saying, "I want something other than delete there," here's your method. UITableViewCell-- initWithStyle reuseIdentifier. This is a new method on UITableViewCell and it replaces initWithFrame reuseIdentifier. So everybody was, "We can give you a frame but we're just going to resize it when we get it into TableViewCell." So initWithStyle reuseIdentifier is the new initializer for UITableViewCells-- again please also use the reuseIdentifier because that really helps us out with performance and scrolling.

You have a bunch of styles available to you and these are things that we use in our own applications so UITableViewStyleDefault, TableViewCellStyleValue1, Value2, and Subtitle-- those aren't terribly descriptive. This is what they look like. So by default, the UITableViewCellDefault has an image view and the main text, just the text of the TableViewCell. The TableViewCellValue1, this has the text and a subtitle; and Value2 has a different format for that.

One is right justified; the other one is left justified and you can tinker around with the metrics for this and things like that. And the subtitle actually is back to having the imageView and the main text and the subtitle text directly underneath that main text. So again these are things that we use in our own applications and if you're using these styles you're going to fit in very well with the rest of the field with the iPhone.

UITableViewCell new methods and properties here-- if you look closely at the old API, you had direct access to the image and text and things like that right on the TableViewCell. And we've actually deprecated all of those methods in 3.0 and we're giving you direct access to the views that we use to put those things in. So it's a little bit of a subtle distinction.

Rather than assigning an image to a TableViewCell, we're going to go ahead and give you access to the ImageView; so if you call for an imageView on a TableViewCell, and there isn't one we'll go ahead and create it and ven that out to you and then you can set the image on that.

And the same thing with the textLabel and the detailTextLabels So when you're going to be modifying your TableViewCells in iPhone OS 3.0, please use these methods. It also gives us some opportunities to do some optimization where if there isn't an imageView, we're not going to actually create one. It lets us save a little memory.

We also now have hooks to be able to find out when the TableViewState is changing, so when the user taps on the edit button and gets all that nice UI fades in to find out when things are changing, you can override these methods in your UITableViewCell subclasses. So willTransitionToState and didTransitionToState this is how you find out exactly just before and just after those transitions occur, and the States are these DefaultMask, ShowingEditControlMask and ShowingDeleteConfirmationMask, and this is your opportunity to basically animate any views that you've put into the UITableViewCells. So if you grab the content view and you've put some of your own views in there, this is your opportunity to animate those views to provide additional feedback for the edit and delete confirmation behaviors.

So you get a crack at being able to do those for your views. You heard Phil talk about just how many countries the Phone is showing up in yesterday morning. UILocalizedIndexedCollation is a class that we've introduced in iPhone OS 3.0 to make it easier on you guys to be able to take your applications and move with the user's change of their language. So when the user goes and selects a new language in the general preferences, this class is actually going to help you provide new sorting behaviors for your data and tableviews. So the current Collation is an object.

You're going to get it from this factory method and you're going to ask it for various things like the sectionTitles. So in English this is the A to Z column with a number at the bottom, but in other languages it's going to have different things there. So we're going to feed you the sectionTitles that are appropriate for the localization that the users set their phone to. And SectionIndexTitles, these are basically the same thing for the right hand side of the index there.

sectionforSectionIndexTitleAtIndex. I had to read this three or four times too. Don't feel bad. A lot of times when you're working with Tableviews and you've got far more sectionTitles and things like that than you do space in the index on the right hand side, this is your opportunity to make between the two if there isn't a one to one correspondence between the titles that are available and your section; so you basically get to tell us which section to scroll to if the user has typed on a particular indexTitle some place in that index bar on the right hand side. So if you cross your eyes a little bit it makes a little bit of sense; sectionForObject collationStringSelector and sortedArrayFromArray collationStringSelector. These are very similar. For both of these API's the collationStringSelector is going to be a Selector that takes no arguments and returns an NSString.

And when we call sectionforObject with the collationStringSelector-well, you can call it-- what will happen is we'll figure out, we'll call that selector on your object and that's going to return an NSString and then we'll use that string to figure out which section of the localization that object would belong in. So this is your opportunity basically to reorganize all your objects into sections that are appropriate for the localization that the user is currently in.

And sortedArrayFromArray, once you've got all of those sections set up, well they might not be in the right order, so sortedArrayFromArray will give us the Array, again the collationStringSelector, we'll sort that Array as appropriate for the sorting rules and the collation rules for the localization that's currently in force. So if you use these, you'll be able to participate in the user's localization much better. And it will be a much cleaner user experience no matter what language the user sets their phone to.

Thanks Mom. So UISearchBarScopes. When you tap on the SearchBar now in mail and in other applications, you're going to get that ScopeBar. Mac OS X on the desktop has had one of these for a while in the finder's search window and things like that. So now we have one here in iPhone OS and you'll be able to control this. This particular example is from some sample code that's out on the Web for searching but again it's the same one that we're using in mail and other applications.

So you can find out whether the SearchBar shows the ScopeBar. You can set that with the showsScopeBar API. ScopeButtonTitles is the Array. It's going to have the titles for the buttons in that segmented control there; and selectiveScopeButtonIndex just tells you which one is currently highlighted. The ScopeBar will only appear though if that ScopeButtonTitles Array has two or more things in it. So we're not going to show it if there's just no real scope there. And SearchBar selectedScopeButton Index did change-- another long method for a very simple thing. This just tells you when the user taps on the ScopeBar and the new item becomes highlighted.

It's a verbose language but we love it. We also now have a SearchDisplayController so with all this search API being available, actually setting up the search and having an easy way to be able to control the search is a little tricky. The SearchDisplayController is a way to be able to make that a lot easier. So you'll initialize a SearchDisplayController with a SearchBar and a contents Controller. And 99 times out of 100, your contents Controller probably is going to be a UITableView Controller.

You've already got the TableViewController set up probably for your data, and it's got a delegate and DataSource and it has all that stuff hooked up to be able to display the data directly out of that DataSource. So this is going to work in conjunction with the UITableViewController that you're probably already using. The SearchDisplayController can have its own delegate, so you'll be able to find out some things that are happening there.

And whether or not it's active and in order to set it active in an animated fashion. You can get the SearchBar from it, you can get the searchContents Controller that was it was initialized with, and you can find out what searchResultsTableView the searchResultsDisplayController is going to use. All right so this is pretty significant. It's going to create a TableView for you to display your searchResults in. And the searchResults data source and searchResults delegate-- these guys actually wind up being probably the UITableView Controller that you passed us to initialize one of these things.

And that actually lets you do something pretty slick which is in your TableViewController's delegate methods, TableView, number of rows and sections, things like that; if you're getting TableView from the ViewController that incoming TableView on that method is going to be the one from the ViewController. But if you're getting it from the SearchDisplayController, it's going to be the one from this method that you initialized here.

So you can actually multiplex in your delegate method that you're using in your UITableViewController right now to be able to distinguish whether you're in view all the data mode or whether you're in view some of the data mode; and this is how you can participate directly with the SearchDisplayController API's.

A bunch of delegate methods on this, so we've got some fairly sophisticated notifications on the delegate to tell you when all this stuff is happening. So WillBeginSearch and DidBeginSearch, these are your opportunities to set up your DataSource or do whatever work you need to do just before the search begins.

WillEndSearch and DidEndSearch, you'll also get PNG's for that on your delegate. SearchDisplayController did load SearchResultsTableView-- this is where it's actually going to bring in its TableView to do its work so you can find out when that happens. And all of these methods for willShow, didShow, willHide, didHide the TableView and these are just opportunities for you to find out when all that stuff is happening.

You may want to be able to change some of the UI or stuff like that. SearchDisplayController shouldReloadTableRorSearchString, this is your chance to tell us whether or not there's any work to do. All right so if the user types in a SearchString and if it's the same SearchString that's before, you might get an opportunity to say no from this, and we're not going to go through and ask you for all the search results data and things like that. And the SearchDisplayController shouldReloadTableforSearchScope-- same thing. Let's say you've got your SearchScope up there and if there's no reason to reload the data, this is your opportunity to tell us, "Yeah there's no work to do. Don't worry about it.

Pay no attention to that man behind the curtain." UITabBarController. We've had a bunch of requests for some more access to the UITabBarController behaviors. The first one is you can get the TabBar directly from the TabBarController so just like UINavigationController, we've given you access to the ToolBar it's using, this gives you access to the TabBar the UITabBarController is using. It is read only, please don't modify this. This is just for state checking.

TabBarController shouldSelectViewController; willBeginCustomizingViewController; shouldSelectViewController gives you the opportunity to say no so that when the user taps on a different TabBar item you don't switch. So this is a way maybe to help the user not lose some of their work, things like that. TabBarController willBeginCustomizingViewControllers, willEndCustomizingViewControllers changed and didEndCustomizingViewControllers changed. This is how you find out how the users customize their TabBar and when they've customized it and whether or not at the end of all that operation they actually changed anything.

They might have moved stuff around and then wound up with the same TabBar configuration that they had before. So these are your opportunities to find out when all of those things happen. UIViewController has some new methods for viewDidUnload and isViewLoaded and these are really just opportunities for you to be able to find out-- oh somebody likes those. These are your opportunities to find out just the State of the UIViewController. viewDidUnload is just simply yes it jettisoned the view, and isViewLoaded you get to check to see whether or not the view is loaded without actually causing the view to load.

One little method but very handy. And there's now also some new API and UIViewController that allows you to do a one part animation, and I found OS 2.0 on the rotation there are two parts to the animation-- there's a first part and a second part. And this is actually just an opportunity to do a faster one part animation. So willAnimateRotationToInterfaceOrientation duration-- this is where we're telling you okay users switched orientations and you're about to go through for an animation of this duration.

And you can find out when that happens here. Also wantsFullScreenLayout. Well unfortunately I don't have a screenshot for this but it's pretty simple. UIViewController when it sets up your views, automatically resizes them to compensate for the status bar across the top-- the little thing that tells you that you either don't have wireless or you don't have 3G depending on where you are.

In Mountain View I never have 3G. wantsFullScreenLayout says if you return yes from there, if you set this to return yes this tells us to resize the view so that it fits underneath the status bar there, and if the status bar is translucent, you'll be able to see your view underneath it as things scroll and move around. I had no idea I had so many relatives in the audience. This is great. UIViewControllers also now have some new behaviors from ModalTransitions. So now I have a bunch of stuff that allows you to control exactly how these ModalTransitions occur.

There's a ModalTransitionStyle; CoverVertical is simply the slide-in that we already do; FlipHorizontal is just taking the view and flipping it to the other side and it looks like you've flipped the thing over; and CrossDissolve is a straight up cross fade. If you've been watching Evan Doll on iTunes U with the Stanford University Class that he teaches, you can see him live in the Presidio Thursday at 5 p.m. That does say Thursday, yes. I want to get it right for the rest of the slides. iPhone ViewController techniques and he's going to spend a lot of time going over all of this stuff.

It will be a great talk especially if you're very heavily ViewController based which you all should be right? Good. We have a number of new features also which I'll talk about here. One of them are some Info plist Keys that we would like to turn on in a future version of the OS. They're not on right now but you can play with them in the simulator.

The first one is UIViewGroupOpacity and this has to do with how we deal with opacity in a tree of subviews. So if you set the opacity on a top level view, and you don't set it everywhere else, this has to do with how we wind up rendering those subviews into the render tree and Edge Anti-aliasing, UIViewAntialiasing-- this is going to control exactly how the edges of the views are drawn; if they appear on half pixel boundaries or if they're rotated and things like that and I have actually a brief demo of these.

The first one we'll do is-- let's take a look at the ViewOpacity demo and this is just a very simple application. We have a bunch of people at work who are big space shuttle fans so I figured I'd do something here with that. What I've got here is each of those patches up there; those are the STS mission patches for 124 and 125.

125 is the Hubble servicing mission, and I've just badged those with a really big number 6. And this slider down here at the bottom controls the GroupOpacity so each of those is a single UIView that has two image views inside of it-- the patch and the badge. And what I'm doing here is I'm just setting the opacity on the top level UIView, it's actually the view you can't see, but when I cause the opacity to slide down here-- let me get this down to something like 20% or so.

If I zoom in on this, you see that where those views draw, you can see the patch through the badge which is probably not the effect you want. What we're doing there is everybody is getting their own opacity and we're just letting you see through all of those views.

When you turn on this UIViewGroupOpacity you can kind of see it a little better here on the STS125 patch here. You can see the red line through here and the names and the little galaxy. When I set the UIViewGroupOpacity key in the Info plist, oh here it is. Xcode actually recognizes this-- let me add this key here in the Info plist.

This is UIViewGroupOpacity. Xcode translates it into this nice rendersWithGroupOpacityString. If I turn that on and just rebuild this App; I haven't changed any code. I just changed the behavior of how we're rendering these views. Now if I make this roughly 20% transparent and zoom in on this guy-- I love that accessibility zoom. Now you see that the patch doesn't show through the badge.

What we're doing there is basically rendering everything to an offscreen buffer individually at the opacity, and then bringing that buffer back onscreen and rendering it in. So this gives you probably a little closer to the behavior you were expecting with Group opacity. Again, we're going to turn this on by default in a future version of the OS, what we'd like you guys to do is go back and try your Apps out in the simulator with this key set; and that will tell you how your drawing is working and whether or not there's any work to do there. And the other one is EdgeAntialiasing and I have an admittedly very cheesy demo for this. But this is just a view that-- it's a square view and I've got a transform on it that rotates at 45 degrees.

And if we zoom in on this, well it's not terribly indicative because I'm getting hosed by the scaling that's going on here; but you can see that stepladder effect there that is basically, it's an aliased thing. There's a gray background here and all you see is a black pixel of square that steps up and the gray background behind it. So if I go ahead and edit this Info plist for UIViewEdgeAntialiasing.

Again, it translates it into something readable and run it; hopefully we'll see-- hey look, it's blurrier. What's actually happening here is the edge is actually being anti-aliased. And in the darker parts of the square there's a darker gray; and in the gray section there's sort of a darker gray from that.

So basically that edge is automatically getting anti-aliased by UIKit when it renders. And the idea here is that we're going to try and make this situation work a lot better for you. So please try both of those keys in your applications anytime you like but sooner would be better than later.

So let's see-- Data Detectors. Data Detectors have been present in Mac OS X on the desktop for a release or so now and they're pretty sophisticated. Data Detectors in UIKit are going to happen on UITextView and UIWebViews and if you set the DataDetectorTypes-- you can set PhoneNumber and Link so we recognize things that look like URL's and things that look like phone numbers. There's also a UIDataDetectorTypeAll here; and if you're going to set Data Detectors on your UITableViews, we'd like you to set UIDataDetectorTypeAll as much as possible.

And the reason for that is as we update the Data Detectors that become available; for instance if we add an address Data Detector, we want your views to be able to get those behaviors automatically. If you just set PhoneNumber, if you just set Link, and we add some new things, you're not going to get all of that neat new functionality without having to resubmit your App to the store. So if you use TypeAll you're going to be a little bit more future proof as new Data Detectors come online. And we now have In-application email Message Sending.

You get to include the Message UIframework, pick up data include and you get a brand new MailController, the mail framework MFMailComposeViewController. And it gives you the exact same Mail UI that we use in our own applications. So you'll get the ViewController comes up, it's the new message, it has all of the bits there for filling in to and from and things like that.

You also can find out whether or not the user is actually able to send mail. If canSendMail returns no, this is your opportunity to either disable UI that would allow them to SendMail and not show certain buttons, things like that, and you might not be able to send mail for a bunch of different reasons, like the user hasn't configured a mail account.

It makes it hard to send mail, things like that. You also have complete control over the SubjectRecipients, the Cc, To, Cc, and Bcc, and you also get an opportunity to tell us to set the MessageBody for a particular message, and whether or not that MessageBody is HTML. So if you have a String and it's just a plain text email, pass node is HTML here, if it's a string that has HTML tags in it and you tell us yes it is HTML, we'll go ahead and render it as HTML in the mail window. And you also get control over adding attachments; addAttachmentData, mimeType, fileName.

Give us the NSData, tell us what the mimeType is, you know application, NSString and that kind of thing and the filename. The filename's actually pretty important. Choose it carefully because that's what the user sees in the mailController right there; and it will give him a much better idea of what that file is.

There are some methods on this that allow you to find out exactly what's either gone wrong or hasn't gone wrong. Hopefully nothing goes wrong; mailComposeController didFinishWithResult error. The mailComposeController will tell you how it's ending. When it goes away you'll get a PNG back on your delegate that says we finished. The results are a whole bunch of different things.

One of them is MFMailComposeResultCancelled; ComposeResultSaved; ComposeResultSent; and ComposeResultFailed. And the Saved means that we made it to the outbox but it didn't get off the device. Sent means hey, you actually managed to get the mail sent off the device. Failed means yes something went really wrong and we couldn't get it off the device at all. And the errors that you get back, again, these NSErrors are all populated with things that are suitable for display to the user. So you may not have to do any modifications of this if you're just doing straight up mail sending.

So the ErrorDomain has two codes. SaveFailed means we couldn't even get it in the outbox, and SendFailed means it was in the outbox, it didn't make it off the device. But if the user were to go check they'd still see mail in their outbox. Matt Drance is our developer evangelist for iPhone and Mac Applications Frameworks. That's his e-mail address. There's a lot of documentation on the iPhone Dev Center.