Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

the-swift-rogramming-language

.pdf
Скачиваний:
15
Добавлен:
11.05.2015
Размер:
4 Мб
Скачать
☆

Swift’s Array type also provides an initializer for creating an array of a certain size with all of its values set to a provided default value. You pass this initializer the number of items to be added to the new array (called count) and a default value of the appropriate type

(called repeatedValue):

var threeDoubles = Double[](count: 3, repeatedValue: 0.0)

// threeDoubles is of type Double[], and equals [0.0, 0.0, 0.0]

Thanks to type inference, you don’t need to specify the type to be stored in the array when using this initializer, because it can be inferred from the default value:

var anotherThreeDoubles = Array(count: 3, repeatedValue: 2.5)

// anotherThreeDoubles is inferred as Double[], and equals [2.5, 2.5, 2.5]

Finally, you can create a new array by adding together two existing arrays of compatible type with the addition operator (+). The new array’s type is inferred from the type of the two arrays you add together:

var sixDoubles = threeDoubles + anotherThreeDoubles

// sixDoubles is inferred as Double[], and equals [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]

Dictionaries

A dictionary is a container that stores multiple values of the same type. Each value is associated with a unique key, which acts as an identifier for that value within the dictionary. Unlike items in an array, items in a dictionary do not have a specified order. You use a dictionary when you need to look up values based on their identifier, in much the same way that a real-world dictionary is used to look up the definition for a particular word.

Swift dictionaries are specific about the types of keys and values they can store. They differ from Objective-C’s NSDictionary and NSMutableDictionary classes, which can use any kind of object as their keys and values and do not provide any information about the nature of these objects. In Swift, the type of keys and values that a particular dictionary can store is always made clear, either through an explicit type annotation or through type inference.

Swift’s dictionary type is written as Dictionary<KeyType, ValueType>, where KeyType is the type of value that can be used as a dictionary key, and ValueType is the type of value that the dictionary stores for those keys.

The only restriction is that KeyType must be hashable—that is, it must provide a way to make itself uniquely representable. All of Swift’s basic types (such as String, Int, Double, and Bool) are hashable by default, and all of these types can be used as the keys of a dictionary. Enumeration member values without associated values (as described in Enumerations) are also hashable by default.

Dictionary Literals

You can initialize a dictionary with with a dictionary literal, which has a similar syntax to the array literal seen earlier. A dictionary literal is a shorthand way to write one or more key-value pairs as a Dictionary collection.

A key-value pair is a combination of a key and a value. In a dictionary literal, the key and value in each key-value pair are separated by a colon. The key-value pairs are written as a list, separated by commas, surrounded by a pair of square brackets:

[ key 1 : value 1 , key 2 : value 2 , key 3 : value 3 ]

The example below creates a dictionary to store the names of international airports. In this dictionary, the keys are three-letter International Air Transport Association codes, and the values are airport names:

var airports: Dictionary<String, String> = ["TYO": "Tokyo", "DUB": "Dublin"]

The airports dictionary is declared as having a type of Dictionary<String, String>, which means “a Dictionary whose keys are of type String, and whose values are also of type String”.

N O T E

The airports dictionary is declared as a variable (with the var introducer), and not a constant (with the let introducer), because more airports will be added to the dictionary in the examples below.

The airports dictionary is initialized with a dictionary literal containing two key-value pairs. The first pair has a key of "TYO" and a value of "Tokyo". The second pair has a key of "DUB" and a value of "Dublin".

This dictionary literal contains two String: String pairs. This matches the type of the airports variable declaration (a dictionary with only String keys, and only String values) and so the assignment of the dictionary literal is permitted as a way to initialize the airports dictionary with two initial items.

As with arrays, you don’t have to write the type of the dictionary if you’re initializing it with a dictionary literal whose keys and values have consistent types. The initialization of airports could have been be written in a shorter form instead:

var airports = ["TYO": "Tokyo", "DUB": "Dublin"]

Because all keys in the literal are of the same type as each other, and likewise all values are of the same type as each other, Swift can infer that Dictionary<String, String> is the correct type to use for the airports dictionary.

Accessing and Modifying a Dictionary

You access and modify a dictionary through its methods and properties, or by using subscript syntax. As with an array, you can find out the number of items in a Dictionary by checking its read-only count property:

println("The dictionary of airports contains \(airports.count) items.") // prints "The dictionary of airports contains 2 items."

You can add a new item to a dictionary with subscript syntax. Use a new key of the appropriate type as the subscript index, and assign a new value of the appropriate type:

airports["LHR"] = "London"

// the airports dictionary now contains 3 items

You can also use subscript syntax to change the value associated with a particular key:

airports["LHR"] = "London Heathrow"

// the value for "LHR" has been changed to "London Heathrow"

As an alternative to subscripting, use a dictionary’s updateValue(forKey:) method to set or update the value for a particular key. Like the subscript examples above, the updateValue(forKey:) method sets a value for a key if none exists, or updates the value if that key already exists. Unlike a subscript, however, the updateValue(forKey:) method returns the old value after performing an update. This enables you to check whether or not an update took place.

The updateValue(forKey:) method returns an optional value of the dictionary’s value type. For a dictionary that stores String values, for example, the method returns a value of type String?, or “optional String”. This optional value contains the old value for that key if one existed

before the update, or nil if no value existed:

if let oldValue = airports.updateValue("Dublin International", forKey: "DUB") { println("The old value for DUB was \(oldValue).")

}

// prints "The old value for DUB was Dublin."

You can also use subscript syntax to retrieve a value from the dictionary for a particular key. Because it is possible to request a key for which no value exists, a dictionary’s subscript returns an optional value of the dictionary’s value type. If the dictionary contains a value for the requested key, the subscript returns an optional value containing the existing value for that key. Otherwise, the subscript returns nil:

if let airportName = airports["DUB"] {

println("The name of the airport is \(airportName).") } else {

println("That airport is not in the airports dictionary.")

}

// prints "The name of the airport is Dublin International."

You can use subscript syntax to remove a key-value pair from a dictionary by assigning a value of nil for that key:

airports["APL"] = "Apple International"

//"Apple International" is not the real airport for APL, so delete it airports["APL"] = nil

//APL has now been removed from the dictionary

Alternatively, remove a key-value pair from a dictionary with the removeValueForKey method. This method removes the key-value pair if it exists and returns the removed value, or returns nil if no value existed:

if let removedValue = airports.removeValueForKey("DUB") { println("The removed airport's name is \(removedValue).")

} else {

println("The airports dictionary does not contain a value for DUB.")

}

// prints "The removed airport's name is Dublin International."

Iterating Over a Dictionary

You can iterate over the key-value pairs in a dictionary with a for-in loop. Each item in the dictionary is returned as a (key, value) tuple, and you can decompose the tuple’s members into temporary constants or variables as part of the iteration:

for (airportCode, airportName) in airports { println("\(airportCode): \(airportName)")

}

//TYO: Tokyo

//LHR: London Heathrow

For more about the for-in loop, see For Loops.

You can also retrieve an iteratable collection of a dictionary’s keys or values by accessing its keys and values properties:

for airportCode in airports.keys { println("Airport code: \(airportCode)")

}

//Airport code: TYO

//Airport code: LHR

for airportName in airports.values { println("Airport name: \(airportName)")

}

ort name: Tokyo

ort name: London Heathrow

If you need to use a dictionary’s keys or values with an API that takes an Array instance, initialize a new array with the keys or values property:

let airportCodes = Array(airports.keys)

// airportCodes is ["TYO", "LHR"]

let airportNames = Array(airports.values)

// airportNames is ["Tokyo", "London Heathrow"]

N O T E

Swift’s Dictionary type is an unordered collection. The order in which keys, values, and key-value pairs are retrieved when iterating over a dictionary is not specified.

Creating an Empty Dictionary

As with arrays, you can create an empty Dictionary of a certain type by using initializer syntax:

var namesOfIntegers = Dictionary<Int, String>()

// namesOfIntegers is an empty Dictionary<Int, String>

This example creates an empty dictionary of type Int, String to store human-readable names of integer values. Its keys are of type Int, and its values are of type String.

If the context already provides type information, create an empty dictionary with an empty dictionary literal, which is written as [:] (a colon inside a pair of square brackets):

namesOfIntegers[16] = "sixteen"

//namesOfIntegers now contains 1 key-value pair namesOfIntegers = [:]

//namesOfIntegers is once again an empty dictionary of type Int, String

N O T E

Behind the scenes, Swift’s array and dictionary types are implemented as generic collections. For more on generic types and collections, see Generics.

Mutability of Collections

Arrays and dictionaries store multiple values together in a single collection. If you create an array or a dictionary and assign it to a variable, the collection that is created will be mutable. This means that you can change (or mutate) the size of the collection after it is created by adding more items to the collection, or by removing existing items from the ones it already contains. Conversely, if you assign an array or a dictionary to a constant, that array or dictionary is immutable, and its size cannot be changed.

For dictionaries, immutability also means that you cannot replace the value for an existing key in the dictionary. An immutable dictionary’s contents cannot be changed once they are set.

Immutability has a slightly different meaning for arrays, however. You are still not allowed to perform any action that has the potential to change the size of an immutable array, but you are allowed to set a new value for an existing index in the array. This enables Swift’s Array type to provide optimal performance for array operations when the size of an array is fixed.

The mutability behavior of Swift’s Array type also affects how array instances are assigned and modified. For more information, see Assignment and Copy Behavior for Collection Types.

N O T E

It is good practice to create immutable collections in all cases where the collection’s size does not need to change. Doing so enables the Swift compiler to optimize the performance of the collections you create.

break and

Control Flow

Swift provides all the familiar control flow constructs of C-like languages. These include for and while loops to perform a task multiple times; if and switch statements to execute different branches of code based on certain conditions; and statements such as

continue to transfer the flow of execution to another point in your code.

In addition to the traditional for-condition-increment loop found in C, Swift adds a for-in loop that makes it easy to iterate over arrays, dictionaries, ranges, strings, and other sequences.

Swift’s switch statement is also considerably more powerful than its counterpart in C. The cases of a switch statement do not “fall through” to the next case in Swift, avoiding common C errors caused by missing break statements. Cases can match many different types of pattern, including range matches, tuples, and casts to a specific type. Matched values in a switch case can be bound to temporary constants or variables for use within the case’s body, and complex matching conditions can be expressed with a where clause for each case.

For Loops

A for loop performs a set of statements a certain number of times. Swift provides two kinds of for loop:

for-in performs a set of statements for each item in a range, sequence, collection, or progression.

for-condition-increment performs a set of statements until a specific condition is met, typically by incrementing a counter each time the loop ends.

For-In

You use the for-in loop to iterate over collections of items, such as ranges of numbers, items in an array, or characters in a string.

This example prints the first few entries in the five-times-table:

for index in 1...5 {

println("\(index) times 5 is \(index * 5)")

}

//1 times 5 is 5

//2 times 5 is 10

//3 times 5 is 15

//4 times 5 is 20

//5 times 5 is 25

The collection of items being iterated is a closed range of numbers from 1 to 5 inclusive, as indicated by the use of the closed range operator (...). The value of index is set to the first number in the range (1), and the statements inside the loop are executed. In this case, the loop contains only one statement, which prints an entry from the five-times- table for the current value of index. After the statement is executed, the value of index is updated to contain the second value in the range (2), and the println function is called again. This process continues until the end of the range is reached.

In the example above, index is a constant whose value is automatically set at the start of each iteration of the loop. As such, it does not have to be declared before it is used. It is implicitly declared simply by its inclusion in the loop declaration, without the need for a let declaration keyword.

N O T E

The index constant exists only within the scope of the loop. If you want to check the value of index after the loop completes, or if you want to work with its value as a variable rather than a constant, you must declare it yourself before its use in the loop.

If you don’t need each value from the range, you can ignore the values by using an underscore in place of a variable name:

let base = 3 let power = 10 var answer = 1

for _ in 1...power { answer *= base

}

println("\(base) to the power of \(power) is \(answer)")

// prints "3 to the power of 10 is 59049"

This example calculates the value of one number to the power of another (in this case, 3 to the power of 10). It multiplies a starting value of 1 (that is, 3 to the power of 0) by 3, ten times, using a half-closed loop that starts with 0 and ends with 9. This calculation doesn’t need to know the individual counter values each time through the loop—it simply needs to execute the loop the correct number of times. The underscore character _ (used in place of a loop variable) causes the individual values to be ignored and does not provide access to the current value during each iteration of the loop.

Use the for-in loop with an array to iterate over its items:

let names = ["Anna", "Alex", "Brian", "Jack"] for name in names {

println("Hello, \(name)!")

}

//Hello, Anna!

//Hello, Alex!

//Hello, Brian!

//Hello, Jack!

You can also iterate over a dictionary to access its key-value pairs. Each item in the dictionary is returned as a (key, value) tuple when the dictionary is iterated, and you can decompose the (key, value) tuple’s members as explicitly named constants for use within in the body of the for-in loop. Here, the dictionary’s keys are decomposed into a constant called animalName, and the dictionary’s values are decomposed into a constant called

legCount:

let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4] for (animalName, legCount) in numberOfLegs {

println("\(animalName)s have \(legCount) legs")

}

//spiders have 8 legs

//ants have 6 legs

//cats have 4 legs

Items in a Dictionary may not necessarily be iterated in the same order as they were inserted. The contents of a Dictionary are inherently unordered, and iterating over them

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]