Читайте также: |
|
- In Swift, we use closures to group codes together into reusable self-contained units. Now you might first hear that description and then think, "hang on, isn't "that what we do with a function?" "After all, a function groups some code "into a reusable self-contained unit." And yes, absolutely, in fact functions are a specialized type of closure. A function is a way to group some code together and give it a name. But a closure doesn't even need a name. It's actually simpler than a function. And other languages support this concept and call this idea an anonymous function.
Some other languages call it a lambda or in Objective C it's called a block. It's a way of being able to group some code together so we can pass it around from one place to another place in our application. And the great thing is, you already know how to get started with this. If you can write a basic function, you can write a closure. Here's what I mean, we already know how to create a simple function, so here's a function that takes no parameters and returns no values, it just performs a println statement.
Now if I were to just go ahead and remove the keyword "func" and the function name, this would be about the simplest closure in the world. Having said that, written by itself, this would cause Swift to throw an error. It's going to say that this is a braced block of statements that's an unused closure. It's basically saying, "yes, you're "grouping some code together, you're "writing this code block, but you're not "doing anything with it and you can't do "anything with this right now, so what's the point?" Because just as the point of writing a function is so you can call that function by using the function name, the point of writing a closure is that you have a block of code that you're going to pass around and use.
Now one way, not a very useful way, but one way I could get ready to do this, to pass this closure around is I could just store it in a variable or constant, just give it a name. So "let myClosure" or "var myClosure equals" and give it a code block. This would be giving this closure a name existing as a named piece of data, a named block of code. This probably doesn't seem to save much over having a function, but bear with me, we're taking this step by step. So, I have this closure to find and give it a name.
I'll now create a function that accepts a closure as a parameter and this is really the entire point of using closures, that we can create these blocks of code and pass them around into other parts of our program. So this is a regular function, we're just using the keyword "func," I've called it "performFiveTimes" and it accepts one parameter, which I've called "myClosureParameter." Now the only thing that should look a little weird right now is most of our parameters up to this point have been using the colon int or colon string or colon Boole.
Well this one's "colon empty parentheses "return arrow empty parentheses." Well, we will talk about this format in just a second, but this is how I'm saying that this function accepts a closure as a parameter, not an int, not a string, not something simple, but a block of code. So, within the function I have a simple loop that just goes around five times and each time, it's going to take whatever closure, whatever block of code that was passed in and execute it. Well, the point of defining a function is we're going to call it, so I can go ahead and call this function passing in the name of that closure that I named up here on line three called "myClosure" and it's going to pass it in to the function, it will loop around five times, calling that every time.
You can actually see the result of it up here that yes it will go through, it will give us console output and write that out five times. So here's the last thing, I can forget about this extra step of actually naming this closure. We can get rid of that, we can grab the closure itself, which is the opening and closing curly brace and any code in between, whether that's one statement like it is here or three or ten or 100 if necessary. And I'm just going to come down here on the function call and paste that entire thing right inside the parentheses as a block of code.
And this is the usual way that you will interact with these, if a function has been defined to accept a closure, to accept a block of code, you'll just directly type the curly braces inside the call to that function and paste in the contents of the code that you want to pass into the function. This works exactly the same way, we can see over here it's being executed five times, we can see the results of it coming out five times. But, there are a couple more things worth knowing about this format. See just as a function is a block of code that can take parameters as input and return values as output.
So can a closure, a closure can have parameters and return values. So let's compare them to function because that's probably the most useful comparison here. So I've got a simple function defined to take no parameters, it's got the empty parentheses after the function name. And we can assume it returns no values because we haven't specified any, there's no return arrow, there's no return arrow string or return arrow int. If I wanted to be very explicit that this function returns nothing, I can in Swift actually write this code, I could write it this way.
Empty parentheses for the input parameters and empty parentheses after the return arrow. And this is the format that we use when we're defining parameters and return type for a closure. So if we begin with a simple closure, the most straightforward code block in the world, simple closure that takes no parameters and returns no values, if we want to be explicit about it, we would take that same format and paste it inside the opening curly brace. Because whereas, with the function definition, we put parameters and return type information before the opening curly brace when we're working with a closure, there isn't anything before the opening curly brace.
A closure begins at the opening curly brace, so we put that information inside. So this is a closure that explicitly takes no parameters and returns no values. It just does a little bit of work. Now one last piece of official syntax is then to separate the parameter and return type information from the rest of the statements in the closure, we use the keyword "in" to split the two apart. Alright, back to the code. So, to revisit this function definition, this is what that syntax means, it's how we define the type for a function that is accepting a closure as a parameter and explicitly a closure that takes no parameters and returns no values, it just performs some action.
So if I pass in any closure matching that definition, it will do that work five times. However, I should really for best practice be explicit down here when I'm passing in that closure and say, "yes, "this is a closure that takes no "parameters, returns no values, "that's that piece of information here." And then I'd use the keyword "in" to separate the parameter and return information from the actual blocks of code from the code in the rest of our closure. And this doesn't change what it was doing a moment ago, but it's the more formal syntax for doing this and it's something that's worth being able to recognize.
So this begs the question, if we have closures that can take parameters and can have return types, how do they work, how do we use them? Well, to illustrate that, let me run through an example of using a closure with some existing functionality that's already in Swift and really, this is the big benefit of using closures, is they allow you to tap into an enormous amount of existing functionality. So, I'm just going to create a new playground. I can strip all the code out of this, as I really don't need it right now. And what we're going to do is use a piece of functionality that already exists, it's a function called "sorted." And there's a couple of ways this can be called, but one of the basic ways is to call it "sorted," passing in two pieces of information.
An array or another collection that you want to sort, and then a little bit of information, a closure, a little bit of code, a little bit of logic that says how any two elements in this array or in this collection should be compared. You see, this built-in sorted function can take care of sorting arrays of thousands of elements, you don't have to write an actual sort algorithm as long as you can provide a little bit of code, a little bit of logic that just says "how do you compare any two pieces?" So, first we create an array.
Now, for time's sake, I'm just using integers. More likely in this situation, it would be an array of some kind of custom object. So this sorted function wants to be provided with a closure that will take two parameters. Now for us, that will be two integers out of this array to compare. And it expects to get back a Boole. How do I know this? Well, I looked at the documentation for the sorted function. So, I need a closure that accepts two integers and returns either "true" if the first is less than the second, or "false" if otherwise. Now, if it seems tough to think, "well, how "would you begin writing that as a closure?" Well, the easy way to do it is first you write that as a regular function and then you change it to a closure, because that's much easier.
So, if we go ahead and write that as a regular function, I'd call it "compareTwo" and this takes two parameters in, they're both integers, I'll call them first and second, and it returns a Boole. I've made a typo there, I've said function instead of func. Let's get rid of that. and I'm using the shorthand method here, that's just going to directly return a Boolean comparison between the two, so if first less than second, we will return true. If anything other than that, we're going to return false. So, a very simple bit of code here, but it should do the trick.
We will convert this from a function into a closure in just a second. Now below this, we're going to have the call to the built-in sorted function and that's just available anywhere in Swift. sorted will return a sorted version of your collection, a sorted version of an array or a dictionary, so I'll create a new constant to retrieve the results into and we will call sorted. First piece of information to pass in is our unsorted array that I created on line five. Then a comma and then we need the closure.
So, I'm going to convert this function into a closure. First thing I'm going to do is just, actually, comment it out because I don't want Swift to be complaining about it with everything that I do here. So, how do we do this? Well, first I get rid of func and the function name, don't need that. Then, the curly braces needs to move right to the start because a closure opens with curly braces. So we have the opening curly brace, we have the parameter information and the return type information. Then we have the body of the closure. The only last thing I need to do is separate that with an in word here.
And that should work as our closure. And we just uncomment that, of course we don't need it by itself. I need to cut it, paste it after that and make sure to finish the closing parentheses for the sorted call. And it looks like it needed to do some kind of 37 comparisons in its compares, it's probably doing some kind of bubble sort, it doesn't really matter I don't care that much. What I'm interested in is the result, so I'm going to type the name of the sorted array down here and then just go over it and find the quick look icon and we can see that yes, we began with a randomly unsorted array and now it's one, two, three, four, 23, 98, it looks perfect, it looks in the right amount and the right structure.
And really, this is just a very quick example of the benefit of getting familiar with closures. Then, once you understand how to use them, you can tap into huge amounts of functionality throughout the Apple frameworks. Not just with sorting, but with networking code and concurrency and animation, there are a lot of pieces of functionality that have been defined for you to provide just a little bit of extra logic and you do that by providing closures. They all expect a familiarity with this idea and your life is so much easier when you have that.
Дата добавления: 2015-08-20; просмотров: 76 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Defining and using enumerations | | | Writing closures Написание закрытия |