Encapsulating Code in Closures

Way back in Methods, we mentioned that functions use the syntax -> to indicate the type of their return value. So, is that (Bool, NSError!) -> Void stuff a function? Actually yes…kind of! What this syntax expresses is a closure, a self-contained block of functionality. The syntax indicates what will be passed in to this block of code (a Bool indicating if permission was granted, and an NSError optional in case the request for access totally failed) and what will be returned from it (Void, that is to say, there is no return value). So it’s not that this parameter is a function; it’s a closure…and in Swift, all functions (and thus all methods on objects) are just a special case of closures!

So what’s so great about closures? Well, for one thing, it means we get to take some code and treat it as if it were any other type, meaning we can pass it to and from functions, store it as a property, and so on. In this case specifically, we get to write some code, give it to the ACAccountStore, and say “ask for permission to use the Twitter account, and run this code when done.” That’s precisely what we want to do here: we want to write a closure that makes a Twitter request if and when the user approves our use of her Twitter account.

Let’s begin by rewriting reloadTweets to get the current Twitter account. We’ll take it slowly and just concern ourselves for now with getting the Twitter account, not what to do with it yet.

1: func​ reloadTweets() {
let​ accountStore = ​ACAccountStore​()
let​ twitterAccountType = accountStore.accountTypeWithAccountTypeIdentifier(
ACAccountTypeIdentifierTwitter​)
5:  accountStore.requestAccessToAccountsWithType(twitterAccountType,
options: ​nil​,
completion: {
(granted: ​Bool​, error: ​NSError​!) -> ​Void​ ​in
guard​ granted ​else​ {
10: NSLog​ (​"account access not granted"​)
return
}
NSLog​ (​"account access granted"​)
})
15: }

On line 2, we create an ACAccountStore object, which we’ll need for the next few steps. The requestAccessToAccountsWithType method will require us to get the Twitter ACAccountType, which we do with a call to accountTypeWithAccountTypeIdentifier on lines 3--4. Once we have that, we can ask for access to Twitter accounts, passing in the type (line 5), a set of options that can be nil for Twitter accounts (line 6), and a completion handler closure that will be called with the result of our request, which receives a Bool to indicate if we were granted access, and an NSError that will describe any error associated with a failed request.

Our preliminary closure ranges from the opening curly brace on line 7 down to line 14, where it ends with a telltale sequence of characters—})—which are the curly brace to end the closure, and the close parenthesis that ends the parameters to the requestAccessToAccountsWithType call that began back on line 5. Line 8 is the signature that indicates what’s being passed into the closure (the granted Boolean and an optional NSError), the return type (Void, meaning nothing), and the keyword in that begins the closure’s logic. Inside this closure, our first decision to make is whether or not we can proceed; if the variable granted that’s passed into the block is false, then we don’t have access to Twitter accounts and should just give up. For now, on lines 9--11, we will just log a failure message and do an early return. Later on we should come back and add a proper alert so the user knows what has happened.

On the other hand, if granted is true, we will be able to start talking to the Twitter API, which means a lot more work! For now, we’ll just log a success message (on line 13).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.189.43.211