App Frameworks • iOS • 51:15
Learn how to integrate Twitter into your applications. If you're new to Twitter, or have existing applications, we'll show you how easy it is to make the most of our new framework for single sign-on accounts.
Speakers: Scott Herz, Glen Steele
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Well, good afternoon. Welcome to session 124, Twitter Integration. My name's Glen, and I'm an iOS software engineer, and I'm going to be joined on the stage in a couple of minutes by my colleague Scott. Scott and I both worked on the Twitter integration in iOS 5, and we're just really excited to share with you the APIs and the things that we've been working on. Scott's got some awesome demos for you to see, so you can look forward to that.
So this is one of my favorite quotes from the TV show The Simpsons. And it's from the Blackboard gag at the beginning of the show where Bart writes out his punishment for the day. And it just reminds me so much of Twitter. You know, if you look up the term "Twitter Revolution" on Wikipedia, you'll get no less than four disambiguations for that term. And these aren't just like silly metaphors or hyperbole. I mean, these actually are referring to real national revolutions that have happened.
And to me, that just speaks a lot to the influence of Twitter in our society as a communications tool today. And this starts to really flesh out when you look at some of the numbers. I mean, Twitter has 200 million users. And they process -- Scott mentioned this in the keynote on Monday -- one billion tweets per week.
And that is just an incredible amount of, like, meaningless banter going on. And that's what Twitter is doing across the Web. But, you know, it's not all just meaningless banter, right? I mean, during the Japan earthquake, they were processing 5,500 tweets per second. And these are people communicating with each other, you know, sharing about what's going on in our world, and, you know, who knows, maybe even communicating with their families, letting them know they're okay. But I think for us as iOS developers, this is a really interesting number to me. There's over 3,000 apps in the App Store or on iOS that have have Twitter integration.
[Transcript missing]
Alright, so this is what we call the Tweet Sheet, and this is the part of this talk where we talk about pain-free Twitter integration. And as I mentioned, we like to refer to this as the Tweet Sheet. Hopefully you've had a chance to play with this a little bit. We love it. Our HI design team just did a phenomenal job with this. It looks beautiful. It has this whole index card motif and a character countdown. It's got, you can add your location to it. You can even add attachments.
And it's just really great and really simple to integrate. So let's talk about how you do that. What we've done is, as well as integrate this into iOS applications like Safari and Maps and Address Book, we've made this and exposed this as an API that's available to you. And it comes in the form of the TWTweet Compose View Controller. So how do you invoke this thing? Well, there's four steps that you basically have to take. And the first is that you need to check for service availability. So if, yeah, that's not a joke.
So not Twitter service availability. I'm talking about whether the user actually has an account set up on their device. If they don't have an account set up on their device, you may decide that you don't want to show the UI element that shows your tweet button or whatever it is that invokes your Tweet Sheet. So once you've done that, it's just a matter of creating the View Controller that is the actual Tweet Sheet and getting an instance of that. And then supplying a completion handler to do that. Tell the tweet sheet what to do once the users hit cancel or send.
Now that you've got that all set up, it's just a matter of presenting it modally over your current view controller. So let's look at how we do this in code. And so I've got just a sample view controller, like my view controller. And I'm just deciding to override the load view method.
And to check whether the user actually has a Twitter account set up, it's just a class method on the TWTweet Compose view controller called can't send tweet. And that'll just return a Boolean value that tells you if the user can actually do a tweet. And so in this case, we're setting an instance variable that will indicate to us later in, you know, whenever our UI loads, whether we want to show our tweet button.
So let's just imagine for a moment that the action on that tweet button is to call this tweet button tap method. And let's take a look at what actually happens when you drill into this method. So now that we've checked for our service availability, the next thing we need to do is just create our tweet sheet. And to do that, it's really simple. We just do a TWTweet Compose view controller, allocant it, simple Objective-C stuff that you're all familiar with, hopefully.
And then supply our completion handler. Now in this case, we're deciding to do something really simple. We're just going to dismiss the tweet sheet when it's done. You may, you know, want to react to the tweet sheet being canceled or sent or the send button being tapped in a different way. In this case, we're just going to dismiss it.
And just to note that this is actually the default behavior if you decide not to provide a tweet. So we're going to call it the TWTweetCompletionHandler. And once we got that, now we just call presentModalViewController over our current view controller. And that will pop up the tweet sheet.
So that's really as simple as it is to set up the tweet sheet in your application. It's just a couple lines of code. But that's not all it can actually do. It has a lot more power than that. And it comes in the form of attachments. So you can actually prime the tweet sheet with some values before you present it to the user.
And there's three ways that you can do that. The first is you can set the initial text on the tweet sheet itself. And that's just done by calling setInitialText and providing your string. And you'll notice that there's a return value here. And all this does is let you know if it was a successful operation.
Okay. So why might that not be the case? Well, if you provided a string that's too long, hopefully we're all aware of the Twitter 140 character limit. I don't think that's going to change anytime soon. But if you've gone too long, then that's going to be a little bit of a problem. So if you've gone too long, then that's one situation where you might get a negative result.
The other is if you've already presented the tweet sheet modally, and then you try and call this, we actually actively disallow you from setting any of these things after that. Because we don't want the user to be interacting with the device and then the tweet sheet to be changing under their feet.
So that's another reason why that might happen. And you'll notice that we don't return any kind of error here because it's not really a condition that you can recover from. Okay. So you can set the initial text. The other thing that you can do is add an image to the tweet sheet, which is great. And this follows the same general pattern that we talked about before with the set initial text. You just provide your UI image, and then you get a returned result.
Now, when you decide to do this, we actually take care of resizing the image for you and uploading it to Twitter's image hosting service and doing the URL shortening for you automatically. And so, you know, that URL takes some of your characters. And again, you may get a negative result if you decide to add too many or you've already used up too many characters in the tweet sheet. The last thing you can do is set up a URL. And again, very similar to what we said before, we handle the URL shortening for you, and a Boolean result is returned.
Okay. So, we've -- I've talked about this a little bit as I've been going over the tweet sheet, but just to reiterate, you know, there are sizing constraints. There's the 140-character maximum. Images and URLs use some of your characters when you decide to add them. And just an interesting side note is that the URL shortening uses 19 characters.
Now, you know, that's a cool little tidbit of information to know, but it's really not something you should rely on, right? Because as the namespace fills up and the URLs get longer, you know, the 19-character length of the URL shortening is not something you want to rely on.
So, instead, make sure that you're paying attention to the Boolean return values because that's what you ought to trust is the truth. Okay, so I'm going to ask Scott to come up and give you a demo of how to use the tweet sheet in your application. So please welcome Scott.
So this is a real simple demo, just to kind of show you how to pop up a tweet sheet and see how we add attachments to it. So what I've done here is just written a simple little app. It's got a number of buttons. And each one of these buttons represents a kind of attachment type that you might want to add to the tweet sheet. So this guy up here, we've got some text. That's the initial text you might want to set.
These guys down here are just a couple images, and then just a sort of a random link. And so when I click these buttons, what's going to happen is it's going to go and make those calls that Glen was just showing you. It's going to set the initial text, or it's going to add an image or a URL.
And if the result of that is true, then we're going to see a cute little green checkbox. And if it's not so good, then you're going to see this sort of angry red indicator. So let's go ahead and try a couple here. So I'm going to click this guy.
So that text, that fit, was less than 140 characters. So we're still good to go. I click another one here. That, we added the image, and it knew that the Tico length today is 19, so we're still all good to go. Can add a couple more. Then when I try to add this one, that one didn't work.
So let's try it again with just a couple simple ones. Just these three things here. Hit the Tweet button. Pop it up, and you can see the Tweet sheet is as we know and love. Let's show you just some of the code here that it took to do that. As I flail around with the mouse. There we go.
And you can also get-- You can watch me learn how to scroll and line. So this here is-- we're just making a new tweet sheet, right? So just Alec and NIT1. Just like Glen did, we're building a very simple completion handler block. And all we're going to do here is-- it's not particularly interesting. Whether or not the user hit cancel or done, we'll go ahead and just dismiss our sheet.
And then here's where we set it. And then down below, as I was adding-- as I was clicking those buttons, again, we're just using these simple methods-- add image, add URL, et cetera. And we're just returning out the back, like, OK, did this work or not? And then there's some other UI kit machinery to actually show the indicators.
So lastly, when I click that button, the Tweet button, it's so simple. All you have to do is just take your Tweet sheet that we made and present it modally, animated, and it pops up all nice, and you're good to go. So that's how easy it is to add a Tweet sheet to your app. So I hope to see a lot of them. Thanks.
Great. Thank you. Scott? So just a couple of tips and tricks when you're interacting with the tweet sheet. Remember that the tweet sheet is really only designed for modal presentations. So you kind of want to stay away from trying to put this thing in a UI navigation controller stack or in a UI popover on the iPad. It's really designed to be presented modally over your application. So use the present modal view controller method on UI view controller to present it.
Again, just to reiterate, set the properties prior to presentation. We don't want you messing around with the tweet sheet under the user's feet while they're using it. So do that before you present it. And then check the can send tweet method if applicable for you. So one little detail to note here is that if the user doesn't actually have an account set up in settings and you decide to invoke the tweet sheet, we'll actually context switch the user back to the user. So if you're using a tweet sheet, you're going to have to go back to settings to allow them to set up an account.
And, you know, this may or may not be a behavior that you want. So you should be aware of it and make sure that you check the can send tweet class method on the view controller. And the other thing is just to be aware that we are doing image resizing.
We are uploading things. So, you know, if you provide a huge image to the add image method, then it's going to take, you know, a few seconds to resize if necessary. Okay. So that is the tweet sheet. That is pain-free Twitter integration. It took us about 10 minutes to go through that. It's really, really simple. And I encourage you, if you have simple Twitter integration needs in your application, use this. You get a great UI for free and it's really easy to invoke it.
Okay, so we talked about that, and now we're going to move on to talk about something else that's pretty cool, which is the new accounts framework in iOS 5. And this is a really cool feature, but it's kind of a sleeper feature, right? It's not really talked about a lot, but what it allows you to do is access built-in system accounts that are on the device. Now, for iOS 5, we're only supporting Twitter accounts, but there's still a lot of power in that.
And we also allow you to add accounts in certain situations and make system accounts as well from your application. And we'll go into why you might want to do that and how to do that in a little bit. And if you do decide to do that, we also take care of the validation for you. We make sure that the credentials that you provide us are good to go with Twitter before we add the account and make it become a system account. All right, so just a word on the architecture of the accounts framework and how it's laid.
So you've got your application, it's in its sandbox, and we've got the accounts database and the protected file system. So how do these things communicate with each other? Well, there's an intermediary process called accounts D that basically acts as the arbiter between your application and the accounts database itself. And this architecture gives us a couple nice features. One is obviously security, right? We can store the credentials for the user securely in the protected file system. And, you know, a bunch of applications can't get at it without going through our frameworks.
And it also gives us a layer of abstraction for your application and other applications to access the accounts, which, you know, limits the way that they can access the database and make sure they're not, you know, messing it up for you, right? So that's just a quick overview on how it's laid out. And this is basically what the class diagram looks like, and it's very simple. We've got four that are there. But I want to finish up with a little bit of a summary.
So I'm going to focus on these three to begin with. And essentially what you have is an account store. And in your account store, you've got a bunch of accounts, and each account has an account type. And that's really all there is to it. But what I'm going to do is go through each of these classes and just describe them to you so you can, you know, maybe understand their function a little better. And we'll start out with the account store. So the account store is your connection to the accounts database. And when you allocate and initialize one of these, automatically, your connection to the accounts database is established.
Now, these are things that you generally want to keep as long-lived instances, right? You typically don't want to allocate one of these, interact with the account, and then throw away the account store, especially if you have the kind of application that's going to be using the account throughout its lifecycle. So it's something you probably want to put maybe in your application delegate or your review controller. You want to keep it around.
Now, it's also important to remember that the account instances themselves are, are bound to the account store from which they came. So if you access an account and pull it out of an account store and then deallocate that account store and try to use that account with another account store, okay, bad things are going to happen. There's an implicit connection between those two objects that, that needs to be respected. The other thing I want to point out is the AC accounts change notification, which is defined in this header.
And this is something that any application that is implementing code that uses the accounts framework needs to respect. It's a notification that fires when the accounts database changes. So if the user goes into settings, adds an account or removes an account, or maybe revokes permission for a particular application, this notification is going to fire and you need to respond to it and observe that notification. And any instances of accounts that you have lying around, you need to refresh and obtain new ones from the account store because otherwise you're going to be dealing with outdated information.
So that's the account store. And the next one that I want to look at is the AC account object, which is really what you're interested in, right? This is the object that represents the account itself, and it's got five basic properties on it. It's very simple. It has a unique identifier. It has an associated account type, username, credential, and description. And I just want to point out the description. So when we create a Twitter account, we automatically create the description by appending the at symbol to the username.
But the user can actually go into settings and adjust this thing so that it can, you know, read however they want it to. So typically, if you're presenting UI that references a particular account, the description is what you want to use, because that's what the user has told the system, "Hey, this is what I want this account to be known by." Okay, the next one is the AC account type object.
And so every account has an account type. And it's got three simple properties as well. Again, it's got an identifier. And these just aren't just, you know, the account type is not just a string or something. This is a real object that lives in the account store. And it has a description.
And then it's got this interesting property called the access granted property. And that tells you whether the user has granted access to accounts of this type to your application. So you can check this at any time to figure out if you have permission to use accounts of this type.
Okay, so let's talk about that a little bit more. How do you actually request permission to use a particular account? It's very simple, and we're going to step through it by code. As I mentioned, accounts are protected by account type. So once you have access to, you know, one Twitter account, you essentially have access to all of them, and we message it to the user in that way.
So to get permission for an account, you just create an account store. Again, very simple, AC account store, Alicanit. Your connection is now established to the database. And then you obtain the account type that you're interested in gaining permission for. In this case, it's always going to be Twitter, right? So to do that, it's just a call to account type with account type identifier. And you'll notice this identifier. So, you know, all supported account types, we define an identifier for them, and it's in the header.
So in this case, it's the AC account type identifier for Twitter. We pass that in, and now we have our Twitter account type object. And we can request permission to use that from the user by just calling on the account store, request access to accounts with type. And that comes with the completion handler. So we've used completion handlers a couple of times now. And I just want to point out, this is probably a good time to point out that we make heavy use of blocks and Grand Central Dispatch in these frameworks.
So if you're not familiar with those, I'd encourage you, get familiar with blocks in Grand Central Dispatch. It's going to be useful if you're interacting with these APIs. So you'll notice in our completion handler, we return a Boolean that indicates whether you got permission or not, and an error in case anything else went wrong. And you can check the granted Boolean value. And if it's true, then you know you have permission to access the accounts.
Okay. So now that you've got permission, you've requested it from the user. And you've got permission to access the accounts. So you can see that the user has granted it to you. How do you actually go and get an account instance? And there's two ways that you can do this. And the first is you can request all the accounts of a particular type. And So let's take a quick look at how you do that in code.
Again, obtain that Twitter account type by calling account type with account type identifier. And then just ask the store for all the accounts of a particular type, and you'll get an ordered array in the same order that the accounts were added of the accounts that are on the system.
The other way that you can do this is to request an account by a particular identifier. And so I mentioned each account has a unique identifier, and you may decide that you want to save that identifier aside somewhere in your code, maybe in a P list or something, and access that exact account later on, or maybe in a different instance of your application. So to do that, it's just a simple call to account with identifier, and that'll give you your AC account object. So those are the two ways that you can access accounts using the accounts framework.
All right. So we've talked about the three basic classes, but there's one more that I want to cover and it's the AC account credential class. And this is a really interesting one because what it makes possible is for you to actually add accounts to the device by providing credentials. So if you're an application developer and you've got a full-fledged Twitter client, it's a pretty good bet that you've got the OAuth access tokens and the token secret associated with those accounts stored in your application.
And wouldn't it be nice if you could migrate those credentials to become system accounts themselves? So that's what we're allowing you to do because we realize that for those of you who are implementing Twitter clients, you know, you've already got your users' account information and it may not be guaranteed that they've gone and set up a Twitter account as a system account already. So what we do is we allow you to actually provide credentials that we will then store as system accounts.
So that's exactly what we're describing here. You can add new system Twitter accounts from your app, and you do that by migrating OAuth credentials, and we'll show you how to do that. When you provide us with the OAuth credentials, we take care of going and talking to Twitter, making sure that your OAuth credentials are OK, and then setting up a system account on the device. And it all happens really pretty seamlessly and automatically. OK, so let's look at in code how you actually do this.
The first thing you do is create your account object. It's got one initializer. Every account has an account type, so it's init with account type. I've showed you a couple times how to obtain the account type from the account store. You just pass that in, and now you've got a new account instance. It's not saved in the database yet, but because we've got to add a couple of other things, or really one more thing. So the next thing you do is create your OAuth credential.
And so you take your OAuth access token and access secret for your particular account and initialize a credential object with it, and then set that credential on the account. And once you've done that, you're ready to go, and it's just a matter of calling account store, save account, pass in your account instance with its OAuth credentials, and we'll go ahead and verify that the credentials are valid.
And it's pretty cool. Right in settings. Your Twitter account will actually appear. And this is really powerful, right? Because it means that your account that you've been using is now accessible to the user. It can be used in the tweet sheet. It can be used in other applications as well, which is really great.
So a couple of tips and tricks in dealing with the accounts framework. One is to ask for access when you need it. So if you've got a full-fledged Twitter client and you're using our frameworks and you want to use the user's accounts, which we encourage you to do, then it makes sense for you to ask at the outset, right at application launch time.
Ask the user if they can use their accounts-- if you can use their accounts, because if you don't, it's essentially a non-starter for you, right? But if you're using Twitter as an auxiliary function to your application or it's just a neat social feature, then don't bug the user with an alert right when your application launches.
Instead, ask for permission when they decide to use that Twitter feature, right? Important to note that certain operations are always gated with alerts. So, for instance, requesting access to an account, obviously, is going to pop up an alert. And adding an account to the system using existing OAuth credentials will also pop up an alert. We're going to ask the user if it's okay to add this account to the system.
Again, don't cross the streams. Don't take an account from one account store and try and interact with another account store using that account. It's just not a good idea. And pay attention to that notification that I was telling you about. And this is an important note as well that I'm going to mention a couple more times. Often as a result of interacting with these APIs, you need to update UI, and you need to make calls to UIKit.
And all of the block-based APIs that we have are not guaranteed to return on the main thread. So if you are updating UI as a result of any of these calls, then make sure you're dispatching that call to the main thread, or performing a selector on the main thread. My favorite way of doing it is this, is just to use dispatch async, and this is more GCD magic. Use dispatch async, get the main queue, and then throw in a block that calls your method that'll actually update your UI.
Okay, so that is a quick overview of the accounts framework. It allows you to access built-in system accounts and use them and interact with the Twitter API using them. It also allows you to migrate existing OAuth credentials that you have and graduate them to become system accounts that can be used by the tweet sheet and other applications if necessary.
So, now we're going to move on and talk about the Twitter request API. Now, I think at this point it's probably a good idea to just kind of take a step back and take a look at what the Twitter ecosystem looks like on iOS. And so what we have is, you know, on iOS we have the best mobile Twitter clients around. Thanks to you guys.
I mean, we have awesome Twitter clients that are available. And then we've got this expressive and useful Twitter API that's available to you, right? And that's great, but it's really not the whole story, right? Because kind of, you know, sandwiched in the middle of this thing is this other thing called OAuth that you have to deal with if you're interacting with Twitter.
And as we were thinking about implementing Twitter in iOS and talking to our counterparts at Twitter and talking to people who've implemented Twitter clients, it became apparent really quickly that the biggest stumbling block to doing this is using OAuth and using -- and I'm not just talking about, you know, the steps of going to a website and authorizing applications.
I mean, just the mechanics of signing your requests. Many of you have to use, you know, open source or third-party libraries to do this kind of thing. And so one of our big goals when we were creating the Twitter API in iOS 5 was just to get rid of this whole layer entirely.
It's okay. Yeah, you can clap. Because I think it's pretty cool. I mean, this really gets a big stumbling block out of your way completely, right? And it allows you to interact with the Twitter API directly and not really have to worry about all these details of how to sign requests and all that stuff. We just take care of it for you. You don't have to worry about it.
[Transcript missing]
We take care of the OAuth signing for you. As I was mentioning, we do all the heavy lifting of that. And all you have to worry about is your application and how to interact with the Twitter API. And you can use any of the Twitter accounts, thanks to the new accounts framework, in conjunction with the TW request object, provided the user has granted you access to do so.
The other thing we added was support for multi-part data. So some of the APIs that Twitter uses or exposes requires you to upload pictures or things like that. And the way that's done is by using multi-part form data. And so we have just a really easy way for you to add that to your TW requests and not have to worry too much about the details. So we'll show you how to do that too.
Scott Herz, Glen Steele All right. So this is our TW request object. And you can see it's got four basic properties to it, right? And if you're familiar with using the Twitter API and looking at the Twitter documentation, these probably look pretty familiar to you because every piece of Twitter documentation out there has essentially an analog to these four pieces of information in the TW request object.
And so when you're coding up your TW requests, you know, I encourage you, have the, have the, have the Twitter API. And so that's kind of the way that we're doing it. Scott Herz, Glen Steele All right. So we have the, the Twitter docs open right next to it. And it should be, it should feel almost as natural as like just filling in the blanks as you go through the documentation. So, you know, we have a URL property.
Every Twitter doc has the URL property which represents the endpoint that you're interacting with. We have the request method. So Twitter APIs support get, post, and some of them support delete. We support all of those. And you just tell us which one you want, you want us to use. And then each doc, each one of them has a request method. And so you can just tell us which one you want us to use. Scott Herz, Glen Steele All right. So Twitter APIs support get, post, and some of them support delete.
We support all of those. And you just tell us which one you want, you want us to use. And then each, the documentation for each API spells out whether the request that you're making is an authenticated request or not. And so that just corresponds to the account property. So if it's an authenticated request, hey, just pop in one of the accounts and we'll use that account to sign the request.
And then each piece of documentation also spells out some parameters. So, you know, if you want to limit the request in some way by providing some parameters, we take care of that in the form of a dictionary that you just provide to us, and we assemble the request for you. Okay. So let's take a quick look at how you would code this up. And it's, again, you know, really simple.
Well, before we do that, I want to point out that there are two ways, once you have your TWRequest object, to perform a request, and the first way you do this is we have a convenience method right on the object called PerformRequestWithHandler. Now this will take care of actually doing all the communication with Twitter and delivering the data back to you in a single Atomic request. Okay. So what do I mean by that? It's kind of a weird word here, but it's--all I mean is that we will go and perform the request and return the data all at once.
Okay. It's asynchronous, but it happens all at once and you get delivered the result at the end of it. The other way to do it is by asking for a signed NSURL request. Now, you know, many of you have mature Twitter clients, you've got applications that are using the Twitter API. You've got this whole NSURL connection stack that handles errors, it handles streaming data and partial downloads and things like that.
Well, how do you plug our stuff into that? So we thought of that and we figured the best way to do it was to give you something that you can just plug right into that infrastructure. So you can call and--on the TWRequest object and ask for a signed URL. We take care of the signing. You dump it into your--. infrastructure, it does the requesting, and it's all taken care of for you.
So, now I mentioned that, you know, we wanted to get rid of the OAuth stuff, and we did that in terms of the way that you guys view it, but it's still there, right? It's still under the covers. OAuth serves a really important function. It authenticates your application and your user to Twitter. So we still need to deal with it. So I figured I would show you exactly what's really going on under the covers here.
So you've got your Twitter client, and it implements the Twitter framework, and you now want to make a request, and so you make up one of these TWRequest objects, and that's represented by the little Twitter bird. And now you go and you call perform request with handler, or you ask for a signed NSURL request. What happens next? Well, what we do is we ship that request over the wire to the accounts D process, which has access to the user's credentials. And we take care of doing the OAuth signing.
So, you know, we set up the base URL, we order the parameters correctly, we take care of doing all the SHA-1 stuff and setting up the NSURL request. And once that's done, then we ship it back over the wire to your process, and then it's up to your process to actually make the request to Twitter either by using the request with handler, perform request with handler, or by using the request with handler.
So, you know, perform request with handler or dispatching your signed NSURL request in your network stack, right? So one thing I want to point out here is, you know, I've seen a little bit of chatter about people wondering, you know, how is my app going to be identified? Is everything going to show up as from iOS? So as part of this signing process, we actually embed enough information about your process that Twitter can identify your application correctly and attribute tweets that come in. So you can see that the message that's coming from you on the Twitter website.
So you won't lose that identification, right? So once it's been shipped back over to the Twitter framework, then your client app sends it over to Twitter and they process the request and return the result back to you. OK, so we talked about the structure of this stuff. Let's look at a little bit of code to see how you do this.
So the first thing we need to do is pick the endpoint that we're going to use. And so in my example, what I'm going to do is write some code to download the user's home timeline. Now if you're familiar with the Twitter API, you know that each of these endpoints basically can be suffixed with the kind of data that you're looking for in your response, right? So in this case, we're suffixing the URL with the .JSON suffix, and that means we're basically expecting JSON data back.
So once we've done that, then we create our parameters dictionary, and that's just a matter of--in this case, we want to limit the number of tweets that come back on the home timeline to 10 instead of like the default 200 or whatever it is, right? So we create a dictionary, and if you look in the Twitter docs, that's just using the count parameter. Set the value to 10, the key to count.
And now we go and create our TWRequest object. And so it's got one initializer that takes three values. The first is the URL that you created. The next is the dictionary of parameters to narrow down your request. And then the next is the request method. And in this case, we're just going to do a simple get.
Okay, so we've done that, we've created our TW request, now what's next? Well, in this case, we just want to use the convenience perform request with handler method. And so we're going to do that. And it returns in its block handler the response data and the NSHTTP URL response and any errors that might come back.
Now, if you're familiar with NSURL connection, this might look familiar. This is the same stuff that comes back if you send a synchronous request, right? But again, it's not synchronous. It's atomic. And it'll come back and give you the response data. So let's take a look at how we handle this in our completion handler. All right.
So I mentioned before that we suffixed our URL with the .json suffix, which means we're expecting JSON information. And there's this great new class in iOS 5 called NSJSON Serialization, which will take in JSON raw data and give you a foundation object on the other side. And so that's what we're using. And basically, what we get is an array of tweets back.
Now, you know, for the sake of space, I'm not really acting on errors here, but I just want to reiterate and encourage you, handle your errors. Make sure you're checking your--that NSError and the JSON error there and responding appropriately. And we're just going to assume that we have some kind of method that's updating our timeline. So we call that update timeline, pass in that array of tweets into it. And again, completion has to be done in the same way that we did in the previous version. So we're going to call that update timeline, pass in that array of tweets into it.
And again, completion has to be done in the same way that we did in the previous version. And again, completion has to be done in the same way that we did in the previous version. And again, completion has to be done in the same way that we did in the previous Deficient handlers are not guaranteed to be returned on the main thread, so to be sure, we're going to dispatch async onto our main queue and call the code that updates our UI. And that's really as simple as it is.
All right. So a quick word about multipart data. How do you upload multipart data if you want to update a profile image or something like that? So I've got a little example in code of how to do that. And in this case, we're going to use the update profile image endpoint, again, with the JSON suffix, create our TWRequest object, pass in the URL. We don't have any parameters this time. And then call this great method called add multipart data.
And in this case, it's a JPEG image. Now, I'm assuming that, you know, in this code, you use the image picker or something and you get a UI image back. So we're just going to use the UI image JPEG representation convenience method to convert that to an NSData in JPEG format. And then Twitter expects images that are in the JPEG format to be in the JPEG format.
So we're going to use the UI image JPEG representation convenience method to convert that to an NSData in JPEG format. And then Twitter expects images that are in the JPEG format. And then Twitter expects images that are in the JPEG format. And then Twitter expects images that are in the JPEG format. And then Twitter expects images that are uploaded to be--that part of the form is called media, so that's the name that we're going to assign to it. And then, of course, we have to set the MIME type to be image/JPEG.
And that's as simple as it is to upload multipart form data in your TWRequest. Again, call perform request with handler and deal with the results that come back from that. Okay, one more time, I'm going to bring Scott up to give you a demo of how to use all these APIs. We've covered a bunch of them. And he's going to do that. I think you're really going to like it. Let's give him a hand.
Thanks. So, actually, if you would allow us just a moment to be a little bit serious. There's an issue that's very close to Glen and I, and that is the current plight of monkeys. I think you can agree that they all face a lot of problems, not the least of which is issues like shrinking habitat. Right? That's a real problem.
They often are evicted from their homes, end up in zoos, where oftentimes they then become addicted to cigarettes, tobacco products. The larger problem than that is there's really no good Twitter client that is dedicated just to monkeys. So we're going to try and address that today with a little app we call MonkeyGram.
So make sure I've done everything right. So this is our Monkeygram application. It's very simple. It's just designed to present some wheels for a monkey to be able to roll around with and build a tweet. When it launches, the first thing it does is using the API that Glen has discussed. It goes and tries to get a Twitter account, because Monkeygram without a Twitter account isn't super interesting. So we're going to say yes.
Let's allow it. So by rolling these wheels here, we're affecting the mention, right? And rolling these guys here affects the tweet body itself. And then down here, over to the right, is the hashtag. Bieber isn't big into economics, so I trust him. So we're going to say tweet. And what this is going to do is use that API that Glen discussed to actually send the tweet. So let's take a look at some of the code that we wrote for that.
So as Glenn mentioned at first, we get our account store. We get our Twitter account type. And then we set about trying to find an appropriate Twitter account. Now, I'm only-- this is just a demo. So I'm only going after the very first Twitter account that I find. One thing to keep in mind is we support multiple accounts, right? So it's kind of important when you write an app to keep that in mind. Don't just go and use the first one you find.
Do as I say, not as I do. As Glenn also mentioned, based on whether or not you're going to use any UI or anything, you really need to keep track of sort of which queue you're on. So we don't exactly know what queue this is coming on, what we're going to get this account on.
So I've wrapped this code in this sort of async call with a block so that it all executes on the main queue. And I do that because down here, depending on whether or not we found an account or not, we're going to go ahead and enable or disable that little button at the bottom.
So here's sort of the meat of sending a text-only tweet. It looks very similar to the stuff that Glen showed you, the differences being that we're hitting a different endpoint, so we're hitting Update. And the keys that we're using are slightly different. It's very simple. It's just status, and then you put the text in there, and you're good to go. So we would assign these parameters. These parameters are called query parameters. They go in as part of the query. They're different than the multi-part parameters, which we'll show you just in a second.
So when the tweet goes out, it comes back. And as you'll see, I'm not really checking in your errors. It just plays a monkey sound, which you didn't hear, which is a damn shame, because I made that sound myself. And I'd love to have you here. So that's what would happen once the request comes back. And here, down below, you'll see I'm just using the very simple fire, let it go off, and figure out what happened, and then come back and tell me about it request method.
[Transcript missing]
So this endpoint is authenticated, right? We are doing this to your account. So this is where we make sure to prime this request with the account that we got earlier. I have a little method called image data, which goes off and makes a cute little image, which I'll show you. And we add that as a part. And we go ahead and tag it with the tag media, and set the type to image JPEG.
And so here you can see sort of where the status text actually comes into play. Instead of putting it as a query parameter, comes in as just a named multi-part data thing. And again, like we discussed a little bit earlier, I wanted to show you, if you wanted to fit this into an existing NSURL connection workflow, what would that look like? And so what we're doing is using this tweet request that we've made, we're getting a signed URL request. And as Glen mentioned, that goes off and does all the OAuth hoo-ha and comes back with this special NSURL request. And we can take that and put it into an NSURL connection that we all know and love and tell it to start.
So I'm not paying attention to too many of the delegate messages, but I do want to show a little progress this time when we send a tweet, because we're pushing up this image and it could take a little bit. And so all I've done is just, I'm overriding, I'm listening to one of NSURL's connection, NSURL connection's delegate messages connection did send body data. And I grab the progress and we'll do something cute with it. So that's that. So let's take a look at what we did. We'll stop that one.
So, let's send another tweet. Can't let Bieber have all the fun. There we go. So we'll send that guy. And now we'll actually see a little bit of progress. Network's good here. And it would have made a monkey noise, I promise. So let's go take a look and see what we actually sent. So I'm going to come over here to Twitter. And here was the message that we sent.
So you can see there's the tweet, the text part, and then we made this cute little image to go along with it. So it's very straightforward. It takes a lot of the hard work, the grunge work, of doing all this OAuth stuff, and it lets you guys go do the stuff that you presumably want to do, which is make cool, entertaining applications and not so much signing OAuth. So that's how that works. Thanks a lot.
Thanks, Scott. Wasn't that awesome. I don't think we can put it on the App Store, but we've been playing a lot with it at work, and it's pretty cool. So just a couple tips and tricks with using the TW request and the Twitter API in general. One of the important things is to remember, follow the Twitter rules of the road.
They've got this document. And follow the Twitter guidelines as appropriate. Don't do things like send tweets on behalf of the user without giving them any visual indication that you're doing so. Those are all the kind of policies that are outlined in the documents. And then again, I just want to point out, make sure you call those completion handlers, or any calls that you make from your completion handlers that have to do with UI, dispatch those on the main thread to make sure things operate as UI Kit expects them to.
So that is Twitter integration. It allows really simple-- it gives you a really simple interface to access the full range of Twitter's API and do really powerful Twitter clients and applications in a really simple way. So if you want more information, contact Bill Dudney, he's our application framework evangelist. Check out the Twitter documents on our frameworks at developer.apple.com, and of course, the Twitter API.
And a couple related sessions. We talked a lot about block-based APIs here, so make sure you brush up on that and check out the blocks and Grand Central dispatch and practice talk. That already happened, but there's always iTunes or ADC on iTunes. And again, you know, we're dealing with networks here, so the CoreOS networking key principles talk is probably a good one to take a look at as well.
Just in summary, we covered the tweet sheet, pain-free Twitter integration, accessing system accounts, and using the TW request APIs to use the full range of Twitter application APIs. So, you know, my send-off to you is go and make some really cool apps and use these APIs. And thanks for coming, and thanks for listening.