天天看點

關于泛型Generics

Introducing generics

You might not know it, but you’ve already seen generics at work while reading thisbook. Arrays and dictionaries are classic examples of the type safety of generics inaction.

Objective-C developers are accustomed to arrays and dictionaries holding objects ofmany types in the same collection. This provides for great flexibility, but how doyou know what an array returned from an API is meant to hold? You can only besure by looking at documentation or at variable names, another form of documentation. Even with documentation, there is nothing (other than bug-free

code!) to prevent something unexpected in the collection at runtime.

Swift, on the other hand, has typed arrays and dictionaries. An array of Ints canonly hold Ints and can never (for example) contain a String. This means you candocument code by writing code, allowing the compiler to do the type checking foryou.

For example, in Objective-C UIKit, the method that handles touches in a customview is as follows: 

- (void)touchesBegan:(NSSet *)toucheswithEvent:(UIEvent *)event; 

The set in this method is known to contain only UITouch instances, but onlybecause the documentation says so. Nothing is stopping the objects in there frombeing anything else, and you generally need to cast the touches in the set asUITouch instances to effectively treat them as UITouch objects.

Swift doesn’t have a set defined in the standard library at this time. However, if youused an array in place of a set, then you could write the above method like this: 

func touchesBegan(touches: [UITouch]!,withEvent event: UIEvent!) 

This tells you that the touches array only contains UITouch instances, and thecompiler will throw an error if the code calling this method tries to pass anythingelse. Not only does the compiler control types placed into the touches array, butyou no longer need to cast elements to instances of UITouch!

Overall, generics provide types as a parameter to the class. All arrays act the sameway, storing values in a list, but generic arrays parameterize value type. You mightfind it helpful to think of it like this: The algorithms you’ll use on arrays are non-type-specific, so all arrays, with all types of values, can share them.

Now that you have a basic sense of generics and their utility, you’re ready to applythem to a concrete scenario. 

Generics in action

To put generics to the test, you’re going to build an app that searches Flickr forimages.

To get you going speedily, there’s a starter project in the resources for this chapter.Open it and quickly familiarize yourself with the main classes. The Flickr classhandles talking to the Flickr API. Notice the API key is located with this class—onehas been provided, but you may want to use your own in case you want to expandon the app. You can sign up for one here: https://www.flickr.com/services/apps/by/ 

Build and run the app. You’ll see this:

Not much yet! Never fear, you’ll soon have this thing pulling in pictures of cats!(What else?)

Ordered dictionaries

Your app is going to download pictures for each user query. It will display them in alist with the most recent search at the top.

But what if your user searches for the same term twice? It would be nice if the appbrought the old results back up to the top of the most recent list and replaced itwith new results.

You might use an array for the data structure to back this, but for the purpose oflearning generics, you’re going to create a new collection: an ordered dictionary.

In many languages and frameworks (including Swift) sets and dictionaries do notguarantee any kind of order, in contrast to arrays. An ordered dictionary is like anormal dictionary, but the keys are in a defined order. You’ll use this functionalityto store search results keyed by search term, making it quick to find results andalso to maintain the order for the table view.

If you were being hasty, you might create a custom data structure to handle theordered dictionary. But you are forward thinking! You want to create somethingthat you can use in apps for years to come! This is a perfect use case for generics.