You are on page 1of 384

Acerca de Swift

NOTA
Para obtener la documentacin preliminar de una futura actualizacin de la lengua
Swift, ver El Swift Lenguaje de Programacin .
Swift es un nuevo lenguaje de programacin para iOS y OS X aplicaciones que se basa
en la mejor de C y Objective-C, sin las limitaciones de compatibilidad C. Swift adopta
patrones de programacin seguras y aade caractersticas modernas para hacer la
programacin ms fcil, ms flexible y ms divertido. Borrn y cuenta nueva de Swift,
respaldadas por los maduros y los marcos de cacao y cacao Touch muy querida, es una
oportunidad para re-imaginar cmo funciona el desarrollo de software.
Swift ha estado aos en la fabricacin. Manzana sent las bases de Swift por el avance
de nuestro compilador, depurador, y la infraestructura marco existente. Hemos
simplificado la gestin de memoria con el recuento de referencias automtico
(ARC). Nuestra pila marco, construido sobre la base slida de la Fundacin y el Cacao,
se ha modernizado y estandarizada en todo. Objective-C en s ha evolucionado para
soportar bloques, literales coleccin, y los mdulos, lo que permite la adopcin marco
de las tecnologas lingsticas modernas sin interrupciones. Gracias a este trabajo
preliminar, ahora podemos introducir un nuevo lenguaje para el futuro del desarrollo de
software de Apple.
Swift se siente familiar para los desarrolladores de Objective-C. Adopta la legibilidad
de los parmetros con nombre de Objective-C y el poder del modelo de objeto dinmico
de Objective-C. Proporciona un acceso transparente a los marcos existentes de cacao y
mezclar y combinar la interoperabilidad con cdigo de Objective-C. La construccin de
esta base comn, Swift introduce muchas nuevas caractersticas y unifica las partes
procesales y orientados a objetos del lenguaje.
Swift es amigable para los nuevos programadores. Es el primer lenguaje de
programacin de sistemas de calidad industrial que es tan expresiva y agradable como
un lenguaje de script. Es compatible con juegos infantiles, una caracterstica innovadora
que permite a los programadores para experimentar con el cdigo Swift y ver los
resultados inmediatamente, sin la sobrecarga de la creacin y ejecucin de una
aplicacin.
Swift combina lo mejor del pensamiento lengua moderna con la sabidura de la cultura
de ingeniera de Apple en general. El compilador est optimizado para el rendimiento, y
el idioma se ha optimizado para el desarrollo, sin comprometer a ambos. Est diseado
para escalar de "hola, mundo" a todo un sistema operativo. Todo esto hace que Swift
una inversin de futuro slido para los desarrolladores y para Apple.
Swift es una fantstica manera de escribir iOS y OS X aplicaciones, y seguir
evolucionando con nuevas caractersticas y capacidades. Nuestras metas para Swift son
ambiciosos. No podemos esperar a ver lo que creas con l.


A Swift tour

La tradicin sugiere que el primer programa en un nuevo idioma debe imprimir las
palabras "Hola, mundo!" En la pantalla. En Swift, esto se puede hacer en una sola lnea:
println ( "Hola, mundo!" )
Si ha escrito cdigo en C o Objective-C, esta sintaxis se parece familiar a usted-en
Swift, esta lnea de cdigo es un programa completo. No es necesario importar una
biblioteca independiente para la funcionalidad como de entrada / salida o manejo de
cadenas. El cdigo escrito en el mbito mundial se utiliza como punto de entrada para el
programa, por lo que no es necesario un principal funcin. Tambin no es necesario
escribir un punto y coma al final de cada sentencia.
Este tour le da suficiente informacin para empezar a escribir cdigo en Swift
mostrando cmo lograr una variedad de tareas de programacin. No se preocupe si
usted no entiende algo, todo lo presentado en este tour se explica en detalle en el resto
de este libro.
NOTA
Para una mejor experiencia, abra este captulo como un parque infantil en
Xcode. Parques infantiles permiten editar los listados de cdigo y ver el resultado
inmediatamente.
Descargar juegos
Los valores simples
Utilice dejar de hacer una constante y var para hacer una variable. El valor de una
constante no necesita ser conocido en tiempo de compilacin, pero usted debe asignarle
un valor exactamente una vez. Esto significa que puede usar constantes para nombrar un
valor que se determina una vez, pero utiliza en muchos lugares.

var myVariable = 42

myVariable = 50

let myConstant = 42
Una constante o variable deben tener el mismo tipo que el valor que se desea asignar a
la misma. Sin embargo, no siempre se tiene que escribir el tipo
explcitamente. Proporcionar un valor cuando se crea una constante o variable permite
al compilador deducir su tipo. En el ejemplo anterior, el compilador infiere
quemyVariable es un nmero entero debido a que su valor inicial es un nmero
entero.
Si el valor inicial no proporciona suficiente informacin (o si no hay valor inicial),
especificar el tipo de escritura que despus de la variable, separados por dos puntos.

let implicitInteger = 70

let implicitDouble = 70.0

let explicitDouble: Double = 70


EXPERIMENTO
Crear una constante con un tipo explcito de flotador y un valor de 4 .
Los valores no se convierten implcitamente a otro tipo. Si usted necesita para convertir
un valor a un tipo diferente, hacer explcita una instancia del tipo deseado.

let label = "The width is "

let width = 94
2

let widthLabel = label + String(width)


EXPERIMENTO
Trate de no incluir la conversin a la Cadena de la ltima lnea. Qu error Qu se
obtiene?
Hay una manera an ms fcil de incluir valores en cadenas: Escriba el valor entre
parntesis, y escribir una barra invertida ( \ ) antes del parntesis. Por ejemplo:

let apples = 3

let oranges = 5

let appleSummary = "I have \(apples) apples."

let fruitSummary = "I have \(apples + oranges) pieces of fruit."


EXPERIMENTO
Use \ () para incluir un clculo de punto flotante en una cadena y que incluya el
nombre de alguien en un saludo.
Crear matrices y diccionarios utilizando corchetes ( [] ), y acceder a sus elementos por
escribir el ndice o la clave entre corchetes.

var shoppingList = ["catfish", "water", "tulips", "blue paint"]

shoppingList[1] = "bottle of water"

var occupations = [

"Malcolm": "Captain",

"Kaylee": "Mechanic",

occupations["Jayne"] = "Public Relations"


Para crear una matriz vaca o diccionario, utilice la sintaxis de inicializador.

let emptyArray = [String]()

let emptyDictionary = [String: Float]()


Si la informacin de tipo se puede inferir, puede escribir una matriz vaca como [] y un
diccionario vaco como[:] ; por ejemplo, cuando se establece un nuevo valor para una
variable o pasar un argumento a una funcin.

shoppingList = []

occupations = [:]
Control de flujo
Utilice si y cambiar para hacer los condicionales, y utilizar para en , para , mientras , y hacer - mientras quepara hacer bucles. Los
parntesis alrededor de la variable de condicin o bucle son opcionales. Se requieren los
apoyos de todo el cuerpo.

let individualScores = [75, 43, 103, 87, 12]

var teamScore = 0

for score in individualScores {

if score > 50 {

teamScore += 3

} else {

teamScore += 1

teamScore
NOTA
En el cdigo anterior, teamScore se escribe en una lnea por s mismo. Esta es una
manera simple de ver el valor de una variable dentro de un parque infantil.
En un caso de declaracin, la condicin debe ser una expresin-este Booleano
significa que el cdigo comosi la puntuacin {...} es un error, no una
comparacin implcita a cero.
Usted puede utilizar si y dejar juntos para trabajar con valores que pudieran
faltar. Estos valores se representan como opcionales. Un valor opcional o bien contiene
un valor o contiene cero para indicar que el valor no est presente. Escriba un signo de
interrogacin ( ? ) despus de que el tipo de un valor para marcar el valor como
opcional.

var optionalString: String? = "Hello"

optionalString == nil

var optionalName: String? = "John Appleseed"

var greeting = "Hello!"

if let name = optionalName {

greeting = "Hello, \(name)"

}
EXPERIMENTO
Cambie optionalName a nil . Lo saludo Qu se obtiene? Aadir
una cosa clusula que establece un saludo diferente si optionalName es nula .
Si el valor opcional es nula , el condicional es falsa y el cdigo entre llaves se
omite. De lo contrario, el valor opcional se desenvuelve y se asigna a la constante
despus de let , lo que hace que el valor envolver disponible dentro del bloque de
cdigo.
Switches soportan cualquier tipo de datos y una amplia variedad de operaciones de
comparacin-que no se limitan a nmeros enteros y las pruebas para la igualdad.

let vegetable = "red pepper"

switch vegetable {

case "celery":

let vegetableComment = "Add some raisins and make ants on a log."

case "cucumber", "watercress":

let vegetableComment = "That would make a good tea sandwich."


case let x where x.hasSuffix("pepper"):

let vegetableComment = "Is it a spicy \(x)?"

default:

let vegetableComment = "Everything tastes good in soup."

}
EXPERIMENTO
Trate de no incluir el caso por defecto. Qu error Qu se obtiene?
Ntese cmo dejar que se puede utilizar en un patrn para asignar el valor que
coincide con esa parte de un patrn a una constante.
Despus de ejecutar el cdigo dentro de la caja del interruptor que haca juego, el
programa sale de la sentencia switch. Ejecucin no contina al siguiente caso, lo que no
hay necesidad de romper explcitamente del interruptor al final del cdigo de cada caso.
Se utiliza para - en iterar sobre los elementos de un diccionario, proporcionando un
par de nombres a utilizar para cada par clave-valor. Los diccionarios son una coleccin
desordenada, por lo que sus claves y valores se repiten a lo largo en un orden arbitrario.

let interestingNumbers = [

"Prime": [2, 3, 5, 7, 11, 13],

"Fibonacci": [1, 1, 2, 3, 5, 8],

"Square": [1, 4, 9, 16, 25],

var largest = 0

for (kind, numbers) in interestingNumbers {

for number in numbers {

if number > largest {

largest = number

largest
EXPERIMENTO
Aadir otra variable para realizar un seguimiento de qu tipo de nmero es el ms
grande, as como lo que mayor nmero era.
Utilice mientras que repetir un bloque de cdigo hasta que una condicin cambia. El
estado de un bucle puede estar en el extremo en su lugar, asegurando que el bucle se
ejecuta al menos una vez.

var n = 2

while n < 100 {

n=n*2

var m = 2

do {

m=m*2

} while m < 100

m
Usted puede mantener un ndice en un bucle, ya sea mediante el uso de .. < para
hacer una serie de ndices o escribiendo un explcito inicializacin, condicin, y el
incremento. Estos dos lazos hacen lo mismo:

var firstForLoop = 0

for i in 0..<4 {

firstForLoop += i

firstForLoop

var secondForLoop = 0

for var i = 0; i < 4; ++i {

secondForLoop += i

secondForLoop
Utilice .. < para hacer una serie que omite su valor superior, y usar ... para hacer
una gama que incluye ambos valores.
Funciones y cierres
Utilice func para declarar una funcin. Llamar a una funcin siguiendo su nombre con
una lista de argumentos entre parntesis. Uso -> para separar los nombres de los
parmetros y tipos de tipo de retorno de la funcin.

func greet(name: String, day: String) -> String {

return "Hello \(name), today is \(day)."

greet("Bob", "Tuesday")

EXPERIMENTO
Retire el da parmetro. Agregar un parmetro para incluir el almuerzo especial de hoy
en el saludo.

Utilice una tupla para hacer un ejemplo de valor para el compuesto, para devolver
varios valores de una funcin. Los elementos de una tupla se pueden denominar por su
nombre o por nmero.

func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {

var min = scores[0]

var max = scores[0]

var sum = 0

for score in scores {

if score > max {

max = score

} else if score < min {

min = score

sum += score

return (min, max, sum)

let statistics = calculateStatistics([5, 3, 100, 3, 9])

statistics.sum

statistics.2
Las funciones tambin pueden tomar un nmero variable de argumentos, a su recogida
en una matriz.

func sumOf(numbers: Int...) -> Int {

var sum = 0

for number in numbers {

sum += number

return sum

sumOf()

sumOf(42, 597, 12)


EXPERIMENTO
Escriba una funcin que calcula el promedio de sus argumentos.
Las funciones pueden ser anidados. Funciones anidadas tienen acceso a las variables
que fueron declaradas en la funcin externa. Puede utilizar las funciones anidadas para
organizar el cdigo en una funcin que es largo o complejo.

func returnFifteen() -> Int {

var y = 10

func add() {

y += 5

add()

return y

returnFifteen()
Las funciones son un tipo de primera clase. Esto significa que una funcin puede
devolver otra funcin como su valor.

func makeIncrementer() -> (Int -> Int) {

func addOne(number: Int) -> Int {

return 1 + number

return addOne

var increment = makeIncrementer()

increment(7)
Una funcin puede tener otra funcin como uno de sus argumentos.

func hasAnyMatches(list: [Int], condition: Int -> Bool) -> Bool {

for item in list {

if condition(item) {

return true

return false

func lessThanTen(number: Int) -> Bool {

return number < 10

var numbers = [20, 19, 7, 12]

hasAnyMatches(numbers, lessThanTen)
Las funciones son en realidad un caso especial de cierres: bloques de cdigo que se
pueden llamar ms tarde. El cdigo en un cierre tiene acceso a cosas como las variables
y funciones que estaban disponibles en el mbito donde se cre el cierre, incluso si el
cierre es en un mbito diferente cuando se ejecuta-que viste un ejemplo de esto ya con

funciones anidadas. Usted puede escribir un cierre sin nombre rodeando cdigo con
llaves ( {} ). Utilice en separar los argumentos y el tipo de retorno del cuerpo.

numbers.map({

(number: Int) -> Int in

let result = 3 * number

return result

})
EXPERIMENTO
Vuelva a escribir el cierre para volver a cero para todos los nmeros impares.
Usted tiene varias opciones para la escritura de los cierres de forma ms
concisa. Cuando el tipo de un cierre que ya se conoce, por ejemplo, la devolucin de
llamada de un delegado, se puede omitir el tipo de sus parmetros, el tipo de retorno, o
ambos. Cierres sola instruccin implcitamente devuelven el valor de su nica
declaracin.

let mappedNumbers = numbers.map({ number in 3 * number })

mappedNumbers
Se puede hacer referencia a los parmetros de nmero en vez de por su nombre-este
enfoque es especialmente til en los cierres muy cortos. Un cierre pasado como el
ltimo argumento de la funcin puede aparecer inmediatamente despus del parntesis.

let sortedNumbers = sorted(numbers) { $0 > $1 }

sortedNumbers
Objetos y clases
Utilice la clase seguido del nombre de la clase para crear una clase. Una
declaracin de propiedad en una clase se escribe de la misma manera como una
declaracin de constante o variable, excepto que es en el contexto de una clase. De igual
forma, mtodo y funcin declaraciones se escriben de la misma manera.

class Shape {

var numberOfSides = 0

func simpleDescription() -> String {

return "A shape with \(numberOfSides) sides."

}
EXPERIMENTO
Aadir una propiedad constante con let , y aadir otro mtodo que toma un
argumento.
Crear una instancia de una clase, poniendo entre parntesis despus del nombre de la
clase. Utilice la sintaxis con punto para acceder a las propiedades y mtodos de la
instancia.

var shape = Shape()

shape.numberOfSides = 7

var shapeDescription = shape.simpleDescription()


Esta versin de la Forma clase le falta algo importante: un inicializador para configurar
la clase cuando se crea una instancia. Utilice init para crear una.

class NamedShape {

var numberOfSides: Int = 0

var name: String

init(name: String) {

self.name = name

func simpleDescription() -> String {

return "A shape with \(numberOfSides) sides."

}
Observe cmo auto se utiliza para distinguir el nombre de la propiedad
del nombre de argumento para el inicializador. Los argumentos para el inicializador
se pasan como una llamada a la funcin cuando se crea una instancia de la clase. Cada
propiedad necesita un valor asignado, ya sea en su declaracin (como
connumberOfSides ) o en el inicializador (como con el nombre ).
Utilice deinit para crear un deinitializer si es necesario realizar alguna tarea de
limpieza antes de que se cancela la asignacin del objeto.
Las subclases incluyen su nombre despus de su superclase nombre de la clase,
separados por dos puntos.No hay ningn requisito para las clases subclase cualquier
clase raz estndar, por lo que puede incluir u omitir una superclase, segn sea
necesario.
Los mtodos en una subclase que anulan la implementacin de la superclase estn
marcados con el override-overriding un mtodo por el accidente, sin anulacin ,
es detectado por el compilador como un error. El compilador tambin detecta con
mtodos de anulacin que en realidad no anulan cualquier mtodo en la superclase.

class Square: NamedShape {

var sideLength: Double

init(sideLength: Double, name: String) {

self.sideLength = sideLength

super.init(name: name)

numberOfSides = 4

func area() -> Double {


10

return sideLength * sideLength

override func simpleDescription() -> String {

return "A square with sides of length \(sideLength)."

let test = Square(sideLength: 5.2, name: "my test square")

test.area()

test.simpleDescription()
EXPERIMENTO
Haga otra subclase de NamedShape llamado Crculo que tiene un radio y un
nombre como argumentos a su inicializador. Implementar un rea y
un simpleDescription mtodo en el Crculo de clase.
Adems de las propiedades simples que se almacenan, las propiedades pueden tener un
getter y un setter.

class EquilateralTriangle: NamedShape {

var sideLength: Double = 0.0

init(sideLength: Double, name: String) {

self.sideLength = sideLength

super.init(name: name)

numberOfSides = 3

var perimeter: Double {

get {

return 3.0 * sideLength

set {

sideLength = newValue / 3.0

override func simpleDescription() -> String {

return "An equilateral triangle with sides of length \(sideLength)."

11

var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")

triangle.perimeter

triangle.perimeter = 9.9

triangle.sideLength
En la incubadora de permetro , el nuevo valor tiene el nombre
implcito nuevoValor . Puede proporcionar un nombre explcito entre parntesis
despus de conjunto .
Observe que el inicializador para la EquilateralTriangle clase tiene tres etapas
diferentes:
1. Establecer el valor de las propiedades que la subclase declara.
2. Llamando inicializador de la superclase.
3. Cambiar el valor de las propiedades definidas por la superclase. Cualquier trabajo de
configuracin adicional que utiliza mtodos getters o setters tambin se puede hacer
en este momento.
Si no es necesario para calcular la propiedad, pero todava tiene que proporcionar el
cdigo que se ejecuta antes y despus de fijar un nuevo valor,
utilice willSet y didSet . Por ejemplo, la clase a continuacin se asegura de que la
longitud del lado de su tringulo es siempre la misma que la longitud del lado de su
cuadrado.

class TriangleAndSquare {

var triangle: EquilateralTriangle {

willSet {

square.sideLength = newValue.sideLength

var square: Square {

willSet {

triangle.sideLength = newValue.sideLength

init(size: Double, name: String) {

square = Square(sideLength: size, name: name)

triangle = EquilateralTriangle(sideLength: size, name: name)

var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")

triangleAndSquare.square.sideLength

triangleAndSquare.triangle.sideLength

12

triangleAndSquare.square = Square(sideLength: 50, name: "larger square")

triangleAndSquare.triangle.sideLength
Los mtodos de las clases tienen una diferencia importante de funciones. Los nombres
de parmetros en funciones slo se utilizan dentro de la funcin, pero los parmetros
nombres en los mtodos tambin se utilizan cuando se llama al mtodo (excepto para el
primer parmetro). Por defecto, un mtodo tiene el mismo nombre para sus parmetros
cuando se llama a ella y dentro del mtodo en s. Se puede especificar un segundo
nombre, que se utiliza dentro del mtodo.

class Counter {

var count: Int = 0

func incrementBy(amount: Int, numberOfTimes times: Int) {

count += amount * times

var counter = Counter()

counter.incrementBy(2, numberOfTimes: 7)
Cuando se trabaja con valores opcionales, puede escribir ? antes de las operaciones,
como los mtodos, propiedades y subndices. Si el valor antes de la ? es nula , todo
despus de la ? se ignora y el valor de toda la expresin es nula . De lo contrario, el
valor es opcional sin envolver, y todo despus de la ? acta sobre el valor de
envolver. En ambos casos, el valor de toda la expresin es un valor opcional.

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")

let sideLength = optionalSquare?.sideLength


Las enumeraciones y estructuras
Utilice enum para crear una enumeracin. Al igual que las clases y todos los dems
tipos con nombre, enumeraciones pueden tener mtodos asociados con ellos.

enum Rank: Int {

case Ace = 1

case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten

case Jack, Queen, King

func simpleDescription() -> String {

switch self {

case .Ace:

return "ace"

case .Jack:

return "jack"

case .Queen:

return "queen"

case .King:

13

return "king"

default:

return String(self.toRaw())

let ace = Rank.Ace

let aceRawValue = ace.toRaw()


EXPERIMENTO
Escriba una funcin que compara dos Rank valores mediante la comparacin de sus
valores brutos.
En el ejemplo anterior, el tipo de valor bruto de la enumeracin es int , por lo que slo
tiene que especificar el primer valor crudo. El resto de los valores brutos se asignan en
orden. Tambin puede utilizar cadenas o nmeros de punto flotante como el tipo de
prima de una enumeracin.
Utilice los toRaw y fromRaw funciones para convertir entre el valor bruto y el valor
de la enumeracin.

if let convertedRank = Rank.fromRaw(3) {

let threeDescription = convertedRank.simpleDescription()

}
Los valores de los miembros de una enumeracin son valores reales, no slo otra
manera de escribir sus valores brutos. De hecho, en los casos donde no hay un valor en
bruto significativo, usted no tiene que proporcionar una.

enum Suit {

case Spades, Hearts, Diamonds, Clubs

func simpleDescription() -> String {

switch self {

case .Spades:

return "spades"

case .Hearts:

return "hearts"

case .Diamonds:

return "diamonds"

case .Clubs:

return "clubs"

let hearts = Suit.Hearts


14

let heartsDescription = hearts.simpleDescription()


EXPERIMENTO
Agregar un color de mtodo para Suit que devuelve "negro" para espadas y palos,
y los retornos "rojos" de corazones y diamantes.
Observe las dos formas en que el Hearts miembro de la enumeracin se hace
referencia ms arriba: Al asignar un valor a los corazones constantes, los miembros
de enumeracin Suit.Hearts se refiere por su nombre completo porque la constante
no tiene un tipo explcito especificado. En el interior del interruptor, la enumeracin es
referido por la forma abreviada .Hearts porque el valor del auto que ya se sabe que
es un juego. Usted puede utilizar el formulario abreviado en cualquier momento el tipo
del valor que ya se conoce.
Utilice struct para crear una estructura. Estructuras de soporte para muchas de las
mismas conductas como las clases, incluyendo mtodos y inicializadores. Una de las
diferencias ms importantes entre las estructuras y las clases es que las estructuras
siempre se copian cuando se pasan alrededor en su cdigo, pero las clases se pasan por
referencia.

struct Card {

var rank: Rank

var suit: Suit

func simpleDescription() -> String {

return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"

let threeOfSpades = Card(rank: .Three, suit: .Spades)

let threeOfSpadesDescription = threeOfSpades.simpleDescription()


EXPERIMENTO
Agregue un mtodo para la tarjeta que crea una baraja completa de tarjetas, con
una carta de cada combinacin de rango y palo.
Una instancia de un miembro de la enumeracin puede tener valores asociados con la
instancia. Las instancias de la misma miembro de enumeracin pueden tener diferentes
valores asociados con ellos. Usted proporciona los valores asociados al crear la
instancia. Valores asociados y valores primas son diferentes: El valor bruto de un
miembro de la enumeracin es el mismo para todas sus instancias, y le proporcionar el
valor en bruto cuando se define la enumeracin.
Por ejemplo, considere el caso de solicitar el amanecer y el atardecer hora de un
servidor. El servidor o bien responde con la informacin o responde con un poco de
informacin de error.

enum ServerResponse {

case Result(String, String)

case Error(String)

15

let success = ServerResponse.Result("6:00 am", "8:09 pm")

let failure = ServerResponse.Error("Out of cheese.")

switch success {

case let .Result(sunrise, sunset):

let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)."

case let .Error(error):

let serverResponse = "Failure... \(error)"

}
EXPERIMENTO
Aadir un tercer caso a ServerResponse y para el interruptor.
Observe cmo se extraen las horas de salida y puesta del sol desde
el ServerResponse valor como parte de hacer coincidir el valor contra los casos de
conmutacin.
Protocolos y Extensiones
Utilice el protocolo para declarar un protocolo.

protocol ExampleProtocol {

var simpleDescription: String { get }

mutating func adjust()

}
Las clases, enumeraciones y estructuras de todo pueden adoptar protocolos.

class SimpleClass: ExampleProtocol {

var simpleDescription: String = "A very simple class."

var anotherProperty: Int = 69105

func adjust() {

simpleDescription += " Now 100% adjusted."

var a = SimpleClass()

a.adjust()

let aDescription = a.simpleDescription

struct SimpleStructure: ExampleProtocol {

var simpleDescription: String = "A simple structure"

mutating func adjust() {

simpleDescription += " (adjusted)"

16

var b = SimpleStructure()

b.adjust()

let bDescription = b.simpleDescription


EXPERIMENTO
Escribe una enumeracin que se ajusta a este protocolo.
Note el uso de la mutacin de la palabra clave en la declaracin
de SimpleStructure para marcar un mtodo que modifica la estructura. La
declaracin de SimpleClass no necesita ninguno de sus mtodos marcados como
mutando debido a los mtodos de una clase siempre puede modificar la clase.
Utilice la extensin para agregar funcionalidad a un tipo existente, tales como
nuevos mtodos y propiedades calculadas. Puede utilizar una extensin para aadir
conformidad protocolo a un tipo que se declara en otro lugar, o incluso a un tipo que ha
importado de una biblioteca o un marco.

extension Int: ExampleProtocol {

var simpleDescription: String {

return "The number \(self)"

mutating func adjust() {

self += 42

7.simpleDescription
EXPERIMENTO
Escribe una extensin para el doble tipo, que aade un absoluteValue propiedad.
Puede utilizar un nombre de protocolo al igual que cualquier otro ejemplo de tipo de
llamada, para crear una coleccin de objetos que tienen diferentes tipos, sino que todos
cumplir con un protocolo nico. Cuando se trabaja con valores cuyo tipo es un tipo de
protocolo, los mtodos fuera de la definicin de protocolo no estn disponibles.

let protocolValue: ExampleProtocol = a

protocolValue.simpleDescription

// protocolValue.anotherProperty // Uncomment to see the error


A pesar de que la variable protocolValue tiene un tipo de tiempo de ejecucin
de SimpleClass , el compilador lo trata como el tipo dado
de ExampleProtocol . Esto significa que no se puede acceder accidentalmente a los
mtodos o propiedades que la clase implementa adems de su conformidad protocolo.
Genricos
Escriba un nombre dentro de parntesis angulares para hacer una funcin genrica o
tipo.

func repeat<ItemType>(item: ItemType, times: Int) -> [ItemType] {

var result = [ItemType]()

for i in 0..<times {

17

result.append(item)

return result

repeat("knock", 4)
Usted puede hacer las formas genricas de las funciones y mtodos, as como las clases,
enumeraciones y estructuras.
// Reimplementar tipo opcional de la biblioteca estndar de

Swift

enum OptionalValue<T> {

case None

case Some(T)

var possibleInteger: OptionalValue<Int> = .None

possibleInteger = .Some(100)
Use where after the type name to specify a list of requirementsfor example, to require
the type to implement a protocol, to require two types to be the same, or to require a
class to have a particular superclass.

func anyCommonElements <T, U where T: SequenceType, U: SequenceType,


T.Generator.Element: Equatable, T.Generator.Element == U.Generator.Element> (lhs:
T, rhs: U) -> Bool {

for lhsItem in lhs {

for rhsItem in rhs {

if lhsItem == rhsItem {

return true

return false

anyCommonElements([1, 2, 3], [3])

anyCommonElements ([ 1 , 2 , 3 ], [ 3 ])
EXPERIMENTO
Modifique el anyCommonElements funcin para realizar una funcin que devuelve
una matriz de los elementos que las dos secuencias tienen en comn.
En los casos sencillos, se puede omitir cuando y simplemente escriba el nombre del
protocolo o de clase despus de dos puntos. Escribiendo <T: equatable> es lo
mismo que escribir <T donde T: equatable> .

18

Los Fundamentos
En esta pgina
Swift es un nuevo lenguaje de programacin para iOS y OS X de desarrollo de
aplicaciones. No obstante, muchas partes de Swift estarn familiarizados desde su
experiencia en el desarrollo en C y Objective-C.
Swift proporciona sus propias versiones de todos los tipos C y Objective-C
fundamentales, incluido Int para enteros, doble y flotador para los valores de
punto flotante, Bool para valores booleanos y de cadena para los datos
textuales. Swift tambin ofrece versiones potentes de los dos tipos de recoleccin
primaria, matriz yDiccionario , como se describe en Tipos Collection .
Al igual que C, Swift utiliza variables para almacenar y hacer referencia a los valores
por un nombre de identificacin. Swift tambin hace un amplio uso de variables cuyos
valores no se pueden cambiar. Estos son conocidos como constantes, y son mucho ms
poderosos que las constantes en C. Las constantes se utilizan a lo largo Swift para hacer
el cdigo ms seguro y ms clara en su intencin cuando se trabaja con valores que no
tienen que cambiar.
Adems de los tipos conocidos, Swift presenta tipos avanzadas que no se encuentran en
Objective-C, como tuplas. Tuples le permiten crear y pasar alrededor de agrupaciones
de valores. Puede usar una tupla para devolver varios valores de una funcin como un
valor nico compuesto.
Swift tambin introduce tipos opcionales, que se encargan de la ausencia de un
valor. Opcionales dicen bien "no es un valor, y que es igual a x "o" no , no es un valor
en absoluto ". Opcionales son similares al uso de nilcon punteros en Objective-C, pero
trabajan para cualquier tipo, no slo a las clases. Opcionales son ms seguros y ms
expresiva que nil punteros en Objective-C y estn en el centro de muchas de las
caractersticas ms poderosas de Swift.
Opcionales son un ejemplo del hecho de que Swift es un seguro de tipo de
idioma. Swift le ayuda a ser claro acerca de los tipos de valores de su cdigo puede
trabajar. Si parte de su cdigo espera una cuerda , la seguridad de tipos le impide
pasndole un Int por error. Esta restriccin le permite capturar y corregir los errores lo
antes posible en el proceso de desarrollo.
Constantes y Variables
Constantes y variables asociar un nombre
(como maximumNumberOfLoginAttempts o WelcomeMessage ) con un valor
de un tipo concreto (por ejemplo, el nmero 10 o la cadena "Hola" ). El valor de
una constante no se puede cambiar una vez que se establece, mientras que una variable
de puede ajustarse a un valor diferente en el futuro.
Declaracin de constantes y variables
Constantes y variables deben ser declaradas antes de ser utilizadas. Usted declara
constantes con la let de palabras clave y las variables con la var palabra clave. He
aqu un ejemplo de cmo las constantes y las variables se pueden utilizar para realizar el
seguimiento del nmero de intentos de inicio de sesin de un usuario ha hecho:

let maximumNumberOfLoginAttempts = 10

var currentLoginAttempt = 0
Este cdigo se puede leer como:

19

"Declarar una nueva constante llamada maximumNumberOfLoginAttempts , y


darle un valor de 10 . A continuacin, declarar una nueva variable
llamada currentLoginAttempt , y darle un valor inicial de 0 ".
En este ejemplo, el nmero mximo de intentos de inicio de sesin permitidos se
declara como una constante, debido a que el valor mximo nunca cambia. El contador
de inicio de sesin actual intento se declara como una variable, ya que este valor debe
ser incrementado despus de cada intento fallido de inicio de sesin.
Se pueden declarar varias constantes o variables mltiples en una misma lnea,
separados por comas:
var x = 0,0 , y = 0,0 , z = 0,0
NOTA
Si un valor almacenado en el cdigo no va a cambiar, siempre declararemos como una
constante con la letpalabra clave. Utilice variables slo para almacenar valores que
deben ser capaces de cambiar.
Tipo Anotaciones
Puede proporcionar una anotacin de tipo cuando se declara una constante o variable,
para tener claro el tipo de valores de la tienda lata constante o variable. Escribe una
anotacin de tipo mediante la colocacin de dos puntos despus del nombre de la
constante o variable, seguido por un espacio, seguido por el nombre del tipo de usar.
Este ejemplo proporciona una anotacin de tipo para una variable
llamada WelcomeMessage , para indicar que la variable puede almacenar de
Cuerda valores:
var welcomeMessage: String
Los dos puntos en la declaracin significa "... el tipo ...", por lo que el cdigo anterior se
puede leer como:
"Declarar una variable llamada WelcomeMessage que es del tipo String. "
La frase "de tipo String "significa" puede almacenar cualquier Cadena de valor.
"Piense en ello como que significa" el tipo de cosas "(o" el tipo de cosa ") que se puede
almacenar.
El WelcomeMessage variables ahora se puede ajustar a cualquier valor de cadena sin
error:
WelcomeMessage = "Hola"
Puede definir mltiples variables relacionadas del mismo tipo en una sola lnea,
separados por comas, con un solo tipo de anotacin despus de que el nombre de la
variable definitiva:

var red, green, blue: Double


NOTA
Es raro que usted necesita para escribir anotaciones de tipo en la prctica. Si
proporciona un valor inicial para una constante o variable en el punto que se define,
Swift casi siempre se puede inferir el tipo que se utilizar para que constante o variable,
como se describe en el tipo de seguridad y la inferencia de tipos . En
la WelcomeMessage ejemplo anterior, no se proporciona ningn valor inicial, por lo
que el tipo de laWelcomeMessage variable se especifica con una anotacin de tipo en
lugar de ser inferido a partir de un valor inicial.

20

Nombrar constantes y variables


Los nombres de constantes y variables pueden contener casi cualquier carcter,
incluidos los caracteres Unicode:

let = 3.14159

let = ""

let
= "dogcow"
Los nombres de constantes y variables no pueden contener espacios en blanco, smbolos
matemticos, flechas, de uso privado (o no vlidos) los puntos de cdigo Unicode o
caracteres de lnea y caja de dibujo.Tampoco pueden comenzar con un nmero, aunque
las cifras pueden ser incluidos en otro lugar dentro del nombre.
Una vez que se ha declarado una constante o variable de un cierto tipo, no se puede
redeclare de nuevo con el mismo nombre, o cambiarlo para almacenar valores de un
tipo diferente. Tampoco se puede cambiar una constante en una variable o una variable
en una constante.
NOTA
Si usted necesita dar una constante o variable el mismo nombre que una palabra clave
reservada Swift, rodear la palabra clave con la espalda garrapatas ( ` ) cuando se utiliza
como un nombre. Sin embargo, evite el uso de palabras clave como nombres a menos
que tenga absolutamente ninguna opcin.
Puede cambiar el valor de una variable existente a otro valor de un tipo compatible. En
este ejemplo, el valor de friendlyWelcome se cambia
de "Hola!" a "Bonjour!" :

var friendlyWelcome = "Hello!"

friendlyWelcome = "Bonjour!"

// friendlyWelcome is now "Bonjour!"


A diferencia de una variable, el valor de una constante no se puede cambiar una vez que
se establece. Si lo intenta, se reporta como un error cuando se compila el cdigo:

let languageName = "Swift"

languageName = "Swift++"

// Se trata de un error de tiempo de compilacin languageName no se puede cambiar


Constantes de impresin y variables
Usted puede imprimir el valor actual de una constante o variable con
el println funcin:

println(friendlyWelcome)

// prints "Bonjour!"
println es una funcin global que imprime un valor, seguido por un salto de lnea, a
una salida apropiada. En Xcode, por ejemplo, println imprime su salida en el panel
de "consola" de Xcode. (Una segunda funcin, la impresin , realiza la misma
tarea sin anexar un salto de lnea al final del valor que se va a imprimir.)
El println funcin imprime cualquier Cadena de valor se pasa a la misma:

println("This is a string")

21

// prints "This is a string"


El println funcin puede imprimir mensajes de registro ms complejos, de una
manera similar a la de CocoaNSLog funcin. Estos mensajes pueden incluir los valores
actuales de constantes y variables.
Swift utiliza interpolacin de cadenas para incluir el nombre de una constante o
variable como un marcador de posicin en una cadena ms larga, ya una pronta Swift
sustituirlo por el valor actual de esa constante o variable. Envuelva el nombre entre
parntesis y escapar con una barra invertida antes del parntesis de apertura:

println("The current value of friendlyWelcome is \(friendlyWelcome)")

// Impresiones "El valor actual de friendlyWelcome es


Bonjour!"
NOTA
Todas las opciones que puede utilizar con la interpolacin de cadenas se describen en
la Cadena de interpolacin .
Comentarios
Utilice los comentarios para incluir texto no ejecutable en su cdigo, como una nota o
un recordatorio a s mismo. Los comentarios son ignorados por el compilador Swift
cuando se compila el cdigo.
Comentarios en Swift son muy similares a los comentarios en C. sola lnea Los
comentarios comienzan con dos barras inclinadas (forward- // ):

// Esto es un comentario
Los comentarios multilnea empiezan con una barra inclinada seguida de un asterisco
( / * ) y terminan con un asterisco seguido de una barra diagonal ( * / ):

/ * Este es tambin un comentario,

pero escrito en varias lneas * /


A diferencia de los comentarios de varias lneas en C, los comentarios de varias lneas
en Swift se pueden anidar dentro de otros comentarios multilnea. Usted escribe
comentarios anidados por iniciar un bloque de varias lneas de comentarios y luego
iniciar un segundo comentario de varias lneas en el primer bloque. El segundo bloque
se cierra a continuacin, seguido por el primer bloque:
/ * Este es el comienzo de la primera comentario multilnea

/ * Esta es la segunda, comentario de varias lneas anidada


* /

este es el final de la primera comentario multilnea * /


Comentarios multilnea anidadas permiten a comentar a cabo grandes bloques de cdigo
de forma rpida y sencilla, incluso si el cdigo contiene ya los comentarios de varias
lneas.
Punto y coma
A diferencia de muchos otros idiomas, Swift no requiere que usted escriba un punto y
coma ( ; ) despus de cada sentencia en el cdigo, aunque puede hacerlo si lo
desea. Los puntos y comas se requiere, sin embargo, si desea escribir varias
instrucciones separadas en una sola lnea:

let cat = " "; println(cat)


22

// prints " "


Enteros
Los enteros son nmeros enteros sin componente fraccional, como 42 y -23 . Los
nmeros enteros se seafirmado (positivo, cero o negativo) o sin signo (positivo o cero).
Swift proporciona firmado y enteros sin signo de 8, 16, 32 y 64 forma de bits. Estos
enteros siguen una convencin de nomenclatura similar a C, en que un entero sin signo
de 8 bits es de tipo Uint8 , y un entero con signo de 32 bits es de tipo Int32 . Al
igual que todos los tipos de Swift, estos tipos enteros tienen nombres propios.
Entero lmites
Usted puede acceder a los valores mnimo y mximo de cada tipo entero con
su min y max propiedades:

let minValue = UInt8.min // minValue is equal to 0, and is of type UInt8

let maxValue = UInt8.max // maxValue is equal to 255, and is of type UInt8


Los valores de estas propiedades son del tipo de nmero de tamao apropiado (tales
como Uint8 en el ejemplo anterior) y por lo tanto se pueden utilizar en expresiones
junto con otros valores del mismo tipo.
Int
En la mayora de los casos, usted no tiene que elegir un tamao especfico de nmero
entero para utilizar en su cdigo. Swift proporciona un tipo entero adicional, Int , que
tiene el mismo tamao que el tamao de palabra nativa de la plataforma actual:
En una plataforma de 32 bits, Int es del mismo tamao que Int32 .
En una plataforma de 64 bits, Int es del mismo tamao que Int64 .
A menos que usted necesita para trabajar con un tamao especfico de nmero entero,
utilice siempre Intpara valores enteros en el cdigo. Esto ayuda cdigo de coherencia
y la interoperabilidad. Incluso en las plataformas de 32 bits, Int puede almacenar
cualquier valor entre -2147483648 y 2147483647 , y es lo suficientemente grande
para muchos rangos enteros.
UInt
Swift tambin proporciona un tipo entero sin signo, UInt , que tiene el mismo tamao
que el tamao de palabra nativa de la plataforma actual:
En una plataforma de 32 bits, UInt es del mismo tamao que UInt32 .
En una plataforma de 64 bits, UInt es del mismo tamao que UInt64 .
NOTA
Uso UInt slo cuando se necesita especficamente un tipo entero sin signo con el
mismo tamao que el tamao de palabra nativa de la plataforma. Si este no es el
caso, Int se prefiere, incluso cuando los valores a ser almacenados son conocidos por
ser no negativo. Un uso consistente de Int para el cdigo de ayudas valores enteros
interoperabilidad, evita la necesidad de convertir entre diferentes tipos de nmeros, y
coincide con el tipo entero de inferencia, como se describe en el tipo de seguridad y tipo
de inferencia .
Nmeros de punto flotante
Nmeros de coma flotante son nmeros con un componente fraccional,
como 3.14159 , 0.1 , y -273.15 .
Tipos de punto flotante pueden representar una gama mucho ms amplia de valores que
los tipos enteros, y pueden almacenar nmeros que son mucho ms grandes o ms

23

pequeos que se pueden almacenar en unint . Swift proporciona dos tipos de nmeros
de punto flotante firmados:
Doble representa un nmero de punto flotante de 64 bits. selo cuando los valores
de punto flotante deben ser muy grandes o particularmente precisa.
Float representa un nmero de punto flotante de 32 bits. selo cuando los valores
de punto flotante no requieren precisin de 64 bits.
NOTA
Doble tiene una precisin de al menos 15 dgitos decimales, mientras que la precisin
de flotador puede ser tan poco como 6 dgitos decimales. El tipo de punto flotante
apropiado utilizar depende de la naturaleza y el rango de valores que necesita para
trabajar en su cdigo.
Escriba Seguridad y tipo de inferencia
Swift es un seguro de tipo de idioma. Un lenguaje de tipo seguro anima a ser claro
acerca de los tipos de valores de su cdigo puede trabajar. Si parte de su cdigo espera
una cuerda , no se puede pasar un int por error.
Debido Swift es un tipo seguro, realiza escribir cheques al compilar el cdigo y
banderas cualesquiera tipos no coincidentes como errores. Esto le permite capturar y
corregir los errores lo antes posible en el proceso de desarrollo.
Tipo de comprobacin le ayuda a evitar errores cuando se trabaja con diferentes tipos de
valores. Sin embargo, esto no significa que usted tiene que especificar el tipo de cada
constante y variable que se declara. Si no se especifica el tipo de valor que necesita,
Swift utiliza la inferencia de tipos para calcular el tipo apropiado. La inferencia de tipos
permite un compilador para deducir el tipo de una expresin concreta de forma
automtica cuando se compila el cdigo, simplemente mediante el examen de los
valores suministrados por el usuario.
Debido a la inferencia de tipos, Swift requiere muchos menos declaraciones de tipo que
lenguajes como C o Objective-C. Constantes y variables todava se escriben de forma
explcita, pero gran parte del trabajo de especificar su tipo est hecho para usted.
La inferencia de tipos es particularmente til cuando se declara una constante o variable
con un valor inicial.Esto se suele hacer mediante la asignacin de un valor
literal (o literal ) a la constante o variable en el punto que se declara. (Un valor literal es
un valor que aparece directamente en el cdigo fuente, como 42 y 3,14159en los
ejemplos a continuacin.)
Por ejemplo, si se asigna un valor literal de 42 a una nueva constante sin decir de qu
tipo es, Swift infiere que desea que la constante de ser un int , porque usted ha
inicializado con un nmero que se ve como un entero:

// MeaningOfLife se infiere a ser de tipo Int


Del mismo modo, si no se especifica un tipo de un literal de coma flotante, Swift infiere
que desea crear undoble :

let meaningOfLife = 42

let pi = 3.14159

// Pi se infiere a ser de tipo doble


Swift siempre elige doble (en lugar de Float ) cuando inferir el tipo de nmeros en
coma flotante.

24

Si combina enteros y de punto flotante literales en una expresin, un tipo


de doble ser inferirse del contexto:

let anotherPi = 3 + 0.14159

// AnotherPi tambin se infiere a ser de tipo doble


El valor literal de 3 tiene ningn tipo explcito en y de s mismo, y por lo tanto un tipo
de salida apropiado deDoble se infiere de la presencia de un literal de coma flotante
como parte de la adicin.
Los literales numricos
Literales enteros se pueden escribir como:
Un decimal nmero, sin el prefijo
Un binario nmero, con un 0b prefijo
Un octal nmero, con un 0o prefijo
A hexadecimal nmero, con un 0x prefijo
Todos estos literales enteros tienen un valor decimal de 17 :

let decimalInteger = 17

let binaryInteger = 0b10001 // 17 in binary notation

let octalInteger = 0o21 // 17 in octal notation

let hexadecimalInteger = 0x11 // 17 in hexadecimal notation


Literales de punto flotante pueden ser decimal (sin prefijo) o hexadecimal (con
un 0x prefijo). Ellos siempre deben tener un nmero (o nmero hexadecimal) en ambos
lados de la coma decimal. Tambin pueden tener un opcional exponente , indicada por
una mayscula o minscula e para carrozas decimales, o una mayscula o
minscula p para carrozas hexadecimales.
Para los nmeros decimales con un exponente de exp , el nmero base se multiplica
por 10 exp :
1.25e2 significa 1.25 10 2 , o 125,0 .
1.25E-2 significa 1,25 10 -2 , o 0,0125 .
Para los nmeros hexadecimales con un exponente de exp , el nmero base se
multiplica por 2 exp :
0xFp2 significa 15 2 2 , o 60.0 .
0xFp-2 significa 15 2 -2 , o 3,75 .
Todos estos literales de punto flotante tienen un valor decimal de 12.1875 :

let decimalDouble = 12.1875

let exponentDouble = 1.21875e1

let hexadecimalDouble = 0xC.3p0



Los literales numricos pueden contener un formato extra para que sean ms fciles de
leer. Ambos nmeros enteros y flotadores pueden ser rellenados con ceros adicionales y
pueden contener guiones bajos para ayudar con la lectura. Ningn tipo de formato afecta
el valor subyacente de la literal:

let paddedDouble = 000123.456


25

let oneMillion = 1_000_000

let justOverOneMillion = 1_000_000.000_000_1


Tipo de conversin numrica
Utilice la Int tipo para todas las constantes de enteros de propsito general y variables
en su cdigo, aunque son conocidos por ser no negativo. Utilizando el tipo de entero por
defecto en situaciones cotidianas significa que constantes enteras y variables son
inmediatamente interoperable en el cdigo y se corresponda con el tipo inferido para
valores enteros literales.
Utilice otros tipos enteros slo cuando son especficamente necesarios para la tarea en
cuestin, debido a los datos de forma explcita tamao de una fuente externa, o para el
funcionamiento, uso de memoria, u otro optimizacin necesaria. El uso de tipos
explcita tamao en estas situaciones ayuda a detectar cualquier desbordamientos de
valor accidentales y documenta implcitamente la naturaleza de los datos que se utiliza.
Entero Conversin
El rango de nmeros que pueden ser almacenadas en una constante entera o variable es
diferente para cada tipo numrico. Un INT8 constante o variable pueden almacenar
nmeros entre -128 y 127 , mientras que unUint8 constante o variable pueden
almacenar nmeros entre 0 y 255 . Un nmero que no caben en una constante o
variable de un tipo entero de tamao se indica como un error cuando se compila el
cdigo:

let cannotBeNegative: UInt8 = -1

// Uint8 no puede almacenar nmeros negativos, por lo que


esta informar de un error

let tooBig: Int8 = Int8.max + 1

// INT8 no puede almacenar un nmero mayor que su valor


mximo,

// Y por lo que este tambin informar de un error


Debido a que cada tipo numrico puede almacenar una serie diferente de valores, debe
optar por la conversin de tipo numrico sobre una base caso por caso. Este enfoque
opt-in evita errores de conversin ocultos y ayuda a que las intenciones de conversin
de tipo explcita en el cdigo.
Para convertir un tipo determinado nmero a otro, se inicializa un nuevo nmero del
tipo deseado con el valor existente. En el siguiente ejemplo, la constante
de twoThousand es de tipo UInt16 , mientras que la constante de uno es de
tipo Uint8 . No se pueden sumar directamente, porque no son del mismo tipo. En
cambio, este ejemplo llama UInt16 (uno) para crear una
nueva UInt16 inicializado con el valor de uno , y utiliza este valor en lugar de la
original:

let twoThousand: UInt16 = 2_000

let one: UInt8 = 1

let twoThousandAndOne = twoThousand + UInt16(one)

26

Debido a que ambos lados de la adicin son ahora de tipo UInt16 , se permite la
adicin. La constante de salida ( twoThousandAndOne ) se infiere a ser de
tipo UInt16 , porque es la suma de dos UINT16 valores.
SomeType (ofInitialValue) es la forma predeterminada para llamar al
inicializador de tipo Swift y pase un valor inicial. Detrs de las escenas, UInt16 tiene
un inicializador que acepta un Uint8 valor, y por lo que este inicializador se utiliza
para hacer un nuevo UInt16 de una existente Uint8 . No se puede pasar
en cualquiertipo aqu, sin embargo, tiene que ser un tipo para el
que UInt16 proporciona un inicializador. La extensin de los tipos existentes para
proporcionar inicializadores que acepten nuevos tipos (incluyendo sus propias
definiciones de tipos) que se cubre en las extensiones .
Entero y en coma flotante Conversin
Las conversiones entre nmeros enteros y de punto flotante tipos numricos deben
hacerse explcitas:

let three = 3

let pointOneFourOneFiveNine = 0.14159

let pi = Double(three) + pointOneFourOneFiveNine

// Pi es igual a 3.14159, y se infiere a ser de tipo doble


Aqu, el valor de la constante de tres se utiliza para crear un nuevo valor de
tipo doble , de modo que ambos lados de la adicin son del mismo tipo. Sin esta
conversin en su lugar, la adicin no se le permitira.
De punto flotante de conversin entera tambin debe hacerse explcito. Un tipo entero
se puede inicializar con un doble o Float valor:

let integerPi = Int(pi)

// IntegerPi es igual a 3, y se infiere a ser de tipo Int


Los valores de coma flotante siempre se truncan cuando se utiliza para inicializar un
nuevo valor de nmero entero de esta manera. Esto significa que 4,75 se convierte
en 4 , y -3,9 convierte -3 .
NOTA
Las reglas para combinar las constantes numricas y variables son diferentes de las
reglas para los literales numricos. El valor literal 3 se puede agregar directamente al
valor literal 0.14159 , porque literales numricos no tienen un tipo explcito en s
mismos. Su tipo es inferido slo en el punto de que son evaluados por el compilador.
Tipo de los nombres
Tipo alias definen un nombre alternativo para un tipo existente. Usted define los alias
de tipo con el typealiaspalabra clave.
Tipo alias son tiles cuando se quiere hacer referencia a un tipo existente por un nombre
que es contextualmente ms apropiado, por ejemplo, cuando se trabaja con datos de un
tamao especfico de una fuente externa:

typealias AudioSample = UInt16


Una vez que se define un alias de tipo, puede utilizar el alias de cualquier lugar que
podra utilizar el nombre original:

var maxAmplitudeFound = AudioSample.min


27

// MaxAmplitudeFound es ahora 0
Aqu, AudioSample se define como un alias para UInt16 . Debido a que es un alias,
la llamada aAudioSample.min llama en realidad UInt16.min , que proporciona
un valor inicial de 0 para el maxAmplitudeFoundvariable.
Booleanos
Swift tiene un bsico de Boole tipo, llamado Bool . Los valores booleanos se les
conoce como lgica , ya que slo alguna vez pueden ser verdaderas o falsas. Swift
proporciona dos valores constantes booleanas,verdaderas y falsas :

let orangesAreOrange = true

let turnipsAreDelicious = false


Los tipos de orangesAreOrange y turnipsAreDelicious se han deducido
como Bool del hecho de que se inicializan con valores literales booleanos. Al igual que
con Int y doble arriba, usted no tiene que declarar constantes o variables
como Bool Si se ajustan a la verdad o falso tan pronto a medida que los crea. La
inferencia de tipos ayuda a que el cdigo Swift ms concisa y fcil de leer cuando se
inicializa las constantes o variables con otros valores cuyo tipo ya se conoce.
Los valores booleanos son particularmente tiles cuando se trabaja con sentencias
condicionales tales como el caso de la declaracin:

if turnipsAreDelicious {

println("Mmm, tasty turnips!")

} else {

println("Eww, turnips are horrible.")

// prints "Eww, turnips are horrible."


Sentencias condicionales tales como el caso de la declaracin se cubren con ms
detalle en el control de flujo.
Seguridad de tipos de Swift evita valores no booleanos de ser sustituido por Bool . El
siguiente ejemplo se informa de un error de tiempo de compilacin:

let i = 1

if i {

// Este ejemplo no se compilar, y se informar de un error

}
Sin embargo, el ejemplo alternativo a continuacin es vlido:

let i = 1

if i == 1 {

// Este ejemplo se compilar con xito

}
El resultado de la i == 1 comparacin es de tipo Bool , y por lo que este segundo
ejemplo del tipo pasa-cheque. Las comparaciones como i == 1 se discuten
en Operadores bsicos .

28

Al igual que con otros ejemplos de tipo de seguridad en Swift, este enfoque evita
errores accidentales y asegura que la intencin de una seccin particular de cdigo es
siempre clara.
Las tuplas
Las tuplas grupo de valores mltiples en un nico valor compuesto. Los valores dentro
de una tupla pueden ser de cualquier tipo y no tienen que ser del mismo tipo que la otra.
En este ejemplo, (404, "Not Found") es una tupla que describe un cdigo de
estado HTTP . Un cdigo de estado HTTP es un valor especial retornado por un
servidor web cada vez que solicita una pgina web. Un cdigo de estado de 404 Not
Found se devuelve si usted solicita una pgina web que no existe.

let http404Error = (404, "Not Found")

// Http404Error es de tipo (int, String), y es igual a


(404, "Not Found")
El (404, "Not Found") grupos de tupla juntos un Int y una cadena para dar el
cdigo de estado HTTP dos valores distintos: un nmero y una descripcin
legible. Puede ser descrito como "una tupla de tipo (int, String) ".
Puede crear tuplas de cualquier permutacin de tipos, y que puede contener muchos
tipos diferentes como desee. No hay nada que nos impida tener una tupla de
tipo (Int, Int, Int) , o (String, Bool) , o de hecho cualquier otra
permutacin usted requiere.
Puede descomponer el contenido de una tupla en constantes o variables independientes,
que luego accede como de costumbre:

let (statusCode, statusMessage) = http404Error

println("The status code is \(statusCode)")

// prints "The status code is 404"

println("The status message is \(statusMessage)")

// prints "The status message is Not Found"


Si slo necesita algunos de los valores de la tupla, ignorar partes de la tupla con un
guin bajo ( _ ) cuando se descompone la tupla:

let (justTheStatusCode, _) = http404Error

println("The status code is \(justTheStatusCode)")

// prints "The status code is 404"


Alternativamente, acceder a los valores de los elementos individuales de una tupla
usando nmeros de ndice a partir de cero:

println("The status code is \(http404Error.0)")

// prints "The status code is 404"

println("The status message is \(http404Error.1)")

// prints "The status message is Not Found"

// Impresiones "El mensaje de estado no se encuentra"


Usted puede nombrar a los elementos individuales de una tupla cuando se define la
tupla:

29

dejar http200Status = ( statuscode : 200 , Descripcin :


"OK" )
Si el nombre de los elementos de una tupla, puede utilizar los nombres de los elementos
para tener acceso a los valores de esos elementos:

println("The status code is \(http200Status.statusCode)")

// prints "The status code is 200"

println("The status message is \(http200Status.description)")

// prints "The status message is OK"


Las tuplas son particularmente tiles como los valores de retorno de las funciones. Una
funcin que intenta recuperar una pgina web puede devolver el (Int,
String) Tipo de tupla para describir el xito o el fracaso de la recuperacin de la
pgina. Al devolver una tupla con dos valores distintos, cada uno de un tipo diferente, la
funcin proporciona informacin ms til sobre su resultado que si slo poda devolver
un solo valor de un solo tipo. Para obtener ms informacin, vea Funciones con
mltiples valores de retorno .
NOTA
Las tuplas son tiles para los grupos temporales de valores relacionados. No son
adecuados para la creacin de estructuras de datos complejas. Si es probable que
persistan ms all de un alcance temporal, lo representan como una clase o estructura,
ms que como una tupla de su estructura de datos. Para obtener ms informacin,
vea Clases y Estructuras .
Opcionales
Utiliza opcionales en situaciones en que un valor puede estar ausente. Un opcional dice:
No es un valor, y es igual a x
o
All no es un valor en absoluto
NOTA
El concepto de opcionales no existe en C o Objective-C. Lo ms cercano en ObjectiveC es la capacidad de volver a cero de un mtodo que de otra manera devolver un
objeto, con nula que significa "la ausencia de un objeto vlido." Sin embargo, esto
slo funciona para los objetos-no funciona para las estructuras , tipos bsicos de C, o
valores de enumeracin. Para estos tipos, mtodos de Objective-C normalmente
devuelven un valor especial (como NSNotFound ) para indicar la ausencia de un
valor. Este enfoque asume que la persona que llama del mtodo sabe que hay un valor
especial para probar en contra y recuerda a comprobar por ello. Opcionales de Swift
permiten indicar la ausencia de un valor de cualquier tipo en absoluto , sin la necesidad
de constantes especiales.
He aqu un ejemplo de cmo opcionales pueden utilizarse para hacer frente a la ausencia
de un valor. De Swift Cadena tipo tiene un mtodo llamado Toint , que trata de
convertir una Cadena de valor en un Int valor.Sin embargo, no todos los cadena se
puede convertir en un entero. La cadena "123" se puede convertir en el valor
numrico 123 , pero la cadena "hola, mundo" no tiene un valor numrico obvio
para convertir.
El ejemplo siguiente utiliza la Toint mtodo para tratar de convertir una cuerda en
un Int :

30

let possibleNumber = "123"

let convertedNumber = possibleNumber.toInt()

// ConvertedNumber se infiere a ser de tipo "Int?", O "Int


opcional"
Debido a que el Toint mtodo puede fallar, devuelve un opcional Int , en lugar de
un int . Un opcional Int se escribe como Int? , no Int . El signo de interrogacin
indica que el valor que contiene es opcional, lo que significa que puede
contener algn Int valor, o podra contener ningn valor en absoluto . (No puede
contener cualquier otra cosa, como por ejemplo un Bool valor o una Cadena de valor.
Es o un int , o no es nada en absoluto.)
nil
Se establece una variable opcional a un estado sin valor asignndole el valor
especial nulo :

var serverResponseCode: Int? = 404

// ServerResponseCode contiene un valor real Int de 404

serverResponseCode = nil

// ServerResponseCode ahora no contiene ningn valor


NOTA
nil no se puede utilizar con constantes y variables no opcional. Si una constante o
variable en el cdigo tiene que trabajar con la ausencia de un valor bajo ciertas
condiciones, siempre declararemos como un valor opcional del tipo apropiado.
Si se define una constante o variable opcional sin proporcionar un valor por defecto, la
constante o variable se ajusta automticamente a cero para usted:

var surveyAnswer : Cadena ?

// SurveyAnswer se ajusta automticamente a cero


NOTA
De Swift nil no es lo mismo que cero en Objective-C. En Objective-C, nil es un
puntero a un objeto inexistente. En Swift, nil no es un puntero-es la ausencia de un
valor de un cierto tipo. Opcionales decualquier tipo se pueden establecer en cero , no
slo tipos de objetos.
Si Las declaraciones y forzado Unwrapping
Puede utilizar un si declaracin para averiguar si un opcional contiene un valor
comparando el opcional contra cero . Se realiza esta comparacin con la "igual a"
operador ( == ) o el "no es igual a" operador ( ! = ).
Si una opcin tiene un valor, se considera que "no es igual a" cero :

if convertedNumber != nil {

println("convertedNumber contains some integer value.")

// prints "convertedNumber contains some integer value."


Una vez que est seguro de que la opcional hace contener un valor, puede acceder a su
valor subyacente mediante la adicin de un signo de exclamacin ( ! ) al final del
nombre de la opcin. El signo de exclamacin efectivamente dice, "Yo s que esta

31

opcin sin duda tiene un valor; por favor use "Esto se conoce como.desenvolver
forzado del valor de la opcin:

if convertedNumber != nil {

println("convertedNumber has an integer value of \(convertedNumber!).")

// Impresiones "convertedNumber tiene un valor entero de


123"
Para ms informacin sobre el caso de la declaracin, vase el control de flujo .
NOTA
Tratar de utilizar ! acceder a un valor opcional inexistente provoca un error de
ejecucin. Asegrese siempre de que un opcional contiene una no- nil valor antes de
usar ! forzar-desenvolver su valor.
Opcional Binding
Utiliza unin opcional para averiguar si un opcional contiene un valor, y si es as, haga
que el valor disponible como una constante o variable temporal. Opcional unin se
puede utilizar con si y mientras declaraciones para comprobar un valor dentro de
un opcional, y para extraer ese valor en una constante o variable, como parte de una sola
accin. si y mientras estados se describen con ms detalle en el control de flujo .
Escribe enlaces opcionales para el caso de la declaracin de la siguiente manera:
if let constantName = someOptional {

statements

}
Puede volver a escribir la possibleNumber ejemplo del Opcionales seccin para
utilizar opcional desenvolver vinculante y no forzada:

if let actualNumber = possibleNumber.toInt() {

println("\(possibleNumber) has an integer value of \(actualNumber)")

} else {

println("\(possibleNumber) could not be converted to an integer")

// prints "123 has an integer value of 123"


Este cdigo se puede leer como:
"Si el opcional Int devuelve possibleNumber.toInt contiene un valor, establece
una nueva constante llamadaactualNumber al valor contenido en la opcional. "
Si la conversin se realiza correctamente, el actualNumber constante est disponible
para su uso dentro de la primera rama del si comunicado. Ya se ha inicializado con el
valor contenido dentro de la opcional, y as que no hay necesidad de utilizar el ! sufijo
para acceder a su valor. En este ejemplo, actualNumber se utiliza simplemente para
imprimir el resultado de la conversin.
Puede utilizar ambas constantes y variables con opcin de encuadernacin. Si quera
manipular el valor deactualNumber dentro de la primera rama del si declaracin,

32

usted podra escribir si actualNumber var su lugar, y el valor contenido en el


opcional se pondran a disposicin como una variable en lugar de una constante.
Implcitamente Unwrapped Opcionales
Como se describi anteriormente, opcionales indican que se permite una variable
constante o tener "ningn valor". Opcionales pueden ser comprobadas con un caso
de declaracin para ver si existe un valor, y puede ser condicionalmente desenvolvi
con opcional de unin para acceder a el valor de la opcin, si es que existe.
A veces se desprende de la estructura de un programa que una opcin ser siempre tener
un valor, despus de que el valor se establece en primer lugar. En estos casos, es til
para eliminar la necesidad de comprobar y desenvolver el valor de la opcional cada vez
que se accede, porque se puede suponer con seguridad a tener un valor todo el tiempo.
Este tipo de opcionales se definen como opcionales implcitamente abierto . Usted
escribe un implcitamente envolver opcional colocando un signo de exclamacin
( cuerda! ) en lugar de un signo de interrogacin (Cadena? ) despus de que el tipo
que desea que sea opcional.
Implcitamente opcionales abierto son tiles cuando el valor de un opcional se confirma
que existe inmediatamente despus de la opcional se define primero y definitivamente
se puede suponer que existe en cada punto a partir de entonces. El uso principal de
opcionales implcitamente abierto en Swift es durante la inicializacin de clase, como se
describe en las referencias sin propietario e implcitamente Unwrapped propiedades
opcionales .
Un opcional implcitamente envolver es una opcin normal de detrs de las escenas,
pero tambin se puede utilizar como un valor no opcional, sin la necesidad de
desenvolver el valor opcional cada vez que se accede.El siguiente ejemplo muestra la
diferencia de comportamiento entre una cadena opcional y una cadena opcional
implcitamente desenvuelto al acceder a su valor envuelto como un explcito Cadena :

let possibleString: String? = "An optional string."

let forcedString: String = possibleString! // requires an exclamation mark

let assumedString: String! = "An implicitly unwrapped optional string."

let implicitString: String = assumedString // no need for an exclamation mark


Usted puede pensar en una forma implcita envolver opcional como dar permiso para
que el facultativo de desenvolverse de forma automtica cada vez que se utiliza. En
lugar de colocar un signo de exclamacin despus del nombre de la opcin cada vez que
lo use, se coloca un signo de exclamacin despus de tipo de la opcin al declararla.
NOTA
Si intenta acceder a una implcita envolver opcional cuando no contiene un valor, se
activar un error de ejecucin. El resultado es exactamente el mismo que si se coloca un
signo de exclamacin despus de un opcional normal que no contenga un valor.
Todava se puede tratar una opcional implcitamente sin envolver como un opcional
normal, para comprobar si contiene un valor:

if assumedString != nil {

println(assumedString)

}
33

// imprime "una cadena opcional implcitamente sin


envolver."
Tambin puede utilizar una forma implcita envolver opcional con opcional de unin,
para comprobar y desenvolver su valor en una sola sentencia:

if let definiteString = assumedString {

println(definiteString)

// imprime "una cadena opcional implcitamente sin


envolver."
NOTA
No utilice un implcitamente sin envolver opcional cuando hay una posibilidad de
convertirse en una variablenula en un punto posterior. Utilice siempre un tipo opcional
normal si usted necesita para comprobar si hay un nulo valor durante la vida de una
variable.
Aseveraciones
Opcionales te permite comprobar los valores que pueden o no existir, y para escribir
cdigo que hace frente con gracia con la ausencia de un valor. En algunos casos, sin
embargo, simplemente no es posible que el cdigo para continuar la ejecucin si el
valor no existe, o si un valor proporcionado no cumple ciertas condiciones. En estas
situaciones, se puede desencadenar una afirmacin en su cdigo para poner fin a la
ejecucin de cdigo y proporcionar una oportunidad para depurar la causa del valor
ausente o no vlido.
Depuracin con afirmaciones
Una afirmacin es un cheque en tiempo de ejecucin que una condicin lgica
definitivamente se evala como verdadera . Literalmente palabras, una afirmacin
"afirma" que una condicin es verdadera. Utiliza una afirmacin para asegurarse de que
una condicin esencial se satisface antes de ejecutar cualquier cdigo adicional. Si la
condicin se evala como verdadera , la ejecucin de cdigo contina como de
costumbre; si la condicin se evala como falsa , la ejecucin de cdigo termina, y su
aplicacin se termina.
Si su cdigo desencadena una afirmacin mientras se ejecuta en un entorno de
depuracin, tales como cuando se construye y ejecuta una aplicacin en Xcode, se
puede ver exactamente dnde se produjo el estado no vlido y consultar el estado de su
aplicacin en el momento en que la afirmacin fue provocado.Una afirmacin tambin
le permite proporcionar un mensaje de depuracin adecuado en cuanto a la naturaleza
de la asercin.
Usted escribe una afirmacin llamando al mundial afirman funcin. Se pasa
la asercin funcin de una expresin que se evala como verdadera o falsa y
un mensaje que se debe mostrar si el resultado de la condicin es falsa :

let age = -3

assert(age >= 0, "A person's age cannot be less than zero")

// Esto hace que la afirmacin para disparar, porque la


edad no es> = 0

34

En este ejemplo, la ejecucin de cdigo continuar slo si la edad> = 0 se evala


como verdadera , es decir, si el valor de la edad es no negativo. Si el valor de la
edad es negativo, como en el cdigo anterior, a continuacin, la edad> = 0 se
evala como falsa , y la afirmacin se activa, de terminar la aplicacin.
El mensaje afirmacin puede omitirse si se desea, como en el siguiente ejemplo:
afirmar ( edad > = 0 )
Cundo utilizar aserciones
Utilice una afirmacin cada vez que un estado tiene el potencial de ser falsa, pero
debe sin duda ser verdad para que su cdigo para continuar la ejecucin. Escenarios
adecuados para una comprobacin de asercin incluyen:
Un ndice subndice entero se pasa a una aplicacin subndice de encargo, pero el
valor del ndice subndice podra ser demasiado baja o demasiado alta.
Un valor se pasa a una funcin, pero un valor no vlido significa que la funcin no
puede cumplir su tarea.
Un valor opcional es actualmente nula , sino un no- nil de valor es esencial para
el cdigo subsiguiente para ejecutar con xito.
Ver tambin subndices y Funciones .
NOTA
Las afirmaciones hacen que su aplicacin para terminar y no son un sustituto para el
diseo de su cdigo de tal manera que las condiciones no vlidas es improbable que
surjan. No obstante, en situaciones donde las condiciones no vlidas son posibles, una
afirmacin es una forma eficaz de garantizar que dichas condiciones se resaltan y se
dieron cuenta durante el desarrollo, antes de la publicacin de su aplicacin.
A Swift tour
Operadores bsicos

35

Operadores bsicos
En esta pgina
Un operador es un smbolo especial o una frase que se utiliza para comprobar, cambiar
o combinar los valores. Por ejemplo, el operador de suma ( + ) suma dos nmeros juntos
(como en let i = 1 + 2 ). Ejemplos ms complejos incluyen el operador lgico
AND && (como en el caso de enteredDoorCode && passedRetinaScan)
y el operador de incremento ++ i , que es un acceso directo para aumentar el valor
de i por 1 .
Swift es compatible con los operadores de C ms estndar y mejora varias funciones
para eliminar los errores comunes de codificacin. El operador de asignacin ( = ) no
devuelve un valor, para evitar que sea utilizado por error cuando el operador igual a
( == ) se destina. Los operadores aritmticos ( + , - , * , / , % , etc) y no permiten
detectar desbordamiento valor, para evitar resultados inesperados cuando se trabaja con
los nmeros que se convierten en mayor o menor que el rango de valores permitido del
tipo que los almacena.Usted puede optar por el comportamiento de desbordamiento de
valor mediante el uso de operadores de desbordamiento de Swift, como se describe
en Operadores de desbordamiento .
A diferencia de C, Swift le permite realizar resto ( % ) clculos sobre nmeros de punto
flotante. Swift tambin proporciona dos operadores de rango ( un .. <b y a ...
b ) que no se encuentran en C, como un acceso directo para expresar un rango de
valores.
En este captulo se describen los operadores comunes en Swift. Operadores
avanzados cubre operadores avanzados de Swift, y describe cmo definir sus propios
operadores personalizados e implementar los operadores estndar para sus propios tipos
personalizados.
Terminologa
Los operadores son unarios, binarios o ternarios:
Unarios operadores operan en un solo objetivo (tales como :
una ). Unarios prefijo operadores aparecen inmediatamente antes de su destino
(como ! b ), y unarios postfix operadores aparecen inmediatamente despus de su
objetivo (tales como i ++ ).
Binarias operadores funcionan con dos objetivos (como 2 + 3 ) y
son infijo porque aparecen en entre sus dos objetivos.
Ternarios operadores operan en tres objetivos. Al igual que C, Swift tiene un solo
operador ternario, el operador condicional ternario ( a b: c ).
Los valores que afectan a los operadores estn operando . En la expresin 1 + 2 ,
la + smbolo es un operador binario y sus dos operandos son los valores 1 y 2 .
Operador de asignacin
El operador de asignacin ( a = b ) inicializa o actualiza el valor de una con el valor
de b :

let b = 10

var a = 5

a=b

// a is now equal to 10

36

Si el lado derecho de la asignacin es una tupla con mltiples valores, sus elementos se
pueden descomponer en varias constantes o variables a la vez:

let (x, y) = (1, 2)

// x is equal to 1, and y is equal to 2


A diferencia del operador de asignacin en C y Objective-C, el operador de asignacin
en Swift s mismo no devuelve ningn valor. La siguiente declaracin no es vlida:

if x = y {

// Esto no es vlido, ya que x = y no devuelve un valor

}
Esta funcin evita que el operador de asignacin ( = ) se utilice por accidente cuando el
operador igual a ( == ) se destina en realidad. Al hacer si x = y no vlida, Swift le
ayuda a evitar este tipo de errores en el cdigo.
Operadores aritmticos
Swift es compatible con los cuatro estndares operadores aritmticos para todos los
tipos de nmeros:
Suma ( + )
Resta ( - )
Multiplicacin ( * )
Divisin ( / )

1 + 2 // equals 3

5 - 3 // equals 2

2 * 3 // equals 6

10.0 / 2.5 // equals 4.0


A diferencia de los operadores aritmticos en C y Objective-C, los operadores
aritmticos Swift no permiten valores se desborden por defecto. Usted puede optar por
el comportamiento de desbordamiento de valor mediante el uso de operadores de
desbordamiento de Swift (como a & + b ). Ver Operadores de desbordamiento .
El operador de suma tambin es apoyado por Cadena concatenacin:

"hello, " + "world" // equals "hello, world"


Dos caracteres valores, o uno de caracteres de valor y uno de cadena de
valor, se pueden sumar para hacer una nueva Cadena de valor:

let dog: Character = " "

let cow: Character = " "

let dogCow = dog + cow

// dogCow is equal to "


"
Ver tambin concatenar cadenas y caracteres .
Operador resto
El operador de resto ( a% b ) resuelve cuntos mltiplos de b cabrn dentro de una y
devuelve el valor que queda (conocido como el resto ).
NOTA

37

El operador resto ( % ) tambin se conoce como un operador de mdulo en otros


idiomas. Sin embargo, su comportamiento en Swift para los nmeros negativos significa
que es, estrictamente hablando, un resto ms que una operacin de mdulo.
He aqu cmo funciona el operador resto. Para calcular el 9% 4 , primero calcular
cuntos 4 s se ajuste dentro de 9 :


Puede encajar dos 4 s interior 9 , y el resto es 1 (se muestra en color naranja).
En Swift, esto se escribe como:

9 % 4 // equals 1
Para determinar la respuesta para a% b , el % del operador calcula la siguiente ecuacin y
devuelve restocomo salida:

un = ( b algunos multiplicador ) + resto


donde algunos multiplicador es el mayor nmero de mltiplos de b que caben
dentro de una .
Insercin de 9 y 4 en esta ecuacin se obtiene:
9=(42)+1
El mismo mtodo se aplica al calcular el resto para un valor negativo de una :
- 9 % 4 // es igual a -1
Insercin de -9 y 4 en los rendimientos ecuacin:
-9 = ( 4 -2 ) + -1
dando un valor resto de -1 .
El signo de b es ignorado por los valores negativos de b . Esto significa que a% b y un
-b% siempre dan la misma respuesta.
Clculos Resto en coma flotante
A diferencia del operador resto en C y Objective-C, el operador resto de Swift tambin
puede funcionar con nmeros de punto flotante:
8 % 2,5 // es igual a 0,5
En este ejemplo, 8 dividido por 2,5 es igual a 3 , con un resto de 0,5 , por lo que el
operador devuelve un restoDoble valor de 0,5 .


Los operadores de incremento y decremento
Al igual que C, Swift ofrece un operador de incremento ( ++ ) y un operador de
decremento ( - ) como un acceso directo para aumentar o disminuir el valor de una
variable numrica por 1 . Puede utilizar estos operadores con variables de cualquier
nmero entero o tipo de punto flotante.

38

var i = 0

++i // i now equals 1


Cada vez que se llama ++ i , el valor de i se incrementa en 1 . Esencialmente, ++
i es un atajo para decir i = i + 1 Del mismo modo,. --i se puede utilizar como
forma abreviada de i = i - 1 .
El ++ y - smbolos pueden ser utilizados como operadores de prefijo o como
operadores de sufijo. ++ i y i ++son dos formas vlidas para aumentar el valor
de i por 1 . Del mismo modo, --i y i-- son dos formas vlidas para disminuir el
valor de i por 1 .
Tenga en cuenta que estos operadores modifican i y tambin devuelven un valor. Si
slo desea aumentar o disminuir el valor almacenado en i , puede ignorar el valor
devuelto. Sin embargo, si usted no utiliza el valor devuelto, que ser diferente en
funcin de si ha utilizado la versin prefijo o de sufijo del operador, de acuerdo con las
siguientes reglas:
Si el operador est escrito antes de la variable, se incrementa la variable antes
de devolver su valor.
Si el operador est escrito despus de la variable, se incrementa la variable despus
de regresar de su valor.
Por ejemplo:

var a = 0

let b = ++a

// a and b are now both equal to 1

let c = a++

// A es igual a 2, pero c se ha establecido en el valor


pre-incremento de 1
En el ejemplo anterior, sea b = ++ un incrementos de un antes de devolver su
valor. Esta es la razn por tantouna y b son iguales a al nuevo valor de 1 .
Sin embargo, dej c = a ++ incrementa un despus de regresar de su valor. Esto
significa que c recupera el antiguo valor de 1 , y un entonces se actualiza para
igualar 2 .
A menos que necesite el comportamiento especfico de i ++ , se recomienda que usted
utilice ++ i y --i en todos los casos, debido a que tienen el comportamiento esperado
tpica de modificar i y devolviendo el resultado.
Operador menos unario
El signo de un valor numrico se puede activar mediante un prefijo - , conocido como
el operador menos unario :

let three = 3

let minusThree = -three // minusThree equals -3

let plusThree = -minusThree // plusThree equals 3, or "minus minus three"


El operador unario menos ( - ) se antepone directamente ante el valor que opera en, sin
ningn espacio en blanco.

39

Operador unario Plus


El operador unario ms ( + ) simplemente devuelve el valor que opera en, sin ningn
cambio:

let minusSix = -6

let alsoMinusSix = +minusSix // alsoMinusSix equals -6


Aunque el operador de suma unaria no hace nada, se puede utilizar para proporcionar
simetra en su cdigo para nmeros positivos cuando tambin mediante el operador
unario menos para los nmeros negativos.
Operadores de Asignacin Compuesto
Al igual que C, Swift proporciona operadores de asignacin compuestos que combinan
de asignacin ( = ) con otra operacin. Un ejemplo es el operador de asignacin de
suma ( + = ):

var a = 1

a += 2

// a es ahora igual a 3
La expresin a + = 2 es la abreviatura de a = a + 2 . Efectivamente, la adicin y
la asignacin se combinan en un operador que realiza ambas tareas al mismo tiempo.
NOTA
Los operadores de asignacin compuestos no devuelven un valor. No se puede
escribir al B = a + = 2 , por ejemplo. Este comportamiento es diferente de los
operadores de incremento y decremento mencionados anteriormente.
Una lista completa de operadores de asignacin compuestos se puede encontrar en las
expresiones .
Operadores de comparacin
Swift es compatible con todos los C estndar operadores de comparacin :
Igual a ( a == b )
No es igual a ( a! = b )
Mayor que ( a> b )
Menos de ( a <b )
Mayor o igual a ( a> = b )
Menor o igual a ( a <= b )
NOTA
Swift tambin proporciona dos operadores de identidad ( === y ! == ), que se utiliza
para probar si dos referencias a objetos tanto se refieren a la misma instancia de
objeto. Para obtener ms informacin, veaClases y Estructuras .
Cada uno de los operadores de comparacin devuelve un Bool valor para indicar si la
declaracin es verdadera:

1 == 1 // cierto, porque 1 es igual a 1

2 ! = 1 // cierto, porque 2 no es igual a 1

2 > 1 // cierto, porque 2 es mayor que 1

1 < 2 // cierto, porque 1 es menor que 2

1 > = 1 // cierto, porque 1 es mayor que o igual a 1

2 <= 1 // falsa, porque 2 no es menor que o igual a 1


40

Los operadores de comparacin se utilizan a menudo en las sentencias condicionales,


como el caso de la declaracin if:

let name = "world"

if name == "world" {

println("hello, world")

} else {

println("I'm sorry \(name), but I don't recognize you")

// imprime "hola, mundo", porque el nombre es de hecho


igual al "mundo"
Para ms informacin sobre el caso de la declaracin, vase el control de flujo .
Operador condicional ternario
El operador condicional ternario es un operador especial con tres partes, que toma la
forma pregunta?answer1: Respuesta2 . Es un acceso directo para la
evaluacin de una de las dos expresiones en funcin de sipregunta es verdadera o
falsa. Si pregunta es verdadera, evala answer1 y devuelve su valor; de lo
contrario, se evala Respuesta2 y devuelve su valor.
El operador condicional ternario es una abreviacin para el cdigo de abajo:

if question {

answer1

} else {

answer2

}
He aqu un ejemplo, que calcula la altura de una fila de tabla. La altura de la fila debe
ser de 50 puntos ms alto que la altura del contenido si la fila tiene una cabecera, y 20
puntos ms alto si la fila no tiene un encabezado:
dejar que contentHeight = 40

dejar HasHeader = true

dejar rowHeight = contentHeight + ( HasHeader ? 50 : 20 )

// RowHeight es igual a 90
El ejemplo anterior es una abreviatura para el cdigo de abajo:

let contentHeight = 40

let hasHeader = true

var rowHeight = contentHeight

if hasHeader {

rowHeight = rowHeight + 50

} else {

rowHeight = rowHeight + 20

}
41

// RowHeight es igual a 90
El primer uso del ejemplo del operador condicional ternario significa
que rowHeight se puede establecer en el valor correcto en una sola lnea de
cdigo. Esto es ms conciso que el segundo ejemplo, y elimina la necesidad
de rowHeight a una variable, porque su valor no necesita ser modificado dentro de
un sideclaracin.
El operador condicional ternario proporciona una taquigrafa eficiente para decidir cul
de las dos expresiones a considerar. Utilice el operador condicional ternario con
cuidado, sin embargo. Su concisin puede conducir al cdigo difcil de leer si se
abusa. Evite combinar varias instancias del operador condicional ternario en una
sentencia compuesta.
Ninguna Coalescente Operador
El operador de coalescencia nula ( a ?? b ) desenvuelve opcional un si contiene un
valor, o devuelve un valor predeterminado b si una es nula . La
expresin una siempre es de un tipo opcional. La expresin b debe coincidir con el tipo
que se almacena dentro de una .
El operador de coalescencia nil es un atajo para el cdigo de abajo:

a != nil ? a! : b
El cdigo anterior utiliza el operador condicional ternario y desenvolver forzada
( una! ) para acceder al valor envuelto en una cuando una no es nula , ya
regresar b lo contrario. El operador de coalescencia nil ofrece una forma ms elegante
para encapsular esta comprobacin condicional y desenvolver de una forma concisa y
fcil de leer.
NOTA
Si el valor de una es no nulo , el valor de b no se evala. Esto se conoce
como evaluacin de corto-circuito .
El ejemplo siguiente utiliza el operador de coalescencia nil que elegir entre un nombre
de color por defecto y un nombre de color definido por el usuario opcional:

let defaultColorName = "red"

var userDefinedColorName: String? // defaults to nil

var colorNameToUse = userDefinedColorName ?? defaultColorName

// UserDefinedColorName es nula, por lo colorNameToUse se


establece en el valor predeterminado de "rojo"
El userDefinedColorName variable se define como un opcional de cuerda ,
con un valor por defecto de cero .Debido userDefinedColorName es de tipo
opcional, puede utilizar el operador de coalescencia nil considerar su valor. En el
ejemplo anterior, el operador se utiliza para determinar un valor inicial para
una cadena variable
llamada colorNameToUse . Debido userDefinedColorName es nula , la
expresin userDefinedColorName ??defaultColorName devuelve el valor
de defaultColorName , o "rojo" .

42

Si asigna un no- nil valor a userDefinedColorName y ejecutar la revisin


operador coalescente nula de nuevo, el valor envuelto
dentro userDefinedColorName se utiliza en lugar del predeterminado:

userDefinedColorName = "green"

colorNameToUse = userDefinedColorName ?? defaultColorName

// UserDefinedColorName no es nula, por lo colorNameToUse


se establece en "verde"

43


Operadores Range
Swift incluye dos operadores de rango , que son atajos para expresar un rango de
valores.
Cerrado operador Range
El operador de rango cerrado ( un ... b ) define un rango que va desde una a b , e
incluye los valores de una yb . El valor de un no debe ser mayor que b .
El operador de rango cerrado es til cuando se repite en un intervalo en el que desea que
todos los valores a utilizar, por ejemplo, con un para - en bucle:

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
Para ms informacin sobre por - en bucles, consulte Flujo de control .
La mitad-Open Operator Range
El operador entreabierta gama ( un .. <b ) define un rango que va desde una a b ,
pero no incluye b . Se dice que es la mitad-abierta , ya que contiene el primer valor,
pero no su valor final. Como con el operador de rango cerrado, el valor de un no debe
ser mayor que b .
Rangos medio abiertas son particularmente tiles cuando se trabaja con listas de cerobasado como matrices, en las que es til para contar hasta (pero sin incluir) la longitud
de la lista:

let names = ["Anna", "Alex", "Brian", "Jack"]

let count = names.count

for i in 0..<count {

println("Person \(i + 1) is called \(names[i])")

// Persona 1 se llama Anna

// Persona 2 se llama Alex

// Persona 3 se llama Brian

// Persona 4 se llama Jack


Tenga en cuenta que la matriz contiene cuatro artculos, pero 0 ..
<cuenta solamente las cuentas en cuanto a3 (el ndice del ltimo elemento de la
matriz), porque es un rango medio abierta. Para ms informacin sobre matrices,
vea Matrices .

44

Operadores lgicos
Los operadores lgicos modificar o combinar los valores lgicos
booleanos true y false . Swift es compatible con los tres operadores lgicos
estndar que se encuentran en los idiomas basados en C:
Logical NOT (!a)
Logical AND (a && b)
Logical OR (a || b)
Logical NOT Operator
El operador lgico NOT ( ! a) invierte un valor booleano para que verdadera se
convierte en falsa , y falsase convierte en verdadera .
El operador lgico NOT es un operador prefijo, y aparece inmediatamente antes del
valor que opera en, sin ningn espacio en blanco. Se puede leer como "no una ", como
se ve en el siguiente ejemplo:

let allowedEntry = false

if !allowedEntry {

println("ACCESS DENIED")

// prints "ACCESS DENIED"


La frase ! si allowedEntry se puede leer como "si no se permite la entrada." La
lnea posterior slo se ejecuta si "no entrada permitida" es cierto; es decir,
si allowedEntry es falsa .
Como en este ejemplo, la eleccin cuidadosa de nombres de constantes y variables
booleanas puede ayudar a mantener el cdigo legible y conciso, evitando dobles
negaciones o afirmaciones lgicas confusas.
Y lgico Operador
El operador lgico Y ( a && b ) crea expresiones lgicas donde ambos valores deben
ser verdad para la expresin general que tambin sea cierto .
Si alguno de los valores es falso , la expresin general tambin ser falsa . De
hecho, si el primer valor esfalso , el segundo valor de ni siquiera ser evaluada, ya que
no puede hacer la expresin global equivale a laverdad . Esto se conoce
como evaluacin de corto-circuito .
En este ejemplo se considera dos Bool valores y slo permite el acceso si ambos
valores son true :

let enteredDoorCode = true

let passedRetinaScan = false

if enteredDoorCode && passedRetinaScan {

println("Welcome!")

} else {

println("ACCESS DENIED")

45

// prints "ACCESS DENIED"

Operador lgico OR
El operador lgico OR ( a || b ) es un operador infijo hecho a partir de dos
personajes de tuberas adyacentes. Se utiliza para crear expresiones lgicas en las que
slo uno de los dos valores tiene que serverdadera para la expresin general para
ser verdad .
Al igual que el operador lgico AND anterior, el operador lgico OR utiliza la
evaluacin de cortocircuito para considerar sus expresiones. Si el lado izquierdo de una
expresin lgica OR es verdadera , no se evala el lado derecho, porque no puede
cambiar el resultado de la expresin general.
En el siguiente ejemplo, la primera Bool valor ( hasDoorKey ) es falsa , pero el
segundo valor (knowsOverridePassword ) es verdadera . Debido a que un
valor es verdadero , la expresin general tambin se evala como verdadera , y
se permite el acceso:

let hasDoorKey = false

let knowsOverridePassword = true

if hasDoorKey || knowsOverridePassword {

println("Welcome!")

} else {

println("ACCESS DENIED")

// prints "Welcome!"
La combinacin de operadores lgicos
Puede combinar mltiples operadores lgicos para crear expresiones compuestas ms
largos:

if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword {

println("Welcome!")

} else {

println("ACCESS DENIED")

// prints "Welcome!"
Este ejemplo utiliza mltiples && y || operadores para crear una expresin compuesta
por ms tiempo. Sin embargo, el && y || operadores siguen funcionando en slo dos
valores, por lo que este es en realidad tres expresiones ms pequeas encadenadas. El
ejemplo se puede leer como:
Si hemos entrado en el cdigo de la puerta correcta y pasamos el escner de la retina, o
si tenemos una llave de la puerta vlida, o si se conoce la contrasea de anulacin de
emergencia y permitir el acceso.
Basado en los valores de enteredDoorCode , passedRetinaScan ,
y hasDoorKey , los primeros dos mini-expresiones son falsas . Sin embargo, la

46

contrasea de anulacin de emergencia es conocido, por lo que la expresin compuesta


en general todava se evala como verdadera .
Los parntesis explcitos
A veces es til incluir parntesis, cuando no son estrictamente necesarios, para que la
intencin de una expresin compleja ms fcil de leer. En el ejemplo de puerta de
acceso anteriormente, es til aadir parntesis alrededor de la primera parte de la
expresin compuesto para hacer su intencin explcita:

if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword


{

println("Welcome!")

} else {

println("ACCESS DENIED")

// prints "Welcome!"
Los parntesis, dejan claro que los dos primeros valores son considerados como parte de
un posible estado independiente en la lgica global. La salida de la expresin
compuesto no cambia, pero la intencin general es ms claro para el lector. La
legibilidad es siempre preferible a la brevedad; utilizar parntesis, donde ayudan a hacer
que sus intenciones claras.

Cuerdas y Personajes
Una cadena es una coleccin ordenada de caracteres, como "hola,
mundo" o "albatros" . Cuerdas Swift estn representados por la Cadena tipo, que
a su vez representa una coleccin de valores de caracteres de tipo.
De Swift de Cuerda y Carcter tipos proporcionan una manera rpida, compatible
con Unicode para trabajar con el texto en el cdigo. La sintaxis para la creacin de la
cadena y la manipulacin es ligero y fcil de leer, con una sintaxis literal de cadena que
es similar a C. concatenacin de cadenas es tan simple como la suma de dos cuerdas con
el + operador, y la mutabilidad cadena se gestiona mediante la eleccin entre una
constante o una variables, al igual que cualquier otro valor en Swift.
A pesar de esta simplicidad de la sintaxis, de Swift Cadena tipo es una aplicacin de
cadena rpida, moderna.Cada cadena se compone de caracteres Unicode
independientemente de la codificacin, y ofrece soporte para acceder a esos personajes
en diversas representaciones Unicode.
Tambin puede utilizar cadenas para insertar constantes, variables, literales y
expresiones en cadenas ms largas, en un proceso conocido como interpolacin de
cadenas. Esto hace que sea fcil crear valores de cadena personalizada para la
visualizacin, el almacenamiento y la impresin.
NOTA
De Swift Cadena tipo se tiende un puente a la perfeccin para la
Fundacin NSString clase. Si est trabajando con el marco de la Fundacin en Cocoa
o Cocoa Touch, todo el NSString API est disponible para llamar en

47

cualquier Cadena de valor se crea, adems de los de Cuerda funciones descritas en


este captulo. Tambin puede utilizar una Cadena de valor con cualquier API que
requiere una NSString instancia.
Para obtener ms informacin sobre el uso de cuerdas con la Fundacin y Cocoa,
consulte Uso de Swift con Cocoa y Objective-C .
Literales de cadena
Puede incluir predefinidos de Cuerda valores dentro de su cdigo como literales de
cadena . Un literal de cadena es una secuencia fija de caracteres de texto rodeado por un
par de comillas dobles ( "" ).
Utilice una cadena literal como valor inicial para una variable constante o:

let someString = "Some string literal value"


Tenga en cuenta que Swift infiere un tipo de cuerda para el someString constante,
ya que se inicializa con un valor literal de cadena.
NOTA
Para obtener informacin sobre el uso de caracteres especiales en los literales de cadena,
vea caracteres Unicode especial en literales de cadena .
Iniciando una cadena vaca
Para crear un vaco de cadena de valor como punto de partida para la construccin
de una cadena ms larga, ya sea asignar una cadena vaca literal a una variable, o
inicializar una nueva cadena con la sintaxis de inicializador ejemplo:

var emptyString = "" // empty string literal

var anotherEmptyString = String() // initializer syntax

// Estas dos cadenas estn vacos, y son equivalentes entre


s
Averige si una cuerda valor est vaco comprobando su
Boolean estaVacia propiedad:

if emptyString.isEmpty {

println("Nothing to see here")

// prints "Nothing to see here"


La mutabilidad de Cuerdas
Se indica si una determinada cadena se puede modificar (o mutado ) mediante la
asignacin a una variable (en cuyo caso puede ser modificado), o a una constante (en
cuyo caso no se puede modificar):

var variableString = "Horse"

variableString += " and carriage"

// variableString is now "Horse and carriage"

let constantString = "Highlander"

constantString += " and another Highlander"


48

// this reports a compile-time error - a constant string cannot be modified


NOTA
Este enfoque es diferente de mutacin cadena en Objective-C y Cocoa, donde se elige
entre dos clases (NSString y NSMutableString ) para indicar si una cadena se
puede mutar.
Las cadenas son tipos de valor
De Swift Cadena tipo es un tipo de valor . Si crea una nueva Cadena de valor,
que de cuerdas valor se copiancuando se pasa a una funcin o mtodo, o cuando se
asigna a una constante o variable. En cada caso, una nueva copia de la existente de
cuerdas se crea valor, y se pasa o le asigna la nueva copia, no la versin original. Los
tipos de valor estn descritas en estructuras y enumeraciones son tipos de valor .
NOTA
Este comportamiento difiere del de NSString en Cocoa. Cuando se crea
una NSString ejemplo, en Cocoa, y pasarlo a una funcin o mtodo o la asigna a una
variable, siempre se est de paso o la asignacin de unareferencia a la misma
solo NSString . Prohibida la reproduccin de la cadena se lleva a cabo, a menos que
usted solicite especficamente.
De Swift copia por defecto Cadena comportamiento asegura que cuando una funcin o
mtodo que pasa unacuerda valor, est claro que usted es dueo de esa
exacta Cadena de valor, independientemente de dnde vino. Usted puede estar seguro
de que la cadena que se pasan no se modificar a menos que modifique usted mismo.
Detrs de las escenas, el compilador de Swift optimiza el uso de cadena para que la
copia se realiza efectivamente slo cuando sea absolutamente necesario. Esto significa
que siempre dan un gran rendimiento cuando se trabaja con cadenas como tipos de
valor.
Trabajar con Personajes
De Swift Cadena tipo representa una coleccin de Carcter valores en un orden
especfico. Puede acceder a los individuales de Carcter valores en una cadena por
la iteracin en esa cadena con un para - en bucle:

for character in "Dog! " {

println(character)

// D

// o

// g

// !

//
La for-in bucle se describe en los bucles for .
Como alternativa, crear una independiente de caracteres constante o variable de
una cadena de un solo carcter literal proporcionando un personaje anotacin de
tipo:

let yenSign: Character = ""

49

La concatenacin de cadenas y caracteres


Cuerda valores se pueden sumar (o concatenan ) con el operador de suma ( + ) para
crear una nueva Cadena de valor:

let string1 = "hello"

let string2 = " there"

var welcome = string1 + string2

// welcome now equals "hello there"


Tambin puede aadir una Cadena de valor a una cuenta existente de
cuerda variable con el operador de asignacin de suma ( + = ):

var instruction = "look over"

instruction += string2

// instruction now equals "look over there"


Se puede aadir un personaje valor a una cuerda variable con la cuerda de
tipo append mtodo:

let exclamationMark: Character = "!"

welcome.append(exclamationMark)

// welcome now equals "hello there!"


NOTA
No se puede aadir una cuerda o de caracteres a una cuenta existente de
caracteres variables, porque unpersonaje valor debe contener un nico carcter
nico.
La interpolacin de Cuerdas
Interpolacin de cuerda es una manera de construir una nueva Cadena de valor a
partir de una mezcla de constantes, variables, literales y expresiones mediante la
inclusin de sus valores dentro de una cadena literal. Cada elemento que se inserta en la
cadena literal se envuelve en un par de parntesis, precedido de una barra invertida:

let multiplier = 3

let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"

// message is "3 times 2.5 is 7.5"


En el ejemplo anterior, el valor de multiplicador se inserta en una cadena literal
como \ (multiplicador) .Este marcador de posicin se sustituye con el valor real
de multiplicador cuando se evala la interpolacin de cadenas para crear una
cadena real.
El valor de multiplicador es tambin parte de una expresin mayor ms adelante
en la cadena. Esta expresin calcula el valor de doble (multiplicador) *
2,5 e inserta el resultado ( 7.5 ) en la cadena. En este caso, la expresin se escribe
como \ (Doble (multiplicador) * 2,5) cuando se incluye dentro de la
cadena literal.
NOTA
Las expresiones se escriben dentro de parntesis dentro de una cadena interpolado no
puede contener un doble cita no literal ( " ) ni la barra invertida ( \ ), y no pueden
contener un retorno de carro o salto de lnea.

50

Unicode
Unicode es un estndar internacional para la codificacin, lo que representa, y
procesamiento de textos en diferentes sistemas de escritura. Se le permite representar
casi todos los caracteres de cualquier idioma en una forma estandarizada, y para leer y
escribir los caracteres ay desde una fuente externa, como un archivo de texto o una
pgina web. De Swift de Cuerda y Carcter tipos son totalmente compatible con
Unicode, como se describe en esta seccin.
Unicode escalares
Detrs de las escenas, nativo de Swift Cadena tipo se construye a partir de escalares
Unicode valores. Un escalar Unicode es un nmero de 21 bits nico para un personaje o
modificador, como U + 0061 paraMINSCULA A ( "a" ), o U + 1F425 para que
daba al frente POLLUELO DEL BEB ( " " ).
NOTA
Un escalar Unicode Unicode es cualquier punto de cdigo en el rango U + 0000 a U
+ D7FF incluido o U + E000 a U + 10FFFF inclusive. Escalares Unicode no
incluyen los Unicode par suplente puntos de cdigo, que son los puntos de cdigo en el
rango de U + D800 a U + DFFF inclusive.
Tenga en cuenta que no todos los escalares Unicode de 21 bits se asignan a un
personaje-algunos escalares estn reservados para la asignacin futura. Los escalares
que se han asignado a un carcter tpicamente tambin tienen un nombre,
como MINSCULA A y orientados hacia delante POLLUELO DEL
BEB en los ejemplos anteriores.
Caracteres Unicode especiales en literales de cadena
Los literales de cadena pueden incluir los siguientes caracteres especiales Unicode:
Los caracteres especiales escapados \ 0 (carcter nulo), \\ (barra invertida), \
t (tabulador horizontal),\ n (salto de lnea), \ r (retorno de carro), \ " (comillas
dobles) y \ ' (comilla simple )
Un escalar Unicode arbitraria, escrito como \ u { n } , donde n es entre uno y
ocho dgitos hexadecimales
El cdigo siguiente muestra cuatro ejemplos de estos caracteres
especiales. Los wisewords constantes contiene dos escaparon dos caracteres de
comillas. Los Dollarsign , Blackheart , y sparklingHeart constantes
demuestran el formato escalar Unicode:

let wiseWords = "\"Imagination is more important than knowledge\" - Einstein"

// "Imagination is more important than knowledge" - Einstein

let dollarSign = "\u{24}" // $, Unicode scalar U+0024

let blackHeart = "\u{2665}" // , Unicode scalar U+2665

let sparklingHeart = "\u{1F496}" // , Unicode scalar U+1F496


Extended Clusters grafema
Cada instancia de Swift Carcter tipo representa un solo grupo grafema
extendida . Un clster grafema extendida es una secuencia de uno o ms escalares
Unicode (cuando se combina) producen un solo carcter legible.
He aqu un ejemplo. La carta se puede representar como la nica escalar
Unicode ( E MINSCULA CON AGUDA, o U + 00E9 ). Sin embargo, la misma

51

carta tambin se puede representar como un par de escalares-una carta estndar e ( E


MINSCULA , o U + 0065 ), seguido de la COMBINACIN DE ACENTO
AGUDO escalar ( U + 0301 ).La COMBINACIN DE ACENTO AGUDO escalar se
aplica grficamente al escalar que lo precede, convirtiendo uncorreo en una cuando
se representa por un sistema de representacin de texto Unicode-consciente.
En ambos casos, la carta se representa como una sola Swift Carcter valor que
representa un clster grafema extendida. En el primer caso, el clster contiene un nico
escalar; en el segundo caso, es un grupo de dos escalares:
let precomposed: Character = "\u{D55C}" //

let decomposed: Character = "\u{1112}\u{1161}\u{11AB}" //

// precomposed is , decomposed is
Racimos de grafema ampliada son una forma flexible para representar muchos
caracteres de alfabetos complejos como un solo personaje valor. Por ejemplo, las
slabas Hangul del alfabeto coreano se pueden representar como una secuencia
cualquiera precomposed o descompuesto. Ambas representaciones califican como un
solo personaje valor en Swift:

let precomposed: Character = "\u{D55C}" //

let decomposed: Character = "\u{1112}\u{1161}\u{11AB}" //

// precomposed is , decomposed is

// Precomposed es , descompuesto es
Racimos de grafema ampliada permiten escalares para encerrar marcas
(como COMBINAR adjuntando CIRCLE , o U + 20DD ) para encerrar otros
escalares Unicode como parte de una sola Carcter valor:

let enclosedEAcute: Character = "\u{E9}\u{20DD}"

// enclosedEAcute is
Escalares Unicode para los smbolos indicadores regionales se pueden combinar en
parejas para hacer un solo personaje de valor, como esta combinacin
de REGIONAL INDICADOR SMBOLO LETRA U ( U + 1F1FA ) yREGIONAL
INDICADOR SMBOLO LETRA S ( U + 1F1F8 ):

let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}"

// regionalIndicatorForUS is
Contando Personajes
Para recuperar un recuento de los caracteres en los valores de una cadena, llame al
mundial countElementsfuncin y pase una cadena como nico parmetro de la
funcin:

let unusualMenagerie = "Koala

println("unusualMenagerie has \(countElements(unusualMenagerie)) characters")

// prints "unusualMenagerie has 40 characters"


Tenga en cuenta que el uso de Swift de clusters grafema extendidas
para Carcter valores significa que la concatenacin de cadenas y modificacin no
siempre puede afectar el nmero de caracteres de una cadena.

, Snail

, Penguin

, Dromedary

"

52

Por ejemplo, si inicializa una nueva cadena con la palabra de cuatro caracteres caf , y
luego aadir unaAGUDA ACCENT COMBINACIN ( U + 0301 ) al final de la
cadena, la cadena resultante va a tener un recuento de caracteres de 4 , con una cuarto
carcter de , no e :

var word = "cafe"

println("the number of characters in \(word) is \(countElements(word))")

// prints "the number of characters in cafe is 4"

word += "\u{301}" // COMBINING ACUTE ACCENT, U+0301

println("the number of characters in \(word) is \(countElements(word))")

// prints "the number of characters in caf is 4"


NOTA
Racimos de grafema ampliada pueden estar compuestos de uno o ms escalares
Unicode. Esto significa que diferentes personajes y diferentes representaciones del
mismo carcter, pueden requerir diferentes cantidades de memoria para
almacenar. Debido a esto, los personajes de Swift No cada uno tomar la misma cantidad
de memoria dentro de la representacin de una cadena. Como resultado, el nmero de
caracteres de una cadena no puede calcularse sin iteracin a travs de la cadena para
determinar sus lmites de racimo grafema prolongados. Si est trabajando con valores de
cadena especialmente largos, tenga en cuenta que la countElements funcin debe
iterar sobre los escalares Unicode en toda la cadena con el fin de calcular un recuento de
caracteres exacta para esa cadena.
Tenga en cuenta tambin que el carcter nmero devuelto por countElements no
siempre es la misma que lalongitud caracterstica de un NSString que contiene los
mismos caracteres. La longitud de un NSString se basa en el nmero de unidades de
cdigo de 16 bits dentro de UTF-16 la representacin de la cadena y no el nmero de
grupos de grafema Unicode extenderse dentro de la cadena. Para reflejar este hecho,
lalongitud de la propiedad NSString se llama utf16Count cuando se accede en
un Swift Cadena de valor.
Comparando Cuerdas
Swift proporciona tres maneras de comparar los valores textuales: string y el carcter de
igualdad, de igualdad de prefijo y sufijo de igualdad.
Cadena de caracteres y la Igualdad
Cadena y carcter igualdad se verifica con la "igual a" operador ( == ) y el "no es igual
a" operador ( =! ), como se describe en Operadores de comparacin :

let quotation = "We're a lot alike, you and I."

let sameQuotation = "We're a lot alike, you and I."

if quotation == sameQuotation {

println("These two strings are considered equal")

// prints "These two strings are considered equal"

53

Dos de Cuerda valores (o dos caracteres valores) se consideran iguales si sus


racimos de grafema extendidos son cannicamente equivalentes . Racimos de grafema
ampliada son cannicamente equivalentes si tienen el mismo significado lingstico y la
apariencia, incluso si estn compuestos de diferentes escalares Unicode detrs de las
escenas.
Por ejemplo, E MINSCULA CON AGUDA ( U + 00E9 ) es cannicamente
equivalente a E MINSCULA ( U + 0065 ), seguido de COMBINAR AGUDA
ACCENT ( U + 0301 ). Ambos grupos de grafema extendidas son formas vlidas de
representar el carcter , y por lo que se consideran equivalentes cannicamente:

// "Voulez-vous un caf?" using LATIN SMALL LETTER E WITH ACUTE

let eAcuteQuestion = "Voulez-vous un caf\u{E9}?"

// "Voulez-vous un caf?" using LATIN SMALL LETTER E and COMBINING


ACUTE ACCENT

let combinedEAcuteQuestion = "Voulez-vous un caf\u{65}\u{301}?"

if eAcuteQuestion == combinedEAcuteQuestion {

println("These two strings are considered equal")

// prints "These two strings are considered equal"


Por el contrario, LATIN CAPITAL LETTER A (U+0041, or "A"), tal como se utiliza
en Ingls, es no equivalente aCIRLICA MAYSCULA A ( U + 0410 , o "" ), tal
como se utiliza en ruso. Los caracteres son visualmente similares, pero no tienen el
mismo significado lingstico:
let latinCapitalLetterA: Character = "\u{41}"

let cyrillicCapitalLetterA: Character = "\u{0410}"

if latinCapitalLetterA != cyrillicCapitalLetterA {

println("These two characters are not equivalent")

// prints "These two characters are not equivalent"


NOTA
Cuerda y carcter comparaciones en Swift no son sensible a la localidad.
Prefijo y Sufijo Igualdad
Para comprobar si una cadena tiene un prefijo o sufijo cadena en particular, el llamado
de la cadenahasPrefix y hasSuffix mtodos, los cuales tienen un solo argumento
de tipo de cadena y devolver un valor booleano.
Los ejemplos a continuacin consideran una matriz de cadenas que representan los
lugares de la escena de los dos primeros actos de Shakespeare Romeo y Julieta :

54

let romeoAndJuliet = [

"Act 1 Scene 1: Verona, A public place",

"Act 1 Scene 2: Capulet's mansion",

"Act 1 Scene 3: A room in Capulet's mansion",

"Act 1 Scene 4: A street outside Capulet's mansion",

"Act 1 Scene 5: The Great Hall in Capulet's mansion",

"Act 2 Scene 1: Outside Capulet's mansion",

"Act 2 Scene 2: Capulet's orchard",

"Act 2 Scene 3: Outside Friar Lawrence's cell",

"Act 2 Scene 4: A street in Verona",

"Act 2 Scene 5: Capulet's mansion",

"Act 2 Scene 6: Friar Lawrence's cell"

]
Usted puede utilizar el hasPrefix mtodo con el romeoAndJuliet matriz para
contar el nmero de escenas en el acto 1 de la obra:

var act1SceneCount = 0

for scene in romeoAndJuliet {

if scene.hasPrefix("Act 1 ") {

++act1SceneCount

println("There are \(act1SceneCount) scenes in Act 1")

// prints "There are 5 scenes in Act 1"


Del mismo modo, utilizar el hasSuffix mtodo para contar el nmero de escenas que
tienen lugar en o alrededor de la mansin de los Capuleto y la celda de Fray Lorenzo:

var mansionCount = 0

var cellCount = 0

for scene in romeoAndJuliet {

if scene.hasSuffix("Capulet's mansion") {

++mansionCount

} else if scene.hasSuffix("Friar Lawrence's cell") {

++cellCount

println("\(mansionCount) mansion scenes; \(cellCount) cell scenes")

// prints "6 mansion scenes; 2 cell scenes"


NOTA

55

Los hasPrefix y hasSuffix mtodos de realizar una comparacin equivalencia


cannica carcter por carcter entre los grupos de grafema extendidos en cada cadena,
como se describe en Cadena y Carcter Igualdad .
Unicode Representaciones de Cuerdas
Cuando una cadena Unicode se escribe en un archivo de texto o algn otro tipo de
almacenamiento, los escalares Unicode en esa cadena se codifican en una de varias
definidos Unicode formas de codificacin .Cada forma codifica la cadena en trozos
pequeos conocidos como unidades de cdigo . Estos incluyen el UTF-8 forma de
codificacin (que codifica una cadena como unidades de cdigo de 8 bits), la forma de
codificacin UTF-16 (que codifica una cadena como unidades de cdigo de 16 bits), y
la forma de codificacin UTF-32 (que codifica una cadena como unidades de cdigo de
32 bits).
Swift proporciona varias formas de acceder a las representaciones Unicode de
cuerdas. Usted puede recorrer en iteracin la cadena con un para - en la declaracin,
para acceder a sus particulares caracteres como valores Unicode extendido racimos
grafema. Este proceso se describe en Trabajar con caracteres .
Alternativamente, acceder a una Cadena de valor en una de las otras tres
representaciones Unicode compatibles:
Una coleccin de caracteres UTF-8 unidades de cdigo (consultado con la
cadena utf8 propiedad)
Una coleccin de 16 caracteres UTF-unidades de cdigo (consultado con la
cadena utf16 propiedad)
Una coleccin de valores escalares Unicode de 21 bits, lo que equivale a UTF-32
forma de codificacin de la cadena (consultado con la
cadena unicodeScalars propiedad)
Cada ejemplo muestra una representacin diferente de la siguiente cadena, que se
compone de los caracteres D , o , g , ! ( EXCLAMATION DOBLE MARCA o Unicode
escalar U + 203C ), y la carcter ( CARA DE PERRO , o Unicode escalar U +
1F436 ):

dejar dogString = "perro! "


UTF-8 Representacin
Puede acceder a una representacin UTF-8 de una cuerda por la iteracin en
su utf8 propiedad. Esta propiedad es de tipo String.UTF8View , que es una
coleccin de 8 bits sin signo ( Uint8 valores), uno para cada byte en UTF-8 la
representacin de la cadena:

for codeUnit in dogString.utf8 {

print("\(codeUnit) ")

print("\n")

// 68 111 103 226 128 188 240 159 144 182


En el ejemplo anterior, los tres primeros decimales codeunit valores
( 68 , 111 , 103 ) representan los caracteres D , o , y g , cuya representacin UTF-8 es
el mismo que su representacin ASCII. Los prximos tres
decimales codeunit valores ( 226 , 128 , 188 ) son una de tres bytes UTF-8

56

representacin del DOBLE EXCLAMACIN carcter. Los cuatro


ltimos codeunit valores ( 240 , 159 , 144 , 182 ) son una de cuatro bytes UTF-8
la representacin de la CARA PERRO carcter.
UTF-16 Representacin
Puede acceder a una representacin UTF-16 de una cuerda por la iteracin en
su utf16 propiedad. Esta propiedad es de tipo String.UTF16View , que es una
coleccin de 16 bits sin signo ( uint16 valores), una para cada unidad de cdigo de 16
bits en UTF-16 la representacin de la cadena:

for codeUnit in dogString.utf16 {

print("\(codeUnit) ")

print("\n")

// 68 111 103 8252 55357 56374


Una vez ms, los tres primeros codeunit valores ( 68 , 111 , 103 ) representan los
caracteres D , o , y g , cuya UTF-16 unidades de cdigo tienen los mismos valores que
en UTF-8 la representacin de la cadena (porque estos escalares Unicode representan
caracteres ASCII ).
El cuarto codeunit valor ( 8252 ) es un equivalente decimal del valor
hexadecimal 203C , que representa el escalar Unicode U + 203C para el DOBLE
EXCLAMACIN carcter. Este carcter se puede representar como una sola unidad de
cdigo UTF-16.
La quinta y sexta codeunit valores ( 55.357 y 56.374 ) son una representacin
par suplente UTF-16 de la CARA PERRO carcter. Estos valores son un valor alto
sustituto de U + D83D (valor decimal 55357 ) y un valor bajo sustituta de U +
DC36 (valor decimal 56374 ).
Unicode Scalar Representacin
Puede acceder a una representacin escalar Unicode de una Cadena de valor de la
iteracin en suunicodeScalars propiedad. Esta propiedad es de
tipo UnicodeScalarView , que es una coleccin de valores de
tipo UnicodeScalar .
Cada UnicodeScalar tiene un valor de propiedad que devuelve el valor de 21
bits del escalar, representada dentro de un UInt32 Valor:

for scalar in dogString.unicodeScalars {

print("\(scalar.value) ")

print("\n")

// 68 111 103 8252 128054


Los valores para las propiedades de los tres primeros UnicodeScalar valores
( 68 , 111 , 103 ) una vez representan de nuevo los caracteres D , o , y g .
El cuarto codeunit valor ( 8252 ) es de nuevo un equivalente decimal del valor
hexadecimal 203C , que representa el escalar Unicode U + 203C para el DOBLE
EXCLAMACIN carcter.

57

El valor de la propiedad de la quinta y ltima UnicodeScalar , 128.054 , es


un equivalente decimal del valor hexadecimal 1F436 , lo que representa el escalar
Unicode U + 1F436 para el CARA DE PERRO carcter.
Como una alternativa a la consulta de sus valor propiedades,
cada UnicodeScalar valor tambin se puede utilizar para construir una
nueva cadena de valor, tal como con interpolacin de cadenas:

for scalar in dogString.unicodeScalars {

println("\(scalar) ")

// D

// o

// g

//

//

Tipos Collection
Swift proporciona dos tipos de coleccin , conocidas como matrices y diccionarios, para
almacenar colecciones de valores. Matrices tienda orden listas de valores del mismo
tipo. Diccionarios almacenar colecciones no ordenadas de valores del mismo tipo, que
puede ser referenciado y mir hacia arriba a travs de un identificador nico (tambin
conocido como una clave).
Arrays y diccionarios en Swift son siempre claras sobre los tipos de valores y claves que
pueden almacenar.Esto significa que no se puede insertar un valor de tipo incorrecto en
una matriz o diccionario por error.Tambin significa que usted puede estar seguro
acerca de los tipos de valores que va a recuperar de una matriz o diccionario. Uso de
Swift de colecciones escritas explcitamente garantiza que el cdigo es siempre claro
acerca de los tipos de valores que puede trabajar y le permite capturar cualquier tipo de
desajustes en el desarrollo temprano de su cdigo.
NOTA
Detrs de las escenas, la matriz y Diccionario tipos de Swift se implementan
como colecciones genricas .Para ms informacin sobre los tipos genricos y
colecciones, vea Genricos .
La mutabilidad de las Colecciones
Si crea una matriz o un diccionario y la asigna a una variable, la coleccin que se crea
ser mutable . Esto significa que usted puede cambiar (o mutar ) la coleccin despus
de que se crea al agregar, eliminar o cambiar elementos de la coleccin. Por el contrario,
si se asigna una matriz o un diccionario a una constante, esa matriz o diccionario
es inmutable , y su tamao y contenido no se pueden cambiar.
NOTA
Es una buena prctica para crear colecciones inmutables en todos los casos en que la
coleccin no necesita cambiar. Si lo hace, le permite al compilador Swift para optimizar
el rendimiento de las colecciones que se crean.

58

Arrays
Un array almacena varios valores del mismo tipo en una lista ordenada. El mismo valor
puede aparecer en una matriz varias veces en diferentes posiciones.
Arrays Swift son especficas sobre los tipos de valores que pueden almacenar. Se
diferencian de Objective-C de NSArray y NSMutableArray clases, que pueden
almacenar cualquier tipo de objeto y no proporcionan ninguna informacin sobre la
naturaleza de los objetos que regresan. En Swift, el tipo de valores que una matriz
particular puede almacenar siempre est claro, ya sea a travs de un tipo de anotacin
explcita, o por medio de la inferencia de tipos, y no tiene que ser un tipo de clase. Si se
crea una matriz de Int valores, por ejemplo, no se puede insertar cualquier valor que
no sea Int valores en la matriz. Arrays Swift son de tipo seguro, y siempre estn claros
acerca de lo que pueden contener.
Tipo de matriz Taquigrafa Sintaxis
El tipo de una matriz Swift est escrito en su totalidad como matriz <SomeType> ,
donde SomeType es el tipo que se permite que el conjunto de almacenar. Tambin
puede escribir el tipo de una matriz en forma abreviada como [SomeType] . Aunque
las dos formas son funcionalmente idnticos, se prefiere la forma abreviada, y se utiliza
en toda esta gua para referirse al tipo de una matriz.
Arreglos Literales
Puede inicializar una matriz con un literal de matriz , que es una forma abreviada de
escribir uno o ms valores como una coleccin de matriz. Un literal de matriz se escribe
como una lista de valores separados por comas, rodeado de un par de corchetes:

[ value 1 , value 2 , value 3 ]

El ejemplo siguiente crea una matriz denominada ShoppingList para almacenar de


Cuerda valores:

var shoppingList: [String] = ["Eggs", "Milk"]

// ShoppingList se ha inicializado con dos artculos


iniciales
El ShoppingList variable se declara como "un conjunto de Cuerda valores ",
escrito como [cadena] . Debido a que esta variedad particular ha especificado un tipo
de valor de la Cadena , se slo permite almacenar de Cuerda valores. Aqu,
la ShoppingList matriz se inicializa con dos cuerdas valores
( "huevos" y "Milk" ), escritas en un literal de matriz.
NOTA
El ShoppingList matriz se declara como una variable (con la var introductor) y no
una constante (con la letintroductor) porque ms elementos se aaden a la lista de la
compra en los siguientes ejemplos.
En este caso, la matriz contiene dos literal de Cuerda valores y nada ms. Esto
coincide con el tipo de laShoppingList declaracin de variables (una matriz que
slo puede contener de Cuerda valores), por lo que la asignacin de la matriz literal
se permite como una manera de inicializar ShoppingList con dos artculos iniciales.
Gracias a la inferencia de tipos de Swift, usted no tiene que escribir el tipo del array si
est inicializar con un literal de matriz que contiene los valores del mismo tipo. La

59

inicializacin de ShoppingList podra haber sido escrito en una forma ms corta en


su lugar:

var shoppingList = ["Eggs", "Milk"]


Debido a que todos los valores de la matriz literal son del mismo tipo, Swift se puede
inferir que [cadena] es el tipo correcto a utilizar para la ShoppingList variable.
Acceso y modificacin de una matriz
Puede acceder y modificar una matriz a travs de sus mtodos y propiedades, o
utilizando la sintaxis subndice.
Para saber el nmero de elementos de una matriz, compruebe su lectura slo contar la
propiedad:

println("The shopping list contains \(shoppingList.count) items.")

// prints "The shopping list contains 2 items."

// imprime "La lista de la compra contiene 2 elementos."


Utilice la Boolean estaVacia propiedad como un acceso directo para comprobar si
el recuento de propiedad es igual a 0 :

if shoppingList.isEmpty {

println("The shopping list is empty.")

} else {

println("The shopping list is not empty.")

// prints "The shopping list is not empty."


Puede agregar un nuevo elemento a la final de una matriz llamando a la matriz de
datos anexados mtodo:

shoppingList.append("Flour")
// shoppingList now contains 3 items, and someone is making pancakes
Alternativamente, agregue un conjunto de uno o ms elementos compatibles con el
operador de asignacin de suma ( + = ):

shoppingList += ["Baking Powder"]

// shoppingList now contains 4 items

shoppingList += ["Chocolate Spread", "Cheese", "Butter"]

// shoppingList now contains 7 items


Recuperar un valor de la matriz utilizando sintaxis subndice , pasando el ndice del
valor que desea recuperar entre corchetes inmediatamente despus del nombre de la
matriz:

var firstItem = shoppingList[0]

// firstItem is equal to "Eggs"


Tenga en cuenta que el primer elemento de la matriz tiene un ndice de 0 , no 1 . Arrays
en Swift son siempre cero-indexada.
Usted puede utilizar la sintaxis subndice para cambiar un valor existente en un ndice
dado:

60

shoppingList[0] = "Six eggs"

// El primer elemento de la lista es ahora igual a "Seis


huevos" en lugar de "huevos"
Tambin puede utilizar la sintaxis subndice para cambiar una serie de valores a la vez,
incluso si el conjunto de reemplazo de los valores tiene una longitud diferente a la gama
que est reemplazando. El ejemplo siguiente reemplaza "Spread
Chocolate" , "queso" , y "Butter" con "Bananas" y "Manzanas" :

shoppingList[4...6] = ["Bananas", "Apples"]

// shoppingList now contains 6 items


NOTA
No se puede utilizar la sintaxis subndice para aadir un nuevo elemento a la final de
una matriz. Si intenta utilizar la sintaxis subndice para recuperar o establecer un valor
para un ndice que est fuera de los lmites existentes de una matriz, se activar un error
de ejecucin. Sin embargo, se puede comprobar que un ndice es vlido antes de
utilizarlo, comparndolo con la matriz de conteo propiedad. Excepto cuando el
recuentoes 0 (es decir, la matriz est vaca), el mayor ndice vlido de una matriz
siempre ser count - 1 , porque las matrices se indexan de cero.
Para insertar un elemento en la matriz en un ndice especificado, la llamada de la
matriz de insercin (atIndex :) mtodo:

shoppingList.insert("Maple Syrup", atIndex: 0)

// shoppingList now contains 7 items

// "Maple Syrup" is now the first item in the list


Esta llamada a la insercin mtodo inserta un nuevo elemento con un valor
de "jarabe de arce" en el comienzo mismo de la lista de la compra, se indica
mediante un ndice de 0 .
Del mismo modo, se elimina un elemento de la matriz con
el removeAtIndex mtodo. Este mtodo elimina el elemento en el ndice
especificado y devuelve el elemento eliminado (aunque se puede ignorar el valor
devuelto si no lo necesita):
let mapleSyrup = shoppingList.removeAtIndex(0)// El elemento que estaba

en el ndice 0 slo se ha eliminado

// ShoppingList ahora contiene 6 artculos, y no el jarabe


de arce

// La constante Maplesyrup es ahora igual a la cadena


"jarabe de arce" eliminado
Las lagunas de una matriz se cierran cuando se elimina un elemento, por lo que el valor
en el ndice 0 es una vez ms igual a "Seis huevos" :

firstItem = ShoppingList [ 0 ]

// FirstItem es ahora igual a "Seis huevos"


Si desea eliminar el ltimo punto de una matriz, utilice el removeLast mtodo en
lugar de la removeAtIndexmtodo para evitar la necesidad de consultar de la

61

matriz recuento propiedad. Al igual que


el removeAtIndexmtodo, removeLast devuelve el elemento eliminado:

let apples = shoppingList.removeLast()

// El ltimo elemento de la matriz slo se ha eliminado

// ShoppingList ahora contiene 5 artculos, y no hay


manzanas

// las manzanas constante es ahora igual a las "manzanas"


retirados cadena


Interactuando sobre una matriz
Puede iterar sobre todo el conjunto de valores en una matriz con el de - en bucle:

for item in shoppingList {

println(item)

// Six eggs

// Milk

// Flour

// Baking Powder

// Bananas
Si usted necesita el ndice entero de cada elemento, as como su valor, utilice el
mundial enumerate funcin para repetir la matriz en
lugar. La enumeracin funcin devuelve una tupla para cada elemento del conjunto
formado por el ndice y el valor de ese elemento. Puede descomponerse en la tupla
constantes o variables temporales como parte de la iteracin:

for (index, value) in enumerate(shoppingList) {

println("Item \(index + 1): \(value)")

// Item 1: Six eggs

// Item 2: Milk

// Item 3: Flour

// Item 4: Baking Powder

// Item 5: Bananas
Para ms informacin sobre la para - en bucle, consulte Para Loops .
Creacin e inicializacin de una matriz
Puede crear una matriz vaca de un cierto tipo (sin establecer valores iniciales),
utilizando la sintaxis de inicializador:

var someInts = [Int]()

println("someInts is of type [Int] with \(someInts.count) items.")


62

// prints "someInts is of type [Int] with 0 items."


Tenga en cuenta que el tipo de la someInts variable se infiere que [Int] , ya que se
ajusta a la salida de un[Int] inicializador.
Alternativamente, si el contexto ya ofrece informacin de tipo, como un argumento de
funcin o una variable ya mecanografiado o constante, se puede crear una matriz vaca
con una matriz vaca literal, que se escribe como [] (un par vaco de corchetes):

someInts.append(3)

// someInts now contains 1 value of type Int

someInts = []

// someInts es ahora un conjunto vaco, pero sigue siendo


de tipo [Int]
De Swift Matriz tipo tambin proporciona un inicializador para la creacin de una
matriz de un cierto tamao, con todos sus valores establecidos en un valor
predeterminado proporcionado. Se pasa este inicializador el nmero de elementos a
aadir a la nueva matriz (denominada cuenta ) y un valor por defecto del tipo
apropiado (denominado repeatedValue ):

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

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


Puede crear una nueva matriz sumando dos matrices existentes de tipo compatible con
el operador de suma ( + ). Tipo de la nueva matriz se infiere a partir del tipo de las dos
matrices se agregan juntos:

var anotherThreeDoubles = [Double](count: 3, repeatedValue: 2.5)

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

var sixDoubles = threeDoubles + anotherThreeDoubles

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

Diccionarios
Un diccionario es un contenedor que almacena varios valores del mismo tipo. Cada
valor se asocia con una nica tecla , que acta como un identificador para ese valor
dentro del diccionario. A diferencia de los elementos de un array, los elementos de un
diccionario no tienen un orden especfico. Se utiliza un diccionario cuando necesita
buscar valores en funcin de su identificador, casi de la misma manera que un
diccionario en el mundo real se utiliza para buscar la definicin de una palabra en
particular.
NOTA

63

Diccionarios Swift son especficas sobre los tipos de claves y valores que pueden
almacenar. Se diferencian de Objective-C
de NSDictionary y NSMutableDictionary clases, que pueden usar cualquier
tipo de objeto como sus claves y valores y no proporcionan ninguna informacin sobre
la naturaleza de esos objetos. En Swift, el tipo de claves y valores que un diccionario
particular puede almacenar siempre se pone de manifiesto, ya sea a travs de un tipo de
anotacin explcita oa travs de la inferencia de tipos.
Diccionario Tipo Taquigrafa Sintaxis
El tipo de un diccionario Swift est escrito en su totalidad como Dictionary
<KeyType, ValueType> , dondeKeyType es el tipo de valor que puede ser
utilizado como una clave de diccionario, y ValueType es el tipo de valor que las
tiendas Diccionario para esas llaves.
Tambin puede escribir el tipo de un diccionario en forma abreviada
como [KeyType: ValueType] . Aunque las dos formas son funcionalmente
idnticos, se prefiere la forma abreviada, y se utiliza en toda esta gua para referirse al
tipo de un diccionario.
Los literales Diccionario
Puede inicializar un diccionario con un diccionario literal , que tiene una sintaxis
similar a la matriz literal visto antes. Un literal diccionario es una forma abreviada de
escribir uno o ms pares clave-valor como unDiccionario coleccin.
Un par clave-valor es una combinacin de una clave y un valor. En un literal
diccionario, la clave y el valor de cada par clave-valor estn separados por dos
puntos. Los pares clave-valor se escriben como una lista, separada por comas, rodeado
de un par de corchetes:

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

El siguiente ejemplo crea un diccionario para almacenar los nombres de los aeropuertos
internacionales. En este diccionario, las claves son cdigos de tres letras de la
Asociacin Internacional de Transporte Areo, y los valores son los nombres de
aeropuertos:

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


La aeropuertos diccionario se declara como tener un tipo de [Cadena:
String] , que significa "un diccionariocuyas claves son del tipo de cuerda ,
y cuyos valores son tambin del tipo de cuerda ".
NOTA
La aeropuertos diccionario se declara como una variable (con la var introductor),
y no una constante (con lalet introductor), debido a que ms aeropuertos se aaden al
diccionario en los ejemplos siguientes.
La aeropuertos diccionario se inicializa con un diccionario literal que contiene dos
pares clave-valor. El primer par tiene una clave de "TYO" y un valor de "Tokio" . El
segundo par tiene una clave de "DUB" y un valor de"Dublin" .
Este literal diccionario contiene dos cuerdas: Cuerda pares. Este tipo de clavevalor coincide con el tipo de losaeropuertos de declaracin de variables (un

64

diccionario con slo Cuerda llaves, y slo de Cuerda valores), por lo que la
asignacin del diccionario literal se permite como una manera de inicializar
los aeropuertos diccionario con dos artculos iniciales.
Al igual que con las matrices, usted no tiene que escribir el tipo del diccionario si ests
inicializar con un literal diccionario cuyas claves y valores tienen tipos coherente. La
inicializacin de los aeropuertos podra haber sido ser escrito en una forma ms
corta en su lugar:

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


Debido a que todas las claves en el literal son del mismo tipo que los dems, y del
mismo modo todos los valores son del mismo tipo que los dems, Swift se puede inferir
que [Cadena: Cadena] es el tipo correcto a utilizar para
el aeropuertos diccionario.
Acceso y Modificacin de un diccionario
Puede acceder y modificar un diccionario a travs de sus mtodos y propiedades, o
utilizando la sintaxis subndice. Al igual que con una matriz, a averiguar el nmero de
elementos en un Diccionario comprobando su lectura slo contar la propiedad:

println("The airports dictionary contains \(airports.count) items.")

// imprime "El diccionario de los aeropuertos contiene 2


elementos."
Utilice la Boolean estaVacia propiedad como un acceso directo para comprobar si
el recuento de propiedad es igual a 0 :

if airports.isEmpty {

println("The airports dictionary is empty.")

} else {

println("The airports dictionary is not empty.")

// imprime "Diccionario de los aeropuertos no est vaca."


Puede agregar un nuevo elemento a un diccionario con la sintaxis subndice. Utilice una
llave del tipo apropiado como el ndice de subndice, y asignar un nuevo valor del tipo
apropiado:

airports["LHR"] = "London"

// Diccionario de los aeropuertos ahora contiene 3


artculos
Tambin puede utilizar la sintaxis subndice para cambiar el valor asociado a una clave
particular:

airports["LHR"] = "London Heathrow"

// El valor de "LHR" se ha cambiado por "Londres Heathrow"


Como alternativa a subndices, use un diccionario UpdateValue (forKey
:) mtodo para establecer o actualizar el valor de una clave particular. Al igual que los
ejemplos anteriores subndice, el UpdateValue (forKey :)mtodo establece un
valor para una clave si no existe ninguno, o actualiza el valor si ya existe esa clave. A
diferencia de un subndice, sin embargo, el UpdateValue (forKey :) mtodo

65

devuelve el viejo valor despus de realizar una actualizacin. Esto le permite comprobar
si una actualizacin se llev a cabo.
El UpdateValue (forKey :) mtodo devuelve un valor opcional de valor tipo
del diccionario. Para un diccionario que almacena Cuerda valores, por ejemplo, el
mtodo devuelve un valor de tipo de cadena? , o "opcional Cadena". Este valor
opcional contiene el valor antiguo para esa clave, si es que exista antes de la
actualizacin, onil si exista ningn valor:

if let oldValue = airports.updateValue("Dublin International", forKey: "DUB") {

println("The old value for DUB was \(oldValue).")

// imprime "El valor antiguo para DUB era Dubln."


Tambin puede utilizar la sintaxis subndice para recuperar un valor del diccionario para
una clave particular.Debido a que es posible solicitar una clave para los que no existe
ningn valor, el subndice de un diccionario devuelve un valor opcional de valor de tipo
del diccionario. Si el diccionario contiene un valor para la clave solicitada, el subndice
devuelve un valor opcional que contiene el valor existente para esa tecla. De lo
contrario, el subndice retornos nil :

if let airportName = airports["DUB"] {

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

} else {

println ( "Ese aeropuerto no est en el diccionario


aeropuertos." )

// imprime "El nombre del aeropuerto es Dublin


International."
Usted puede utilizar la sintaxis subndice para quitar un par clave-valor de un
diccionario mediante la asignacin de un valor de cero para esa clave:

airports["APL"] = "Apple International"

// "Apple Internacional" no es el aeropuerto ms real para


APL, por lo que la elimina

airports["APL"] = nil

// APL ha sido eliminado del diccionario


Alternativamente, quitar un par clave-valor de un diccionario con
el removeValueForKey mtodo. Este mtodo elimina el par clave-valor si existe y
devuelve el valor extrado, o vuelve nulo cuando no existe otro valor:

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.")

}
66

// imprime "El nombre del aeropuerto es eliminado Dublin


International."
Iterar sobre un diccionario
Puede iterar sobre los pares de valores clave en un diccionario con un para en bucle. Cada elemento en el diccionario se devuelve como una (, valor de la
clave) tupla, y se puede descomponer los miembros de la tupla en constantes o
variables temporales como parte de la iteracin:

for (airportCode, airportName) in airports {

println("\(airportCode): \(airportName)")

// LHR: London Heathrow

// TYO: Tokyo
Para ms informacin sobre la para - en bucle, consulte Para Loops .
Tambin puede recuperar una coleccin iterable de claves o valores de un diccionario
mediante el acceso a sus claves y valores propiedades:

for (airportCode, airportName) in airports {

println("\(airportCode): \(airportName)")

// LHR: London Heathrow

// TYO: Tokyo
For more about the for-in loop, see For Loops.
You can also retrieve an iterable collection of a dictionarys keys or values by accessing
its keys and valuesproperties:

for airportCode in airports.keys {

println("Airport code: \(airportCode)")

// Airport code: LHR

// Airport code: TYO

for airportName in airports.values {

println("Airport name: \(airportName)")

// Airport name: London Heathrow

// Airport name: Tokyo


Si usted necesita utilizar claves o valores de un diccionario con una API que toma
una matriz de ejemplo, inicializar un nuevo array con las claves o valores
de la propiedad:

let airportCodes = [String](airports.keys)

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


67

let airportNames = [String](airports.values)

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


NOTA
De Swift Diccionario tipo es una coleccin desordenada. No se especifica el orden
en el que las claves, valores y pares clave-valor se recuperan cuando la iteracin en un
diccionario.
Creacin de un diccionario vaco
Al igual que con las matrices, se puede crear un Diccionario vaco de cierto tipo
utilizando la sintaxis de inicializador:

var namesOfIntegers = [Int: String]()

// namesOfIntegers is an empty [Int: String] dictionary


En este ejemplo se crea un diccionario vaco de tipo [Int: String] para almacenar
nombres legibles de valores enteros. Sus teclas son de tipo int , y sus valores son de
tipo Cadena .
Si el contexto ya ofrece informacin de tipo, puede crear un diccionario vaco con un
diccionario vaco literal, que se escribe como [:] (dos puntos dentro de un par de
corchetes):

namesOfIntegers [ 16 ] = "diecisis"

// namesOfIntegers ahora contiene 1 par clave-valor

namesOfIntegers = [:]

// namesOfIntegers es una vez ms un diccionario vaco de


tipo [Int: String]

Valores hash para los tipos clave de diccionario
Un tipo debe ser Hashable con el fin de ser utilizado como un diccionario de tipo clave,
es decir, el tipo debe proporcionar una forma de calcular un valor hash por s
mismo. Un valor hash es un Int valor que es el mismo para todos los objetos que
comparan iguales, tal que si a == b , se deduce que a.hashValue ==
b.hashValue .
Todos los tipos bsicos de Swift (tales como cuerdas , Int , doble , y Bool ) son
Hashable por defecto, y todos estos tipos se pueden usar como las teclas de un
diccionario. Valores de los miembros de enumeracin sin valores asociados (como se
describe en enumeraciones ) tambin son Hashable por defecto.
NOTA
Usted puede utilizar sus propios tipos personalizados como tipos clave de diccionario al
hacerlos conformes a la Hashable protocolo de la biblioteca estndar de Swift. Los
tipos que se ajustan a la Hashable protocolo debe proporcionar una
gettable Int propiedad llamada hashValue , y tambin deben proporcionar una
implementacin de la "es igual" operador ( == ). El valor devuelto por un tipo
de hashValue propiedad no est obligado a ser la misma en diferentes ejecuciones del
mismo programa, o en diferentes programas.

68

Para obtener ms informacin acerca de conforme a los protocolos,


consulte Protocolos .
Control de flujo
Swift proporciona todos los estados de flujos de control conocidos de idiomas como
C. Estos incluyen for and whileloops para realizar una tarea varias veces; ify switch
sentencias para ejecutar diferentes ramas de cdigo basado en ciertas condiciones; y
declaraciones tales como breaky continue para transferir el flujo de ejecucin a
otro punto en el cdigo.
Adems de la tradicional de bucle que se encuentra en C, Swift agrega un for- in
bucle que hace que sea fcil de iterar sobre arrays, diccionarios, rangos, cadenas y otras
secuencias.
De Swift switch declaracin tambin es considerablemente ms potente que su
homlogo en C. Los casos de un switch de declaracin no "caen a travs de" al
siguiente caso en Swift, evitando errores C comunes causadas por faltantes de break
declaraciones. Los casos pueden coincidir con muchos modelos diferentes, incluyendo
partidos de rango, tuplas, y arroja a un tipo especfico. Valores coincidentes en un
switch de caso se pueden unir a las constantes o variables temporales para su uso
dentro del cuerpo del caso, y las condiciones de juego complejas se pueden expresar con
una clusula where para cada caso.
Para Loops
Swift proporciona dos tipos de bucle que realizan un conjunto de declaraciones de un
cierto nmero de veces:
La for- in bucle realiza una serie de afirmaciones para cada elemento en un
rango, secuencia, recogida, o progresin.
El for bucle realiza una serie de declaraciones hasta que se cumpla una condicin
especfica, por lo general mediante el incremento de un contador cada vez que el
bucle termina.
For-In
Se utiliza la for- in bucle para iterar sobre colecciones de objetos, tales como rangos
de nmeros, elementos de un conjunto, o caracteres de una cadena.
Este ejemplo imprime las primeras entradas de la cinco-veces-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
La coleccin de artculos que se iterado es una gama cerrado de nmeros
de 1 a 5 inclusive, como se indica por el uso del operador de rango cerrado ( ... ). El

69

valor del ndice se establece en el primer nmero en el rango ( 1 ), y se ejecutan las


sentencias dentro del bucle. En este caso, el bucle contiene slo una declaracin, que
imprime una entrada de la cinco veces-mesa para el valor actual de ndice . Despus
de que se ejecuta la sentencia, el valor de ndice se actualiza para contener el segundo
valor en el intervalo ( 2 ), y elprintln funcin es llamada nuevamente. Este proceso
contina hasta que se alcanza el final de la gama.
En el ejemplo anterior, el ndice es una constante cuyo valor se establece
automticamente al inicio de cada iteracin del bucle. Como tal, no tiene que ser
declarado antes de ser usado. Se declara implcitamente simplemente por su inclusin
en la declaracin del bucle, sin la necesidad de un let declaracin palabra clave.
NOTA
El ndice constante existe solamente dentro del alcance de la bucle. Si desea
comprobar el valor del ndicedespus de completar el bucle, o si usted quiere trabajar
con su valor como una variable en lugar de una constante, debe declararlo a ti mismo
antes de su uso en el circuito.
Si usted no necesita cada valor de la gama, puede ignorar los valores mediante el uso de
un guin en lugar de un nombre de variable:

let base = 3

let power = 10

var answer = 1

for _ in 1...power {

answer *= base

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

// Imprime "3 a la potencia de 10 es 59049"


En este ejemplo se calcula el valor de un nmero a la potencia de otro (en este caso, 3 a
la potencia de 10 ).Se multiplica un valor inicial de 1 (es decir, 3 a la potencia de 0 )
por 3 , diez veces, utilizando una gama cerrado que comienza con 1 y termina
con 10 . Este clculo no tiene por qu conocer los valores de los contadores
individuales en cada iteracin del bucle simplemente necesita ejecutar el bucle el
nmero correcto de veces. El carcter de subrayado _ (en lugar de una variable de
bucle) hace que los valores individuales sean ignorados y no proporciona acceso al
valor actual en cada iteracin del bucle.
Use una for- in bucle con un arsenal para repetir sus artculos:

let names = ["Anna", "Alex", "Brian", "Jack"]

for name in names {

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

// Hello, Anna!

// Hello, Alex!

// Hello, Brian!

// Hello, Jack!

70

Tambin puede iterar sobre un diccionario para acceder a sus pares clave-valor. Cada
elemento en el diccionario se devuelve como un (clave, valor) tupla cuando se
itera el diccionario, y se puede descomponer el (valor llave) los miembros de la
tupla como constantes nombradas explcitamente para su uso dentro del cuerpo de
la para - en bucle. Aqu, las claves del diccionario se descomponen en una constante
llamadaanimalName , y los valores del diccionario se descomponen en una constante
llamada legCount :

let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]

for (animalName, legCount) in numberOfLegs {

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

// araas tienen 8 patas

// gatos tienen 4 patas

// hormigas tienen 6 patas


Los elementos de un diccionario no necesariamente pueden repetir en el mismo
orden en que se insertaron.El contenido de un diccionario son intrnsecamente
desordenada, y la iteracin en ellos no garantiza el orden en el que se recuperarn. Para
ms informacin sobre matrices y diccionarios, vea Tipos Collection .)
Adems de las matrices y los diccionarios, tambin puede utilizar la para - en bucle
para iterar sobre loscaracteres valores en una cadena:

for character in "Hello" {

println(character)

// H

// e

// l

// l

// o
For
Adems de para - en bucles, Swift apoya al estilo de C tradicional para bucles con
una condicin y un incrementador:

for var index = 0; index < 3; ++index {

println("index is \(index)")

// index is 0

// index is 1

// index is 2
Heres the general form of this loop format:

71

for initialization ; condition ; increment {

statements

}
Los puntos y comas separan las tres partes de la definicin del bucle, como en C. Sin
embargo, a diferencia de C, Swift no necesita parntesis alrededor de toda la
inicializacin "; condicin; bloque de incremento ".
El bucle se ejecuta de la siguiente manera:
1. La primera vez que se entra en el bucle, la expresin de inicializacin se evala una
vez, para establecer cualquier constante o variables que se necesitan para el bucle.
2. La expresin de condicin es evaluada. Si se evala como falsa , el bucle termina,
y la ejecucin de cdigo contina despus de la de llave de cierre del bucle ( } ). Si
la expresin se evala comoverdadera , la ejecucin de cdigo contina
ejecutando las sentencias entre llaves.
3. Despus se ejecutan todas las declaraciones, la expresin de incremento se
evala. Puede aumentar o disminuir el valor de un contador, o establecer una de las
variables inicializadas a un nuevo valor basado en el resultado de las
declaraciones. Despus de la expresin de incremento ha sido evaluado, la ejecucin
vuelve al paso 2, y la expresin de condicin se evala otra vez.
El proceso de formato de bucle y la ejecucin descrita anteriormente es la abreviatura de
(y equivalente a) el siguiente esquema:

initialization

while condition {

statements

increment
}
Constantes y variables declaradas dentro de la expresin de inicializacin
(como ndice var = 0 ) slo son vlidos en el mbito de la de bucle en s. Para
recuperar el valor final del ndice despus de los extremos de bucle, debe declarar el
ndice antes de que comience el alcance del bucle:

var index: Int

for index = 0; index < 3; ++index {

println("index is \(index)")

// index is 0

// index is 1

// index is 2

println ( "Las sentencias de bucle fueron ejecutados \ ( index ) veces " )

72

// grabados "fueron ejecutados Las sentencias de bucle 3


veces"
Tenga en cuenta que el valor final del ndice despus de que se complete este bucle
es 3 , no 2 . La ltima vez que la declaracin de la subasta ndice ++ se llama, se
pone ndice a 3 , lo que hace que el ndice <3equiparar a falso , terminando
el bucle.
Mientras Loops
Un tiempo de bucle realiza un conjunto de declaraciones hasta que una condicin se
convierte en falsa . Este tipo de bucles se utilizan mejor cuando no se conoce el
nmero de iteraciones antes de que comience la primera iteracin. Swift proporciona
dos tipos de tiempo de bucle:
mientras evala su estado en el inicio de cada pasada a travs del bucle.
hacer - mientras se evala su condicin al final de cada paso a travs del
bucle.

While (Mientras)
Un while de bucle comienza evaluando un solo estado. Si la condicin
es verdadera , un conjunto de estados se repite hasta que la condicin se convierte
en falsa .
Aqu est la forma general de un while bucle:

while condition {
statements

Este ejemplo tiene un simple juego de Serpientes y Escaleras (tambin conocido


como Serpientes y Escaleras ):

73


Las reglas del juego son las siguientes:
El tablero tiene 25 cuadrados, y el objetivo es aterrizar en o ms all de la plaza 25.
Cada turno, tirar un dado de seis caras y jugada de ese nmero de plazas, siguiendo
el camino horizontal que indica la flecha punteada arriba.
Si su turno termina en la parte inferior de una escalera, que se asciende por la
escalera.
Si su turno termina a la cabeza de una serpiente, se mueve hacia abajo esa serpiente.
El tablero de juego est representado por una serie de Int valores. Su tamao se basa
en una constante llamada finalSquare , que se utiliza para inicializar la matriz y
tambin para comprobar si hay una condicin de victoria ms adelante en el ejemplo. La
junta se inicializa con cero 26 Int valores, no 25 (uno por cada uno en los ndices
de 0 a travs de 25 inclusive):

let finalSquare = 25

var board = [Int](count: finalSquare + 1, repeatedValue: 0)


Algunas plazas se establecen a continuacin, a tener valores ms especficos para las
serpientes y escaleras. Cuadrados con una base de la escalera tiene un nmero positivo a
mover el tablero, mientras que los cuadrados con una cabeza de serpiente tienen un
nmero negativo para moverte hacia abajo la placa:

board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02

board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08


Plaza 3 contiene la parte inferior de una escalera que sube a la plaza 11 Para representar
esto, board [03] es igual a 08 , lo que equivale a un valor entero de 8 (la diferencia
entre 3 y 11 ). El operador unario ms ( + i ) los saldos con el operador menos unario
( -i ), y los nmeros menores que 10 se rellenan con ceros para que todas las
definiciones de mesa se alinean. (Ni tweak estilstica es estrictamente necesario, pero
que conducen a ms aseado cdigo.)
Casilla de salida del jugador es "cero plaza", que se encuentra junto a la esquina inferior
izquierda del tablero.La primera tirada de dados siempre se mueve el jugador en el
tablero:

74

var square = 0

var diceRoll = 0

while square < finalSquare {

// roll the dice

if ++diceRoll == 7 { diceRoll = 1 }

// move by the rolled amount

square += diceRoll

if square < board.count {

// if we're still on the board, move up or down for a snake or a ladder

square += board[square]

println("Game over!")
En este ejemplo se utiliza un enfoque muy simple para tirar los dados. En lugar de un
generador de nmeros aleatorios, que comienza con un diceRoll valor de 0 . Cada
vez que a travs del tiempo de bucle, diceRoll se incrementa con el operador de
incremento prefijo ( ++ i ), y luego se comprueba para ver si se ha hecho demasiado
grande. El valor de retorno de ++ diceRoll es igual al valor de diceRoll despus
de que se incrementa. Cada vez que este valor de retorno es igual a 7 , la tirada se ha
vuelto demasiado grande, y se pone a un valor de 1 . Esto da una secuencia
de diceRoll valores que siempre es 1 , 2 , 3 , 4 , 5 , 6 , 1 , 2 y as sucesivamente.
Despus de tirar los dados, el jugador avanza por diceRoll cuadrados. Es posible que
la tirada de dados pudo haber movido el jugador ms all de la plaza 25, en cuyo caso el
juego ha terminado. Para hacer frente a este escenario, el cdigo comprueba que la
plaza es menor que el consejo de gama recuento propiedad antes de aadir el
valor almacenado en cartn [cuadrados] en la actual plaza de valor para
mover el jugador hacia arriba o hacia abajo las escaleras o las serpientes.
Si este cheque no se ha realizado, a bordo [cuadrado] podran tratar de acceder a
un valor fuera de los lmites de la placa de matriz, que daran lugar a un
error. Si cuadrado es ahora igual a 26 , el cdigo sera tratar de comprobar el valor
de la tabla de [26] , que es ms grande que el tamao de la matriz.
La corriente mientras que la ejecucin del bucle finaliza entonces, y la condicin
del bucle se comprueba para ver si el bucle debe ejecutarse de nuevo. Si el jugador ha
movido en o ms all de la plaza nmero 25 , la condicin del bucle se evala
como falsa , y el juego termina.
Un mientras bucle es apropiado en este caso porque la longitud del juego no est
claro en el comienzo de lamientras bucle. En cambio, el bucle se ejecuta hasta que
una condicin particular es satisfecho.
Do-While
La otra variacin de la while bucle, conocido como el do while bucle, realiza
una sola pasada a travs del bloque de bucle primero, antes de considerar la condicin
del bucle. A continuacin, sigue repitiendo el bucle hasta que la condicin es falsa .

75

Aqu est la forma general de un do while bucle:


do {

statements

} while condition
Aqu est el juego de la oca ejemplo de nuevo, escrito como un do - mientras bucle
en lugar de una , mientras que bucle. Los valores
de finalSquare , tablero , cuadrados , y diceRoll se inicializan
exactamente de la misma manera que con un tiempo de bucle:

let finalSquare = 25

var board = [Int](count: finalSquare + 1, repeatedValue: 0)

board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02

board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08

var square = 0

var diceRoll = 0
En esta versin del juego, la primera accin en el circuito es para comprobar si hay una
escalera o una serpiente. No Escalera en el tablero lleva al jugador directamente a la
plaza 25, por lo que no es posible ganar el juego al subir una escalera. Por lo tanto, es
seguro para comprobar si hay una serpiente o una escalera como la primera accin en el
circuito.
Al comienzo del juego, el jugador est en "cero plaza". tablero [0] siempre es
igual 0 , y no tiene efecto:

do {

// move up or down for a snake or ladder

square += board[square]

// roll the dice

if ++diceRoll == 7 { diceRoll = 1 }

// move by the rolled amount

square += diceRoll

} while square < finalSquare

println("Game over!")
Despus de los controles de cdigo para serpientes y escaleras, los dados se rueda, y el
jugador se mueve hacia adelante por diceRoll cuadrados. La ejecucin del bucle de
corriente luego termina.
La condicin del bucle ( mientras cuadrado <finalSquare ) es el mismo que
antes, pero esta vez no se evala hasta que el final de la primera pasada por el bucle. La
estructura de la do - mientras bucle se adapta mejor a este juego que el tiempo de
bucle en el ejemplo anterior. En el do while bucle de arriba, cuadrado + =
bordo [cuadrado] siempre se ejecuta inmediatamente despus del bucle while
la condicin confirma que la plaza est todava en el tablero. Este comportamiento

76

elimina la necesidad de la comprobacin de lmites de la matriz visto en la versin


anterior del juego.
Sentencias condicionales
A menudo es til para ejecutar diferentes piezas de cdigo basado en ciertas
condiciones. Es posible que desee ejecutar un pedazo de cdigo cuando se produce un
error, o para mostrar un mensaje cuando un valor es demasiado alto o demasiado
bajo. Para hacer esto, usted hace parte de su cdigo condicional .
Swift proporciona dos maneras de agregar saltos condicionales a su cdigo, conocido
como el caso de la declaracin y el interruptor comunicado. Normalmente, se
utiliza el caso de declaracin para evaluar las condiciones simples con slo unos
pocos resultados posibles. El interruptor de declaracin se adapta mejor a
condiciones ms complejas con mltiples permutaciones posibles, y es til en
situaciones en las que la concordancia de patrones puede ayudar a seleccionar una rama
de cdigo apropiado para ejecutar.
If
En su forma ms simple, el if de la declaracin tiene un solo caso
de condicin. Ejecuta un conjunto de declaraciones slo si esa condicin es true:

var temperatureInFahrenheit = 30

if temperatureInFahrenheit <= 32

println ( "Hace mucho fro. Considere usar una bufanda." )

// imprime "Es muy fro. Considere usar una bufanda."


El ejemplo anterior comprueba si la temperatura es inferior o igual a 32 grados
Fahrenheit (el punto de congelacin del agua). Si lo es, se imprime un mensaje. De lo
contrario, ningn mensaje se imprime, y la ejecucin de cdigo contina despus de que
el caso de llave de cierre de declaracin.
El caso de declaracin puede proporcionar un conjunto alternativo de los estados,
conocidos como clusula else , para cuando el si la condicin es falsa . Estas
declaraciones se indican con la otra palabra clave:

temperatureInFahrenheit = 40

if temperatureInFahrenheit <= 32 {

println("It's very cold. Consider wearing a scarf.")

} else {

println("It's not that cold. Wear a t-shirt.")

// imprime "no est tan fra. Lleve una camiseta".


Una de estas dos ramas siempre se ejecuta. Debido a que la temperatura ha aumentado
a 40 grados Fahrenheit, ya no es lo suficientemente fro como para aconsejar que
llevaba un pauelo, y lo que la otrarama se dispara en su lugar.

77

Puede mltiple cadena si las declaraciones en conjunto, a tener en cuenta clusulas


adicionales:

temperatureInFahrenheit = 90

if temperatureInFahrenheit <= 32 {

println("It's very cold. Consider wearing a scarf.")

} else if temperatureInFahrenheit >= 86 {

println("It's really warm. Don't forget to wear sunscreen.")

} else {

println("It's not that cold. Wear a t-shirt.")

// imprime "Es muy caliente. No se olvide de usar protector


solar."
Aqu, un adicional if se aade la declaracin para responder a las temperaturas
particularmente clidos. La ltima else clusula se mantiene, e imprime una
respuesta para cualquier temperatura que no son ni demasiado caliente ni demasiado
fra.
La final else clusula es opcional, sin embargo, y puede ser excluida si el conjunto de
condiciones no necesita ser completa:

temperatureInFahrenheit = 72

if temperatureInFahrenheit <= 32 {

println("It's very cold. Consider wearing a scarf.")

} else if temperatureInFahrenheit >= 86 {

println ( "Es muy caliente. No se olvide de usar protector solar." )

}
En este ejemplo, la temperatura no es ni demasiado fro ni demasiado caliente para
activar el si o ms si las condiciones, y as se imprime ningn mensaje.
Switch
Un switch declaracin considera un valor y lo compara contra varios patrones
coincidentes posibles.A continuacin, se ejecuta un bloque de cdigo apropiado, basado
en el primer patrn que coincida con xito.Un switch declaracin proporciona una
alternativa a la if la declaracin para responder a mltiples estados posibles.
En su forma ms simple, un switch declaracin compara un valor con uno o ms
valores del mismo tipo:

switch some value to consider {

case value 1 :
respond to value 1

case value 2 ,

78

value 3 :

respond to value 2 or 3

default:

otherwise, do something else

}
Cada switch de declaracin consiste en mltiples posibles casos , cada uno de los
cuales comienza con el caso de palabras clave. Adems de comparar con los valores
especficos, Swift ofrece varias maneras para cada caso para especificar patrones
coincidentes ms complejos. Estas opciones se describen ms adelante en esta seccin.
El cuerpo de cada interruptor de caso es una rama separada de la ejecucin de
cdigo, de manera similar a las ramas de un si declaracin. El interruptor de la
declaracin determina qu rama debe ser seleccionado.Esto se conoce
como conmutacin en el valor que se est considerando.
Cada switch de declaracin debe ser exhaustiva . Es decir, cada valor posible del
tipo que se est considerado debe ser igualada por uno de los de
conmutacin casos. Si no es apropiado para proporcionar un switch de caso para
cada valor posible, se puede definir un cajn de sastre caso por defecto para cubrir
cualquier valor que no se tratan de forma explcita. Este cajn de sastre caso se indica
con la palabra clavepor defecto , y debe aparecer siempre pasado.
En este ejemplo se utiliza un interruptor declaracin a considerar un nico carcter
en minscula llamadasomeCharacter :

let someCharacter: Character = "e"

switch someCharacter {

case "a", "e", "i", "o", "u":

println("\(someCharacter) is a vowel")

case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",

"n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":

println("\(someCharacter) is a consonant")

default:

println("\(someCharacter) is not a vowel or a consonant")

// Impresiones "e es una vocal"


El switch primer caso de declaracin coincide con las cinco vocales en minsculas
en el idioma Ingls.Del mismo modo, su segundo caso coincide con todas las
consonantes en ingls en minsculas.
No es prctico para escribir el resto de caracteres posibles en el marco de un switch
de caso, y por lo que este switch declaracin proporciona un default caso para
que coincida con el resto de personajes que no son vocales o consonantes. Esta
disposicin garantiza que el switch de la declaracin es exhaustiva.

79

No fallthrough Implcito
En contraste con el switch de declaraciones en C y Objective-C, switch
declaraciones en Swift no se pierdan en el fondo de cada caso y en la siguiente de forma
predeterminada. En lugar de ello, todo elconmutador de declaracin termina su
ejecucin tan pronto como la primera coincidencia interruptor se completa caso,
sin requerir una explcita break comunicado. Esto hace que el interruptor de la
declaracin ms seguro y ms fcil de usar que en C, y evita la ejecucin de ms de
un interruptor de caso por error.
NOTA
Aunque ruptura no se requiere en Swift, todava se puede utilizar
un descanso para que coincida con la declaracin y pasar por alto un caso particular,
o para salir de un caso emparejado antes de que el caso ha terminado su
ejecucin. Ver Rotura en una sentencia switch para ms detalles.
El cuerpo de cada caso debe contener al menos una sentencia ejecutable. No es vlido
para escribir el siguiente cdigo, debido a que el primer caso est vaca:

let anotherCharacter: Character = "a"

switch anotherCharacter {

case "a":

case "A":

println("The letter A")

default:

println("Not the letter A")

// Esto reportar un error en tiempo de compilacin


A diferencia de un interruptor de instruccin en C,
este interruptor declaracin no coincide con tanto "a" y"A" . Ms bien, se
informa de un error de tiempo de compilacin que el caso "a": no contiene
ninguna de las declaraciones ejecutables. Este enfoque evita fallthrough accidental de
un caso a otro, y lo convierte en cdigo ms seguro que es ms claro en su intencin.
Varias coincidencias para un solo interruptor de caso pueden estar separados por
comas, y pueden ser escritas en varias lneas si la lista es larga:

switch some value to consider {

case value 1 ,

value 2 :
statements

}
NOTA
Para optar por fallthrough comportamiento para un determinado conmutador caso,
utilice el fallthrough palabra clave, como se describe en fallthrough .

80

GAMA A JUEGO
Los valores en los switch de los casos se puede comprobar por su inclusin en un
rango. Este ejemplo utiliza rangos de nmeros para proporcionar un recuento de
lenguaje natural para los nmeros de cualquier tamao:

let count = 3_000_000_000_000

let countedThings = "stars in the Milky Way"

var naturalCount: String

switch count {

case 0:

naturalCount = "no"

case 1...3:

naturalCount = "a few"

case 4...9:

naturalCount = "several"

case 10...99:

naturalCount = "tens of"

case 100...999:

naturalCount = "hundreds of"

case 1000...999_999:

naturalCount = "thousands of"

default:

naturalCount = "millions and millions of"

println("There are \(naturalCount) \(countedThings).")

// imprime "Hay millones y millones de estrellas en la Va


Lctea."

Tuples
Puede usar tuplas para probar varios valores en el
mismo interruptor comunicado. Cada elemento de la tupla puede ser probado
contra un valor diferente o rango de valores. Como alternativa, utilice el guin bajo
(_ identificador) para adaptarse a cualquier valor posible.
El siguiente ejemplo toma una (x, y) punto, expresado como un simple tupla de
tipo (Int, Int) , y lo clasifica en el grfico que sigue el ejemplo:

let somePoint = (1, 1)

switch somePoint {

case (0, 0):

println("(0, 0) is at the origin")


81

case (_, 0):

println("(\(somePoint.0), 0) is on the x-axis")

case (0, _):

println("(0, \(somePoint.1)) is on the y-axis")

case (-2...2, -2...2):

println("(\(somePoint.0), \(somePoint.1)) is inside the box")

default:

println("(\(somePoint.0), \(somePoint.1)) is outside of the box")

// imprime "(1, 1) es dentro de la caja"


El switch de declaracin determina si el punto est en el origen (0, 0); en el eje x de
color rojo; en el eje y naranja; dentro de la caja azul de 4 por 4 centrada en el origen; o
fuera de la caja.
A diferencia de C, Swift permite mltiples switch casos a considerar el mismo valor
o valores. De hecho, el punto (0, 0) pudo igualar todos cuatro de los casos en este
ejemplo. Sin embargo, si varias coincidencias son posibles, se utiliza siempre el primer
caso a juego. El punto (0, 0) se correspondera con case (0, 0) en primer lugar, y
as todos los dems casos coincidentes sera ignorado.
Vinculaciones Valor
Un switch de caso puede unir el valor o valores de que coincide con constantes o
variables temporales, para su uso en el cuerpo de la caja. Esto se conoce como valor de
unin , ya que los valores son "unido" a las constantes temporales o variables dentro del
cuerpo de la caja.
El siguiente ejemplo toma una (x, y) punto, expresado como una tupla de tipo (Int,
Int) y lo clasifica en el grfico que sigue:

let anotherPoint = (2, 0)

switch anotherPoint {
82

case (let x, 0):

println("on the x-axis with an x value of \(x)")

case (0, let y):

println("on the y-axis with a y value of \(y)")

case let (x, y):

println("somewhere else at (\(x), \(y))")

// Imprime "en el eje x con un valor x de 2"


El switch de declaracin determina si el punto est en el eje x de color rojo, en el eje
y naranja, o en otra parte, en ninguno de eje.
Los tres switch casos declaran de marcador de posicin constantes x e y , que toman
forma temporal en los valores de una o ambas tuplas de otroPunto . El primer
caso, caso (sea x, 0) , coincide con cualquier punto con una y el valor de 0 y
asigna del punto x valor de la constante temporal x . Del mismo modo, el segundo
caso, el caso (0, dejar y) , coincide con cualquier punto con una x valor
de 0 y asigna del punto yvalor de la constante temporal y .
Una vez que las constantes temporales se declaran, pueden ser utilizados dentro de
bloque de cdigo de la carcasa. Aqu, se utilizan como abreviatura para la impresin de
los valores con el println funcin.
Tenga en cuenta que este switch de declaracin no tiene un valor
predeterminado caso. El ltimo caso,let caso (x, y) , declara una tupla de
dos constantes de marcador de posicin que pueden coincidir con cualquier valor. Como
resultado de ello, de que coincide con todos los posibles valores restantes, y
undefecto no es necesario para hacer que el caso del switch declaracin
exhaustiva.
En el ejemplo anterior, x y y son declarados como constantes con el let palabra clave,
porque no hay necesidad de modificar sus valores dentro del cuerpo de la caja. Sin
embargo, podran haber sido declaradas como variables en su lugar, con la var palabra
clave. Si esto se hubiera hecho, se habra creado una variable temporal e inicializado

83

con el valor apropiado. Cualquier cambio en esa variable slo tendran un efecto en el
cuerpo de la caja.
Where
Un interruptor de caso puede utilizar una donde clusula para evaluar
afecciones adicionales.
El ejemplo siguiente cataloga un punto en el siguiente grfico (x, y):

let yetAnotherPoint = (1, -1)

switch yetAnotherPoint {

case let (x, y) where x == y:

println("(\(x), \(y)) is on the line x == y")

case let (x, y) where x == -y:

println("(\(x), \(y)) is on the line x == -y")

case let (x, y):

println("(\(x), \(y)) is just some arbitrary point")

// imprime "(1, -1) est en la lnea x == -y"


El switch de la declaracin determina si el punto est en la lnea diagonal verde
donde x == y , en la lnea diagonal prpura donde x == -y , o ninguno.
Los tres switch casos declaran de marcador de posicin constantes x e y , que toman
forma temporal en los dos valores de tupla de yetAnotherPoint . Estas constantes
se utilizan como parte de un donde clusula, para crear un filtro dinmico. El siwtch
de caso coincide con el valor actual del punto slo si el que la condicin de la
clusula se evala como verdadera para ese valor.
Como en el ejemplo anterior, el ltimo caso coincide con todos los posibles valores
restantes, y por lo que undefecto no es necesario para hacer que el caso del
interruptor declaracin exhaustiva.

84

Declaraciones de transferencia de control


Enunciados de transferencia de control cambian el orden en que se ejecuta el cdigo,
transfiriendo el control de una sola pieza de cdigo a otro. Swift tiene cuatro enunciados
de transferencia de control:
continuar
ruptura
fallthrough
retorno
La siguen , descanso , y fallthrough declaraciones se describen a
continuacin. El retorno declaracin se describe en Funciones .
Continuar
La siguen declaracin dice un bucle para detener lo que est haciendo y empezar de
nuevo desde el comienzo de la siguiente iteracin a travs del bucle. Dice que "he
terminado con la iteracin actual del bucle" sin salir del bucle completo.
NOTA
En una de bucle con un estado y incrementador, incrementador del bucle est siendo
evaluada despus de llamar al continan comunicado. El bucle en s sigue
trabajando como de costumbre; se omite slo el cdigo dentro del cuerpo del bucle.
El ejemplo siguiente elimina todas las vocales y los espacios de una cadena en
minsculas para crear una frase crptica rompecabezas:

let puzzleInput = "great minds think alike"

var puzzleOutput = ""

for character in puzzleInput {

switch character {

case "a", "e", "i", "o", "u", " ":

continue

default:

puzzleOutput.append(character)

println(puzzleOutput)

// prints "grtmndsthnklk"
El cdigo anterior llama al continue palabra clave cada vez que coincide con una
vocal o un espacio, provocando la iteracin actual del bucle a fin de inmediato y para
saltar directamente a la comienzo de la siguiente iteracin. Este comportamiento
permite que el bloque de interruptores para que coincida (e ignorar) slo los caracteres
de vocales y espaciales, en lugar de exigir el bloque para que coincida con cada
personaje que debe quedar impreso.
Break
La break declaracin finaliza la ejecucin de todo un estado de flujo de control
inmediatamente. La break declaracin se puede utilizar dentro de un switch o una

85

sentencia de bucle cuando se quiere terminar la ejecucin del switch de declaracin


o bucle antes de lo que sera el caso.
Rotura en una Declaracin Loop
Cuando se utiliza dentro de una sentencia de bucle, break termina la ejecucin del
bucle inmediato, y transfiere el control a la primera lnea de cdigo despus de llave de
cierre del bucle ( } ). No se ejecuta el cdigo ms lejos de la iteracin actual del bucle,
y no habr ms iteraciones del bucle se inician.
Rotura en una sentencia switch
Cuando se utiliza dentro de un switch declaracin, break hace que el switch
de declaracin para terminar su ejecucin de inmediato, y para transferir el control a la
primera lnea de cdigo despus de que el switch de llave de cierre de declaracin
( } ).
Este comportamiento puede ser utilizado para emparejar y pasar por alto uno o ms
casos en un switchcase. Porque de Swift swicht declaracin es exhaustiva y no
permite que los casos vacos, a veces es necesario hacer coincidir deliberadamente e
ignorar un caso con el fin de hacer que sus intenciones explcitas. Usted puede hacer
esto escribiendo la ruptura declaracin como todo el cuerpo de la caja desea
ignorar. Cuando este caso se corresponde con el switch de la declaracin,
la ruptura declaracin dentro de la caja termina el switch de la ejecucin de la
declaracin de inmediato.
NOTA
Un switch de caso que slo contiene un comentario es reportado como un error en
tiempo de compilacin. Los comentarios no son declaraciones y no causan un switch
de caso para ser ignorada.Utilice siempre una ruptura declaracin de ignorar
un switch de caso.
El siguiente ejemplo se conecta un Character value y determina si representa un
smbolo nmero en uno de los cuatro idiomas. Mltiples valores estn cubiertos en un
solo switch caso de brevedad:

let numberSymbol: Character = "" // Simplified Chinese for the number 3

var possibleIntegerValue: Int?

switch numberSymbol {

case "1", "", "", " ":

possibleIntegerValue = 1

case "2", "", "", " ":

possibleIntegerValue = 2

case "3", "", "", " ":

possibleIntegerValue = 3

case "4", "", "", " ":

possibleIntegerValue = 4

default:
86

break

if let integerValue = possibleIntegerValue {

println("The integer value of \(numberSymbol) is \(integerValue).")

} else {

println("An integer value could not be found for \(numberSymbol).")

// imprime "El valor entero de es 3"


En este ejemplo se comprueba numberSymbol para determinar si se trata de un,
rabe, chino, tailands o smbolo latino para los nmeros 1 a 4 . Si se encuentra una
coincidencia, uno de los switch de casos de declaracin establece una
opcin Int? variable llamada possibleIntegerValue a un valor entero
correspondiente.
Despus de la sentencia switch completa su ejecucin, el ejemplo se utiliza opcional
vinculante para determinar si se ha encontrado un
valor. El possibleIntegerValue variable tiene un valor inicial implcito
decero en virtud de ser un tipo opcional, por lo que la opcin de unin tendr xito
slo si possibleIntegerValuese establece en un valor real por uno de
los interruptor primeros cuatro casos de declaracin.
No es prctico enumerar todos los posibles caracteres valor en el ejemplo anterior,
por lo que un default case ofrece un cajn de sastre para cualquier carcter que no
se corresponden. Este default case no tiene que realizar ninguna accin, por lo que
se escribe con una sola ruptura declaracin como su cuerpo. Tan pronto como
el valor predeterminado se corresponde caso, la break declaracin termina
el switch de ejecucin de sentencia, y la ejecucin de cdigo contina desde el if
let comunicado.
Fallthrough
Sentencias switch en Swift no se pierdan en el fondo de cada caso y en la siguiente. En
cambio, toda la instruccin switch completa su ejecucin tan pronto como se complete
el primer caso a juego. Por el contrario, C que requiere insertar una
explcita ruptura declaracin al final de cada interruptor de caja para prevenir
fallthrough. Evitar fallthrough defecto significa que
Swift interruptor declaraciones son mucho ms concisa y predecible que sus
contrapartes en C, y as evitan la ejecucin de mltiples interruptores casos por
error.
Si realmente necesita comportamiento fallthrough estilo C, se puede optar por este
comportamiento en una base de caso por caso con el fallthrough palabra clave. El
ejemplo siguiente utiliza fallthrough para crear una descripcin textual de un
nmero:

let integerToDescribe = 5

var description = "The number \(integerToDescribe) is"

switch integerToDescribe {
87

case 2, 3, 5, 7, 11, 13, 17, 19:

description += " a prime number, and also"

fallthrough

default:

description += " an integer."

println(description)

// imprime "El nmero 5 es un nmero primo, y tambin un


nmero entero."
En este ejemplo se declara una nueva cuerda variable llamada Descripcin y le
asigna un valor inicial. La funcin se considera el valor
de integerToDescribe utilizando un interruptor comunicado. Si el valor
deintegerToDescribe es uno de los nmeros primos en la lista, la funcin anexa
texto al final de la descripcin , observar que el nmero es primo. A continuacin,
utiliza la fallthrough palabra clave para "caer en" el defaultcaso
tambin. El valor predeterminado caso aade un poco de texto extra al final de
la descripcin, y elinterruptor de declaracin es completa.
Si el valor de integerToDescribe es no en la lista de los nmeros primos
conocidos, que no se corresponde con el primer interruptor de caso en
absoluto. No hay otros casos especficos, y as integerToDescribe es igualada por
el cajn de sastre default caso.
Despus de que el interruptor de declaracin ha finalizado la ejecucin, la
descripcin que hace el nmero se imprime utilizando la println funcin. En este
ejemplo, el nmero 5 se identifica correctamente como un nmero primo.
NOTA
El fallthrough palabra clave no comprueba las condiciones del caso para
el interruptor de caso que hace que la ejecucin caer. El fallthrough palabra
clave simplemente hace que la ejecucin de cdigo para ir a las sentencias dentro del
siguiente caso (o default bloque caso), como en el estndar de
C interruptorcomportamiento comunicado.

Declaraciones Etiquetada
Puede anidar bucles y cambiar estados dentro de otros bucles y cambiar estados en
Swift para crear estructuras de flujo de control complejos. Sin embargo, los lazos
y cambiar los estados pueden utilizar tanto laruptura declaracin al finalizar su
ejecucin antes de tiempo. Por lo tanto, a veces es til para ser explcito acerca de qu
lazo o interruptor declaracin quieres un descanso declaracin para
terminar. Del mismo modo, si usted tiene mltiples bucles anidados, puede ser til para
ser explcito acerca de lo que el buclecontinuar declaracin debera afectar.
Para alcanzar estos objetivos, puede marcar una sentencia de bucle
o cambiar declaracin con una etiqueta de declaracin , y el uso de esta etiqueta con
la ruptura declaracin o continuar declaracin para terminar o continuar la
ejecucin de la sentencia etiquetada.

88

Una declaracin de la etiqueta se indica mediante la colocacin de una etiqueta en la


misma lnea que la palabra clave introductor de la declaracin, seguido de dos
puntos. He aqu un ejemplo de esta sintaxis para un tiempo de bucle, aunque el
principio es el mismo para todos los bucles y los interruptores declaraciones:
label name : while condition {

statements

}
El ejemplo siguiente utiliza la ruptura y seguir las declaraciones con la
etiqueta mientras bucle de una versin adaptada de la Serpientes y Escaleras juego
que vimos anteriormente en este captulo. Esta vez, el juego tiene una regla adicional:
Para ganar, debes aterrizar exactamente en la plaza 25.
Si una tirada de dados particular, le tomara ms all de la plaza 25, debe tirar de nuevo
hasta que sacas el nmero exacto necesario para aterrizar en la plaza 25.
El tablero de juego es el mismo que antes:


Los valores de finalSquare , tablero , cuadrados , y diceRoll se
inicializan en la misma forma que antes:

let finalSquare = 25

var board = [Int](count: finalSquare + 1, repeatedValue: 0)

board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02

board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08

var square = 0

var diceRoll = 0
Esta versin del juego utiliza un tiempo de bucle y un interruptor
de declaracin para implementar la lgica del juego. El tiempo de bucle tiene una
etiqueta llamada declaracin gameLoop , para indicar que es el bucle principal del
juego para el juego de Serpientes y Escaleras.

89

El while loop que la condicin del bucle es mientras cuadrado =


finalSquare! , para reflejar que debe aterrizar exactamente en la plaza 25:

gameLoop: while square != finalSquare {

if ++diceRoll == 7 { diceRoll = 1 }

switch square + diceRoll {

case finalSquare:

// diceRoll will move us to the final square, so the game is over

break gameLoop

case let newSquare where newSquare > finalSquare:

// diceRoll will move us beyond the final square, so roll again

continue gameLoop

default:

// this is a valid move, so find out its effect

square += diceRoll

square += board[square]

println("Game over!")
Los dados se enrolla en el inicio de cada bucle. En lugar de mover el reproductor
inmediatamente, uninterruptor de sentencia se utiliza para tener en cuenta el
resultado de la medida, y para trabajar si se permite que el movimiento:
Si la tirada de dados se mover el jugador a la plaza final, el juego ha
terminado. Las vacaciones de gameLoop transferencias sentencia de control
a la primera lnea de cdigo fuera del tiempo de bucle, que termina el juego.
Si la tirada de dados se mover el jugador ms all de la plaza final, el movimiento
no es vlida, y el jugador tiene que tirar de nuevo. El continuar
gameLoop declaracin termina la actual , mientras que la iteracin de bucle
y comienza la siguiente iteracin del bucle.
En todos los dems casos, la tirada es un movimiento vlido. El jugador se mueve
hacia adelante pordiceRoll cuadrados y los controles de juego de lgica para
cualquier juego de la oca. El bucle se termina y el control vuelve al mismo
tiempo condicin para decidir si se requiere otro turno.
NOTA
Si la break afirmacin anterior no utiliz el gameLoop etiqueta, sera romper con
el interruptor de la declaracin, no el tiempo comunicado. Usando
el gameLoop etiqueta deja claro que controlar declaracin debe ser terminado.
Tenga en cuenta tambin que no es estrictamente necesario utilizar
el gameLoop etiqueta cuando llame acontinuar gameLoop para saltar a la
siguiente iteracin del bucle. Slo hay un bucle en el juego, y lo que no hay ambigedad
en cuanto a que el bucle continan declaracin afectar. Sin embargo, no hay ningn
dao en el uso de la gameLoop etiqueta con el continuar comunicado. Si lo hace,

90

es consistente con el uso de la etiqueta junto a la ruptura declaracin, y ayuda a que


la lgica del juego ms claro de leer y entender.

Funciones
En esta pgina
Funciones son trozos independientes de cdigo que realizan una tarea especfica. Usted
da una funcin de un nombre que identifique lo que hace, y este nombre se usa para
"llamar" la funcin para llevar a cabo su tarea cuando es necesario.
Sintaxis de la funcin unificada de Swift es lo suficientemente flexible como para
expresar cualquier cosa, desde una funcin de C-estilo simple, sin nombres de
parmetros a un mtodo-al estilo de Objective C compleja con nombres de parmetros
locales y externos para cada parmetro. Los parmetros se pueden proporcionar valores
predeterminados para simplificar las llamadas a funciones y pueden ser pasados como
in-out parmetros, que modifican una variable pasada una vez que la funcin ha
terminado su ejecucin.
Cada funcin en Swift tiene un tipo, que consiste en los tipos de parmetros de la
funcin y el tipo de retorno.Usted puede utilizar este tipo como cualquier otro tipo de
Swift, que hace que sea fcil pasar funciones como parmetros a otras funciones, y para
volver funciones de funciones. Las funciones tambin pueden ser escritos dentro de
otras funciones para encapsular funcionalidad til dentro de un mbito de la funcin
anidada.
La definicin y la Llamada de funciones
Cuando se define una funcin, puede opcionalmente especificar uno o ms nombrado,
valores escritos que la funcin toma como entrada (conocida como parmetros ), y / o
un tipo de valor que la funcin va a pasar de nuevo como salida cuando se hace
(conocidos como su tipo de retorno ).
Cada funcin tiene un nombre de funcin , que describe la tarea que realiza la
funcin. Para utilizar una funcin, "llama" esa funcin con su nombre y lo pasa valores
de entrada (conocida como argumentos ) que coinciden con los tipos de parmetros de
la funcin. Los argumentos de una funcin siempre se deben proporcionar en el mismo
orden que la lista de parmetros de la funcin.
La funcin en el ejemplo siguiente se llama sayHello , porque eso es lo que hace-que
toma el nombre de una persona como entrada y devuelve un saludo para esa
persona. Para lograr esto, se define un parmetro de entrada de cadena de valor
llamada PersonName -y un tipo de retorno de la Cadena , que contendr un saludo
para esa persona:

func sayHello(personName: String) -> String {

let greeting = "Hello, " + personName + "!"

return greeting

}
Toda esta informacin se rueda para arriba en funcin de la definicin , que se prefija
con la func palabra clave. Usted indica el tipo de la funcin de retorno con la flecha de

91

retorno -> (un guin seguido de un soporte en ngulo recto), que es seguido por el
nombre del tipo de volver.
La definicin describe lo que hace la funcin, lo que espera recibir, y lo devuelve
cuando se hace. La definicin hace que sea fcil para la funcin a ser llamada sin
ambigedades de su cdigo en otros lugares:

println(sayHello("Anna"))

// prints "Hello, Anna!"

println(sayHello("Brian"))

// prints "Hello, Brian!"


Se llama a la sayHello funcin pasndole una cuerda valor argumento entre
parntesis, como sayHello ("Anna") . Debido a que la funcin devuelve
una Cadena de Valor, sayHello se puede envolver en una llamada a
la println funcin para imprimir esa cadena y ver su valor de retorno, como se
muestra arriba.
El cuerpo de la sayHello funcin comienza definiendo una nueva Cadena constante
llamada de felicitacin y establecindola en un mensaje de saludo simple
para PersonName . Este saludo se pasa entonces de nuevo fuera de la funcin usando
el retorno de palabras clave. Tan pronto como saludo de retorno se llama, la
funcin termina su ejecucin y devuelve el valor actual de saludo .
Usted puede llamar al sayHello funcin varias veces con diferentes valores de
entrada. El ejemplo anterior muestra lo que sucede si se llama con un valor de entrada
de "Anna" , y un valor de entrada de "Brian" . La funcin devuelve un saludo a
medida en cada caso.
Para simplificar el cuerpo de esta funcin, se combinan la creacin del mensaje y la
sentencia de retorno en una sola lnea:

func sayHelloAgain(personName: String) -> String {

return "Hello again, " + personName + "!"

println(sayHelloAgain("Anna"))

// prints "Hello again, Anna!"

Parmetros de funciones y valores de retorno


Parmetros de la funcin y los valores de retorno son extremadamente flexibles en
Swift. Se puede definir cualquier cosa, desde una funcin de utilidad simple con un solo
parmetro sin nombre de una funcin compleja con nombres de parmetros expresivos
y diferentes opciones de parmetros.
Parmetros de entrada mltiple
Las funciones pueden tener mltiples parmetros de entrada, que se escriben entre
parntesis de la funcin, separados por comas.
Esta funcin toma un comienzo y un ndice final para un rango medio abierta, y trabaja
cuntos elementos de la gama contiene:

func halfOpenRangeLength(start: Int, end: Int) -> Int {


92

return end - start

println(halfOpenRangeLength(1, 10))

// prints "9"

Funciones sin parmetros


Las funciones no son necesarias para definir los parmetros de entrada. He aqu una
funcin sin parmetros de entrada, que siempre devuelve la misma cuerda mensaje
cada vez que se llama:

func sayHelloWorld() -> String {

return "hello, world"

println(sayHelloWorld())

// prints "hello, world"


La definicin de una funcin an necesita parntesis despus del nombre de la funcin,
a pesar de que no toma ningn parmetro. El nombre de la funcin tambin es seguido
por un par de parntesis vaco cuando se invoca la funcin.
Funciones Sin Valores devueltos
Las funciones no son necesarias para definir un tipo de retorno. Aqu hay una versin de
la sayHello funcin, llamada sayGoodbye , que imprime su propia Cadena de
valor en lugar de devolverlo:

func sayGoodbye(personName: String) {

println("Goodbye, \(personName)!")

sayGoodbye("Dave")

// prints "Goodbye, Dave!"


Debido a que no tiene que devolver un valor, la definicin de la funcin no incluye la
flecha de retorno ( -> ) o un tipo de retorno.
NOTA
En sentido estricto, la sayGoodbye funcin no todava devuelve un valor, a pesar de
que hay valor de retorno se define. Funciones sin un tipo de retorno definido devuelven
un valor especial de tipo Vaco . Esto es simplemente una tupla vaca, en efecto, una
tupla con cero elementos, que puede escribirse como () .
El valor de retorno de una funcin puede ser ignorada cuando se le llama:

func printAndCount(stringToPrint: String) -> Int {

println(stringToPrint)

return countElements(stringToPrint)

func printWithoutCounting(stringToPrint: String) {


93

printAndCount(stringToPrint)

printAndCount("hello, world")

// prints "hello, world" and returns a value of 12

printWithoutCounting("hello, world")

// imprime "hola, mundo", pero no devuelve un valor


La primera funcin, printAndCount , imprime una cadena y, a continuacin,
devuelve su recuento de caracteres como un int . La segunda
funcin, printWithoutCounting , llama a la primera funcin, pero no tiene en
cuenta su valor de retorno. Cuando la segunda funcin es llamada, el mensaje sigue
siendo impreso por la primera funcin, pero el valor devuelto no se utiliza.
NOTA
Los valores de retorno pueden ser ignorados, pero una funcin que dice que va a
devolver un valor siempre debe hacerlo. Una funcin con un tipo de retorno definido no
puede permitir que el control se le caiga de la parte inferior de la funcin sin devolver
un valor, y tratar de hacerlo resultar en un error en tiempo de compilacin.
Funciones con valores de retorno mltiples
Puede utilizar un tipo tupla como el tipo de cambio de una funcin para devolver varios
valores como parte del valor de retorno de un compuesto.
El ejemplo siguiente define una funcin llamada MinMax , que encuentra los nmeros
mayor y menor de una gran variedad de Int valores:

func minMax(array: [Int]) -> (min: Int, max: Int) {

var currentMin = array[0]

var currentMax = array[0]

for value in array[1..<array.count] {

if value < currentMin {

currentMin = value

} else if value > currentMax {

currentMax = value

return (currentMin, currentMax)

}
El MinMax funcin devuelve una tupla que contiene dos Int valores. Estos valores
estn etiquetados min y maxpara que puedan ser accedidos por su nombre cuando se
consulta el valor devuelto por la funcin.
El cuerpo de la MinMax funcin inicia estableciendo dos variables de trabajo
llamados currentMin y currentMaxal valor del primer nmero entero de la
matriz. La funcin entonces itera sobre los valores restantes de la matriz y comprueba
cada valor para ver si es menor o mayor que los valores

94

de currentMin y currentMaxrespectivamente. Por ltimo, los valores mnimos y


mximos generales se devuelven como una tupla de dosInt valores.
Debido a que los valores de miembro de la tupla se nombran como parte de tipo de
retorno de la funcin, se puede acceder con la sintaxis con punto para recuperar los
valores mximo y mnimo y encontrado:

let bounds = minMax([8, -6, 2, 109, 3, 71])

println("min is \(bounds.min) and max is \(bounds.max)")

// prints "min is -6 and max is 109"


Tenga en cuenta que los miembros de la tupla no necesitan ser identificado en el punto
que la tupla se devuelve desde la funcin, debido a que sus nombres ya estn
especificados como parte del tipo de retorno de la funcin.
Opcional Tipos Tuple Retorno
Si el tipo de tupla que ser devuelto de una funcin tiene el potencial de tener "ningn
valor" para toda la tupla, se puede usar un opcional tipo de retorno tupla para reflejar el
hecho de que toda la tupla puede ser nula .Usted escribe un tipo de retorno tupla
opcional colocando un signo de interrogacin despus del parntesis de cierre del tipo
tupla, como (Int, Int)? o (String, Int, Bool)? .
NOTA
Un tipo de tupla opcional tal como (Int, Int)? es diferente de una tupla que
contiene tipos opcionales, tales como (Int Int ?,?) . Con un tipo de tupla
opcional, toda la tupla es opcional, no slo cada valor individual dentro de la tupla.
El MinMax funcin anterior devuelve una tupla que contiene dos Int valores. Sin
embargo, la funcin no realiza ninguna comprobacin de seguridad en la matriz que se
pasa. Si la matriz argumento contiene una matriz, es decir, una matriz con un
vaco conteo de 0 -el MinMax funcin, como se ha definido anteriormente, se
activar un error de ejecucin cuando se intenta acceder a la matriz [0] .
Para hacer frente a este escenario "vaco matriz" de forma segura, escribir
la MinMax funcin con un tipo de retorno tupla opcional y devolver un valor
de cero cuando la matriz est vaca:

func minMax(array: [Int]) -> (min: Int, max: Int)? {

if array.isEmpty { return nil }

var currentMin = array[0]

var currentMax = array[0]

for value in array[1..<array.count] {

if value < currentMin {

currentMin = value

} else if value > currentMax {

currentMax = value

return (currentMin, currentMax)

95

Usted puede utilizar opcional vinculante para comprobar si esta versin


del MinMax funcin devuelve un valor tupla real o nula :

if let bounds = minMax([8, -6, 2, 109, 3, 71]) {

println("min is \(bounds.min) and max is \(bounds.max)")

// prints "min is -6 and max is 109"

Parmetro Funcin Nombres


Todas las funciones anteriores definen nombres de los parmetros de sus parmetros:

func someFunction(externalParameterName localParameterName: Int) {

// function body goes here, and can use localParameterName

// to refer to the argument value for that parameter

}
Sin embargo, estos nombres de parmetros slo se utilizan dentro del cuerpo de la
funcin de s mismo, y no se pueden utilizar cuando se llama a la funcin. Este tipo de
nombres de los parmetros se conocen comonombres de parmetros locales , ya que
slo estn disponibles para su uso dentro del cuerpo de la funcin.
Nombres de parmetros externos
A veces es til para nombrar cada parmetro cuando se llama a una funcin, para
indicar el propsito de cada argumento se pasa a la funcin.
Si desea que los usuarios de su funcin de proporcionar los nombres de parmetros que
llama a su funcin, definir un nombre de parmetro externo para cada parmetro,
adems del nombre del parmetro local. Usted escribe un nombre de parmetro externo
antes del nombre de parmetro local que da soporte, separadas por un espacio:

func someFunction(externalParameterName localParameterName: Int) {

// Cuerpo de la funcin va aqu, y se puede utilizar


localParameterName

// Para referirse al valor del argumento para ese parmetro

}
NOTA
Si proporciona un nombre de parmetro externo para un parmetro, el nombre externo
debe siempre ser utilizada cuando se llama a la funcin.
Como ejemplo, considere la siguiente funcin, que se une a dos cadenas mediante la
insercin de un tercer "carpintero" cuerda entre ellos:

func join(s1: String, s2: String, joiner: String) -> String {

return s1 + joiner + s2

}
Cuando se llama a esta funcin, el propsito de las tres cadenas que se pasa a la funcin
es clara:

join("hello", "world", ", ")

// Devuelve "hola, mundo"


96

Para el propsito de estas Cuerda valores ms claros, definir nombres de los


parmetros externos para cadaunen parmetro de la funcin:

func join(string s1: String, toString s2: String, withJoiner joiner: String)

-> String {

return s1 + joiner + s2

}
In En esta versin de la join a la funcin, el primer parmetro tiene un nombre
externo de cadena y un nombre local de s1 ; el segundo parmetro tiene un nombre
externo de toString y un nombre local de s2 ; y el tercer parmetro tiene un nombre
externo de withJoiner y un nombre local de joiner.
Ahora puede utilizar estos nombres de parmetros externos para llamar a la funcin sin
ambigedades:

join(string: "hello", toString: "world", withJoiner: ", ")

// Devuelve "hola, mundo"


El uso de nombres de parmetros externos permite a esta segunda versin de
la unirse a la funcin que se llamar en una frase-como forma expresiva los usuarios
de la funcin, sin dejar de ofrecer un cuerpo de funcin que sea legible y clara en su
intencin.
NOTA
Considere el uso de nombres de parmetros externos cada vez que el propsito de los
argumentos de una funcin sera claro para alguien que lee su cdigo por primera
vez. No es necesario especificar los nombres de parmetros externos si el propsito de
cada parmetro es unvoco cuando se invoca la funcin.
Taquigrafa externos nombres de los parmetros
Si desea proporcionar un nombre de parmetro externo para un parmetro de la funcin,
y el nombre de parmetro local ya es un nombre apropiado para usar, no es necesario
escribir el mismo nombre dos veces para ese parmetro. En su lugar, escribir el nombre
de una vez, y como prefijo el nombre con un smbolo de almohadilla ( # ). Esto le dice a
Swift a utilizar ese nombre como nombre de parmetro local y el nombre del parmetro
externo.
Este ejemplo define una funcin llamada containsCharacter , que define los
nombres de parmetros externos para sus dos parmetros mediante la colocacin de un
smbolo de hash antes de que sus nombres de parmetros locales:

func containsCharacter(#string: String, #characterToFind: Character) -> Bool {

for character in string {

if character == characterToFind {

return true

return false

97

Eleccin de esta funcin de nombres de parmetros hace que para un cuerpo de la


funcin de lectura clara, permitiendo al mismo tiempo la funcin de ser llamado sin
ambigedad:

let containsAVee = containsCharacter(string: "aardvark", characterToFind: "v")

// containsAVee equals true, because "aardvark" contains a "v"

Valores de los parmetros por defecto


Puede definir un valor por defecto para cualquier parmetro como parte de la definicin
de una funcin. Si se define un valor por defecto, se puede omitir este parmetro cuando
se llama a la funcin.
NOTA
Coloca los parmetros con valores por defecto al final de la lista de parmetros de una
funcin. Esto garantiza que todas las llamadas a la funcin utilizan el mismo orden de
sus argumentos no predeterminados, y deja en claro que la misma funcin se est
llamando en cada caso.
Aqu hay una versin de la unirse funcin desde antes, lo que proporciona un valor
predeterminado para sucarpintero de parmetro:

func join(string s1: String, toString s2: String,

withJoiner joiner: String = " ") -> String {

return s1 + joiner + s2

}
Si un valor de cadena para el carpintero se proporciona cuando el unirse a la
funcin se llama, que valor de cadena se utiliza para unir las dos cadenas juntas, como
antes:

join(string: "hello", toString: "world", withJoiner: "-")

// returns "hello-world"
Sin embargo, si no hay ningn valor de carpintero se proporciona cuando se invoca
la funcin, el valor por defecto de un nico espacio ( "" ) se utiliza en su lugar:

join(string: "hello", toString: "world")

// returns "hello world"

Nombres externas para parmetros con valores predeterminados


En la mayora de los casos, es til para proporcionar (y por lo tanto requieren) un
nombre externo para cualquier parmetro con un valor por defecto. Esto asegura que el
argumento a favor de que el parmetro es claro en su propsito si se proporciona un
valor cuando la funcin es llamada.
Para hacer este proceso ms fcil, Swift proporciona un nombre externo automtico
para cualquier parmetro que tiene un valor predeterminado. El nombre externo
automtico es el mismo que el nombre local, como si hubiera escrito un smbolo de
hash antes de que el nombre local en el cdigo.
Aqu hay una versin de la unirse a la funcin de antes, que no proporciona los
nombres externos para cualquiera de sus parmetros, pero todava proporciona un valor
predeterminado para su carpintero deparmetro:

98

func join(s1: String, s2: String, joiner: String = " ") -> String {

return s1 + joiner + s2

}
En este caso, Swift proporciona automticamente un nombre de parmetro externo para
el carpinteroparmetro. Por tanto, el nombre externo se debe proporcionar al llamar
a la funcin, por lo que el propsito del parmetro claro e inequvoco:

join("hello", "world", joiner: "-")

// returns "hello-world"
NOTA
Usted puede optar por salir de este comportamiento escribiendo un guin bajo ( _ ) en
lugar de un nombre externo explcito al definir el parmetro. Sin embargo, se prefieren
los nombres externos para parmetros con valores por defecto.
Parmetros variadic
Un parmetro variadic acepta cero o ms valores de un tipo especificado. Se utiliza un
parmetro variadic para especificar que el parmetro se puede pasar un nmero variable
de valores de entrada cuando se llama la funcin. Escribir parmetros variadic
insertando tres personajes de poca ( ... ) despus del nombre de tipo de parmetro.
Los valores que se pasan a un parmetro variadic se ponen a disposicin en el cuerpo de
la funcin como una matriz del tipo apropiado. Por ejemplo, un parmetro variadic con
un nombre de nmeros y un tipo dedoble ... se pone a disposicin dentro del
cuerpo de la funcin como una matriz constante llama nmeros de tipo [Doble] .
El siguiente ejemplo calcula la media aritmtica (tambin conocida como la media )
para obtener una lista de nmeros de cualquier longitud:

func arithmeticMean(numbers: Double...) -> Double {

var total: Double = 0

for number in numbers {

total += number

return total / Double(numbers.count)

arithmeticMean(1, 2, 3, 4, 5)

// Devuelve 3.0, que es la media aritmtica de estos cinco


nmeros

arithmeticMean ( 3 , 8,25 , 18,75 )

// Devuelve 10,0, que es la media aritmtica de estos tres


nmeros
NOTA
Una funcin puede tener como mximo un parmetro variadic, y siempre debe aparecer
ltimo en la lista de parmetros, para evitar la ambigedad cuando se llama a la funcin
con varios parmetros.

99

Si su funcin tiene uno o ms parmetros con un valor por defecto, y tambin tiene un
parmetro variadic, coloque el parmetro variadic despus de todos los parmetros en
mora al final de la lista.
Parmetros Constante y Variable
Parmetros de la funcin son constantes por defecto. Tratar de cambiar el valor de un
parmetro de la funcin desde dentro del cuerpo de que los resultados de la funcin en
un error en tiempo de compilacin.Esto significa que usted no puede cambiar el valor de
un parmetro por error.
Sin embargo, a veces es til para una funcin que tiene una variable de copia del valor
de un parmetro para trabajar. Usted puede evitar definir una nueva variable a s mismo
dentro de la funcin mediante la especificacin de uno o ms parmetros
como parmetros variables en lugar. Los parmetros variables estn disponibles como
variables y no como constantes, y dan una nueva copia modificable del valor del
parmetro de la funcin de trabajar.
Definir parmetros variables con el prefijo del nombre del parmetro con la palabra
clave var :

func alignRight(var string: String, count: Int, pad: Character) -> String {

let amountToPad = count - countElements(string)

if amountToPad < 1 {

return string

let padString = String(pad)

for _ in 1...amountToPad {

string = padString + string

return string

let originalString = "hello"

let paddedString = alignRight(originalString, 10, "-")

// PaddedString es igual a "----- hola"

// OriginalString sigue siendo igual a "hola"


Este ejemplo define una nueva funcin llamada alignright , que alinea una cadena
de entrada hasta el borde derecho de una cadena de salida ms larga. Cualquier espacio
de la izquierda se llena con un carcter de relleno especificado. En este ejemplo, la
cadena "hello" se convierte en la cadena "----- hola" .
El alignright funcin define el parmetro de entrada de cadena a ser un
parmetro variable. Esto significa quela cadena ya est disponible como una
variable local, inicializado con el valor de cadena que se pasa-in, y puede ser
manipulado dentro del cuerpo de la funcin.
La funcin comienza por la elaboracin de cuntos caracteres deben agregarse a la
izquierda de la cadenacon el fin de derecha alinearlo dentro de la cadena

100

global. Este valor se almacena en una constante local llamado amountToPad . Si no


se necesita relleno (es decir, si amountToPad es menor que 1 ), la funcin
simplemente devuelve el valor de entrada de cadena sin ningn relleno.
De lo contrario, la funcin crea un nuevo temporal de cuerda constante
llamada padString , inicializado con laalmohadilla de carcter, y
aade amountToPad copias de padString a la izquierda de la cadena
existente. (ACadena de valor no se puede aadir a un personaje valor, por lo que
el padString constante se utiliza para asegurarse de que ambos lados de
la + operador son de Cuerda valores.)
NOTA
Los cambios que realice en un parmetro variable no persisten ms all del final de cada
llamada a la funcin, y no son visibles fuera del cuerpo de la funcin. El parmetro
variable slo existe durante toda la vida de esa llamada a la funcin.
In-Out Parmetros
Los parmetros variables, como se describe anteriormente, slo pueden ser modificados
dentro de la propia funcin. Si desea una funcin para modificar el valor de un
parmetro, y quiere que esos cambios persisten despus de la llamada a la funcin ha
terminado, defina este parmetro como un parmetro in-out en su lugar.
Usted escribe un parmetro en-cabo colocando la inout palabra clave en el inicio de
su definicin de parmetros. Un parmetro de entrada-salida tiene un valor que se
pasa en a la funcin, es modificada por la funcin, y se pasa de nuevo fuera de la
funcin para reemplazar el valor original.
Slo puede pasar una variable como argumento para un parmetro in-out. No se puede
pasar una constante o un valor literal como el argumento, porque las constantes y
literales no pueden ser modificados. Usted coloca un signo ( y ) directamente antes del
nombre de una variable cuando se pasa como argumento a un parmetro inout, para
indicar que se puede modificar con la funcin.
NOTA
En-hacia fuera parmetros no pueden tener valores por defecto, y los parmetros
variadic no pueden ser marcados como inout . Si marca un parmetro como inout ,
no puede tambin ser marcado como var odejar .
He aqu un ejemplo de una funcin llamada swapTwoInts , que tiene dos in-out
parmetros enteros llaman unay b :

func swapTwoInts(inout a: Int, inout b: Int) {

let temporaryA = a

a=b

b = temporaryA

}
El swapTwoInts funcin simplemente intercambia el valor de b en una , y el valor
de una en b . La funcin realiza este intercambio almacenando el valor de una en una
constante temporal llamada temporaryA , asignando el valor de b a una , y luego
asignar temporaryA a b .
Usted puede llamar al swapTwoInts funcin con dos variables de tipo int para
intercambiar sus valores. Tenga en cuenta que los nombres

101

de someInt y anotherInt son prefijadas con un smbolo de unin cuando se pasan


a la swapTwoInts funcin:

var someInt = 3

var anotherInt = 107

swapTwoInts(&someInt, &anotherInt)

println("someInt is now \(someInt), and anotherInt is now \(anotherInt)")

// Impresiones "someInt es ahora 107, y anotherInt es ahora


3"
El ejemplo anterior muestra que los valores originales
de someInt y anotherInt son modificados por elswapTwoInts funcin, a pesar
de que fueron definidos originalmente fuera de la funcin.
NOTA
En Salida parmetros no son los mismos que devolviendo un valor de una
funcin. El swapTwoInts ejemplo anterior no define un tipo de retorno o devuelve un
valor, pero todava modifica los valores de someInt yanotherInt . En-hacia fuera
parmetros son una forma alternativa para una funcin tenga efecto fuera del alcance de
su cuerpo de la funcin.
Tipos de funciones
Cada funcin tiene un determinado tipo de funcin , integrada por los tipos de
parmetros y el tipo de retorno de la funcin.
Por ejemplo:

func addTwoInts(a: Int, b: Int) -> Int {

return a + b

func multiplyTwoInts(a: Int, b: Int) -> Int {

return a * b

}
Este ejemplo define dos funciones matemticas simples
llamados addTwoInts y multiplyTwoInts . Estas funciones cada toman
dos Int valores y devuelven un int valor, que es el resultado de realizar una
operacin matemtica apropiada.
El tipo de ambas de estas funciones es (Int, Int) -> Int . Esto puede leerse
como:
"Un tipo de funcin que tiene dos parmetros, tanto de tipo int , y que devuelve un
valor de tipo int . "
He aqu otro ejemplo, para una funcin sin parmetros o valor de retorno:

func printHelloWorld() {

println("hello, world")

}
El tipo de esta funcin es () -> () , o "una funcin que no tiene parmetros y
devuelve vaco . "Funciones que no se especifique un valor de retorno siempre
devuelven vaco , lo que equivale a una tupla vaca en Swift, se muestra como () .

102

Uso de tipos de funcin


Utilice tipos de funciones al igual que cualquier otro tipo de Swift. Por ejemplo, puede
definir una constante o variable a ser de un tipo de funcin y asignar una funcin
adecuada a esa variable:
var mathFunction : ( Int , Int ) -> Int = addTwoInts
Esto puede leerse como:
"Definir una variable llamada mathFunction , que tiene un tipo de 'una funcin que
toma dos Int valores y devuelve un int valor. ' Establezca esta nueva variable para
hacer referencia a la funcin llamada addTwoInts".
El addTwoInts funcin tiene el mismo tipo que el mathFunction variables, por lo
que esta asignacin se permite por tipo ortogrfico de Swift.
Ahora puede llamar a la funcin asignada con el nombre mathFunction :

// Impresiones "Resultado: 5"


Una funcin diferente con el mismo tipo de juego puede ser asignado a la misma
variable, de la misma manera como para los tipos de no funcionamiento:

mathFunction = multiplyTwoInts

println("Result: \(mathFunction(2, 3))")

// Impresiones "Resultado: 6"


Al igual que con cualquier otro tipo, se puede dejar en manos de Swift para inferir el
tipo de funcin cuando se asigna una funcin a una constante o variable:

println("Result: \(mathFunction(2, 3))")

let anotherMathFunction = addTwoInts

// AnotherMathFunction se infiere a ser de tipo (Int, Int)


-> Int
Tipos de funciones como tipos de parmetros
Puede utilizar un tipo de funcin, tales como (Int, Int) -> Int como un tipo de
parmetro de otra funcin.Esto le permite dejar algunos aspectos de la aplicacin de una
funcin para la persona que llama de la funcin de proporcionar, cuando se invoca la
funcin.
He aqu un ejemplo para imprimir los resultados de las funciones matemticas desde
arriba:

func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int) {

println("Result: \(mathFunction(a, b))")

printMathResult(addTwoInts, 3, 5)

// Impresiones "Resultado: 8"


Este ejemplo define una funcin llamada printMathResult , que tiene tres
parmetros. El primer parmetro se llama mathFunction , y es de tipo (Int,
Int) -> Int . Puede pasar cualquier funcin de ese tipo que el argumento a favor de
este primer parmetro. El segundo y tercer parmetros se llaman una y b , y son ambos
de tipo int . Estos se utilizan como los dos valores de entrada para la funcin
matemtica proporcionado.

103

Cuando printMathResult se llama, se le pasa el addTwoInts funcin, y valora


el nmero entero 3 y 5 . Se llama a la funcin, dotndolos de los 3 y 5 , e imprime el
resultado de 8 .
El papel de printMathResult es imprimir el resultado de una llamada a una
funcin matemtica de un tipo apropiado. No importa lo que la aplicacin de esa
funcin en realidad lo-hace slo importa que la funcin es del tipo correcto. Esto
permite printMathResult a entregar algunas de sus funciones a la persona que
llama de la funcin de una manera con seguridad de tipos.
Tipos de funciones como Tipos de valor devueltos
Usted puede utilizar un tipo de funcin que el tipo de retorno de otra funcin. Usted
puede hacer esto escribiendo un tipo de funcin completa inmediatamente despus de la
flecha de retorno ( -> ) de retorno de la funcin.
El siguiente ejemplo define dos funciones simples
llamados StepForward y stepbackward . El StepForwardfuncin devuelve un
valor uno ms que su valor de entrada, y la stepbackward funcin devuelve un valor
de un precio inferior a su valor de entrada. Ambas funciones tienen un tipo de (Int)
-> Int :

func stepForward(input: Int) -> Int {

return input + 1

func stepBackward(input: Int) -> Int {

return input - 1

}
Aqu hay una funcin llamada chooseStepFunction , cuyo retorno tipo es "una
funcin del tipo (Int) -> Int ".chooseStepFunction devuelve
el StepForward funcin o la stepbackward funcin basada en un parmetro
Boolean llamada hacia atrs :

func chooseStepFunction(backwards: Bool) -> (Int) -> Int {

return backwards ? stepBackward : stepForward

}
Ahora puede utilizar chooseStepFunction obtener una funcin que le paso en una
direccin o la otra:

var currentValue = 3

let moveNearerToZero = chooseStepFunction(currentValue > 0)

// MoveNearerToZero ahora se refiere a la stepbackward ()


funcin
El ejemplo anterior determina si se necesita un paso positivo o negativo para mover una
variable llamadaCurrentValue progresivamente ms cerca de
cero. CurrentValue tiene un valor inicial de 3 , lo que significa
queCurrentValue> 0 vuelve verdadera ,
causando chooseStepFunction para devolver el stepbackward funcin. Una

104

referencia a la funcin devuelto se almacena en una constante


llamada moveNearerToZero .
Ahora que moveNearerToZero refiere a la funcin correcta, que puede ser utilizado
para contar a cero:

println("Counting to zero:")

// Counting to zero:

while currentValue != 0 {

println("\(currentValue)... ")

currentValue = moveNearerToZero(currentValue)

println("zero!")

// 3...

// 2...

// 1...

// zero!
Funciones anidadas
Todas las funciones que ha encontrado hasta ahora en este captulo han sido ejemplos
de funciones globales, que se definen en un mbito global. Tambin puede definir
funciones dentro de los cuerpos de otras funciones, conocidas como funciones
anidadas .
Funciones anidadas estn ocultos del mundo exterior de forma predeterminada, pero an
as pueden ser llamados y utilizados por su funcin envolvente. Una funcin envolvente
tambin puede devolver una de sus funciones anidados para permitir la funcin anidada
para ser utilizado en otro mbito.
Puede volver a escribir la chooseStepFunction ejemplo anterior de usar y
devolver funciones anidadas:

println("Counting to zero:")

// Counting to zero:

while currentValue != 0 {

println("\(currentValue)... ")

currentValue = moveNearerToZero(currentValue)

println("zero!")

// 3...

// 2...

// 1...

// zero!


105

Cierres
Los cierres son bloques autnomos de la funcionalidad que se pueden pasar alrededor y
utilizar en su cdigo.Cierres en Swift son similares a los bloques en C y Objective-C y
para lambdas en otros lenguajes de programacin.
Los cierres pueden capturar y almacenar las referencias a todos los constantes y
variables del contexto en el que se definen. Esto se conoce como el cierre de ms de
esas constantes y variables, de ah el nombre "cierres". Swift se encarga de toda la
gestin de memoria de captura para usted.
NOTA
No se preocupe si usted no est familiarizado con el concepto de "captura". Se explica
en detalle a continuacin en la captura de Valores .
Funciones globales y anidadas, como introdujo en funciones , en realidad son casos
especiales de cierres.Los cierres tienen una de tres formas:
Funciones globales son los cierres que tienen un nombre y no captan ningn valor.
Funciones anidadas son los cierres que tienen un nombre y pueden capturar valores
de su funcin que encierra.
Expresiones de cierre son cierres annimas escritas en una sintaxis ligera que puede
capturar los valores de su contexto circundante.
Expresiones de cierre de Swift tienen un estilo claro limpio, con optimizaciones que
fomenten breve sintaxis, libre de desorden en escenarios comunes. Estas optimizaciones
incluyen:
Inferir los parmetros y valores de retorno tipos de contexto
Rendimientos implcitos de los cierres de una sola expresin
Nombres de los argumentos taquigrafa
Perdiendo sintaxis cierre
Expresiones de cierre
Funciones anidadas, como introdujo en Funciones anidadas , son un medio conveniente
de nombrar y definir los bloques autnomos de cdigo como parte de una funcin ms
grande. Sin embargo, a veces es til escribir las versiones ms cortas de construcciones
tipo funcin sin una declaracin y nombre completo. Esto es particularmente cierto
cuando se trabaja con funciones que tienen otras funciones como uno o ms de sus
argumentos.
Expresiones de cierre son una manera de escribir cierres en lnea en una breve, centrado
sintaxis.Expresiones de cierre proporcionan varias optimizaciones de sintaxis para
escribir cierres en forma abreviada y sin prdida de claridad o la intencin. Los
ejemplos a continuacin ilustran el cierre de expresin estas optimizaciones mediante el
refinado de un nico ejemplo de la ordenada en funcin de varias iteraciones, cada
una de las cuales expresa la misma funcionalidad de una manera ms concisa.
La Funcin Ordenada
La biblioteca estndar de Swift proporciona una funcin llamada ordenados , que
ordena una matriz de valores de un tipo conocido, en base a la salida de un cierre de la
clasificacin que usted proporcione. Una vez que se completa el proceso de
clasificacin, la ordenada funcin devuelve una nueva matriz del mismo tipo y
tamao que el anterior, con sus elementos en el orden de clasificacin correcto. La
matriz original no es modificado por la ordenada funcin.

106

Los ejemplos de expresin de cierre a continuacin utilizan la ordenada funcin para


ordenar un arreglo decuerdas valores en orden alfabtico inverso. Aqu est la matriz
inicial que ser resuelto:

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]

"Barry" , "Daniella" ]
La ordenada funcin toma dos argumentos:
Matriz de valores de un tipo conocido.
Un cierre que toma dos argumentos del mismo tipo que el contenido de la matriz, y
devuelve un Boolvalor para decir si el primer valor debe aparecer antes o despus
de que el segundo valor una vez que se ordenan los valores. El cierre de
clasificacin tiene que devolver verdadero si el primer valor debe
aparecer antes del segundo valor, y falso de lo contrario.
Este ejemplo es clasificar un conjunto de Cuerda valores, por lo que el cierre de la
clasificacin tiene que ser una funcin del tipo (String, String) -> Bool .
Una manera de proporcionar el cierre de clasificacin es escribir una funcin normal del
tipo correcto, y para pasarlo adentro como el clasificado segundo parmetro de la
funcin:

func backwards(s1: String, s2: String) -> Bool {

return s1 > s2

var reversed = sorted(names, backwards)

// Inversa es igual a ["Ewa", "Daniella", "Chris", "Barry",


"Alex"]
Si la primera cadena ( s1 ) es mayor que la segunda cadena ( s2 ), el revs funcin
devolver verdadero , lo que indica que s1 debe aparecer antes de s2 en la matriz
ordenada. Para caracteres en cadenas, "mayor que" significa "aparece ms adelante en el
alfabeto que no sea". Esto significa que la letra "B" es "mayor que" la letra "A" , y la
cadena "Tom" es mayor que la cadena "Tim" . Esto da una especie alfabtico inverso,
con"Barry" se coloca antes de "Alex" , y as sucesivamente.
Sin embargo, esta es una forma bastante largo aliento para escribir lo que es
esencialmente una funcin de una sola expresin ( a> b ). En este ejemplo, sera
preferible para escribir el cierre en lnea de clasificacin, usando la sintaxis de la
expresin de cierre.
Sintaxis Expresin Clausura
Sintaxis de las expresiones de cierre tiene la siguiente forma general:

{ ( parameters ) -> return type in


statements

}
Sintaxis de las expresiones de cierre puede utilizar parmetros constantes, parmetros
variables y inoutparmetros. Los valores por defecto no puede ser
proporcionada. Parmetros variadic se pueden utilizar si el nombre del parmetro

107

variadic y coloca ltima en la lista de parmetros. Las tuplas tambin se puede utilizar
como tipos de parmetros y tipos de retorno.
El siguiente ejemplo muestra una versin expresin cierre del revs funcin de antes:

reversed = sorted(names, { (s1: String, s2: String) -> Bool in

return s1 > s2

})
Tenga en cuenta que la declaracin de parmetros y el tipo de retorno para este cierre en
lnea es idntica a la declaracin del revs funcin. En ambos casos, se escribe
como (s1: String, s2: String) -> Bool . Sin embargo, para la expresin
de cierre en lnea, los parmetros y el tipo de retorno se escriben dentro de las llaves, y
no fuera de ellas.
El comienzo del cuerpo del cierre se introduce por el en la palabra clave. Esta palabra
clave indica que la definicin de parmetros y devuelve un tipo del cierre ha terminado,
y el cuerpo del cierre est por comenzar.
Debido a que el cuerpo del cierre es tan corto, que incluso se puede escribir en una sola
lnea:

reversed = sorted(names, { (s1: String, s2: String) -> Bool in return s1 > s2 } )

Esto ilustra que la llamada general a la sorted funcin se ha mantenido la misma. Un


par de parntesis, todava envuelve todo el conjunto de argumentos de la funcin. Sin
embargo, uno de esos argumentos es ahora un cierre inline.
Inferir Tipo De Contexto
Debido a que el cierre de la clasificacin se pasa como un argumento a una funcin,
Swift puede inferir los tipos de sus parmetros y el tipo de valor que devuelve el tipo de
la ordenada segundo parmetro de la funcin. Este parmetro est esperando una
funcin del tipo (String, String) -> Bool . Esto significa que el(String,
String) y Bool tipos no necesitan ser escritas como parte de la definicin de la
expresin de cierre.Debido a que todos los tipos se puede inferir, la flecha de retorno ( > ) y los parntesis alrededor de los nombres de los parmetros tambin se pueden
omitir:

reversed = sorted(names, { s1, s2 in return s1 > s2 } )


Siempre es posible inferir los tipos de parmetros y el tipo de retorno al pasar un cierre
a una funcin como una expresin de cierre en lnea. Como resultado, usted nunca tiene
que escribir un cierre en lnea en su forma ms completa cuando el cierre se utiliza un
argumento de funcin.
Sin embargo, usted todava puede hacer los tipos explcita si lo desea, y lo hace, es
alentado si se evita la ambigedad para los lectores de su cdigo. En el caso de
la ordenada funcin, el propsito de la clausura se desprende del hecho de que la
clasificacin est teniendo lugar, y es seguro para que el lector asume que el cierre es
probable que sea el trabajo con Cuerda valores, ya que est ayudando con la
clasificacin de una matriz de cadenas.

108

Devoluciones implcitas de cierres sola expresin


Cierres sola expresin pueden regresar de forma implcita el resultado de su expresin
nica omitiendo elretorno de palabras clave de su declaracin, como en esta versin
del ejemplo anterior:

reversed = sorted(names, { s1, s2 in s1 > s2 } )


En este caso, el tipo de funcin de la ordenada El segundo argumento de la funcin
deja claro que un Boolvalor debe ser devuelto por el cierre. Debido a que el cuerpo del
cierre contiene una sola expresin ( s1> s2 ) que devuelve un Bool valor, no hay
ambigedad, y el retorno de la palabra clave puede ser omitida.
Nombres de argumentos taquigrafa
Swift proporciona automticamente nombres de los argumentos de la taquigrafa para
inline cierres, que se pueden utilizar para hacer referencia a los valores de los
argumentos del cierre por los nombres $ 0 , $ 1 , $ 2, y as sucesivamente.
Si utiliza estos nombres de los argumentos de la taquigrafa en su expresin de cierre, se
puede omitir la lista de argumentos de la clausura de su definicin, y el nmero y tipo
de los nombres de los argumentos de la taquigrafa se desprendern de el tipo de
funcin esperada. El de palabras clave tambin se puede omitir, porque la expresin de
cierre se compone en su totalidad de su cuerpo:

reversed = sorted(names, { $0 > $1 } )


Aqu, $ 0 y $ 1 se refieren al primero y segundo del cierre de Cuerda argumentos.
Funciones del operador
De hecho, hay una an ms breve manera de escribir la expresin de cierre anterior. De
Swift Cadena tipo define su implementacin-cadena especfica de la mayor-que el
operador ( > ) como una funcin que tiene dos parmetros de tipo de cadena , y
devuelve un valor de tipo Bool . Esto coincide exactamente con el tipo de funcin
necesaria para el clasificado segundo parmetro de la funcin. Por lo tanto, usted
puede simplemente pasar en el operador mayor que, y Swift se infiere que desea utilizar
su implementacin-cadena especfica:

reversed = sorted(names, >)


Para ms informacin sobre las funciones del operador, consulte Funciones del
operador .
Trailing Cierres
Si usted necesita para pasar una expresin de cierre a una funcin como argumento final
de la funcin y la expresin de cierre es largo, puede ser til para escribir como
un cierre posterior en su lugar. A cierre de arrastre es una expresin de cierre que se
escribe fuera de (y despus ) de los parntesis de la funcin de llamada que soporta:

func someFunctionThatTakesAClosure(closure: () -> ()) {

// function body goes here

// As es como se llama a esta funcin sin necesidad de


utilizar un cierre de arrastre:

109

someFunctionThatTakesAClosure({

// Cuerpo de cierre va aqu

})

// As es como se llama a esta funcin con un cierre


posterior en su lugar:

someFunctionThatTakesAClosure() {

// Cuerpo detrs del cierre va aqu

}
NOTA
Si una expresin de cierre se proporciona como nico argumento de la funcin y le
proporcionar esa expresin como un cierre trasero, que no es necesario escribir un par
de parntesis () despus del nombre de la funcin cuando se llama a la funcin.
El cierre de cadena de clasificacin de la sintaxis de la expresin Cierre seccin anterior
se puede escribir fuera de la ordenada parntesis de funcionar como un cierre de
salida:

reversed = sorted(names) { $0 > $1 }


Cierres trailing son ms tiles cuando el cierre es suficientemente largo que no es
posible escribir en lnea en una sola lnea. Como un ejemplo, de Swift matriz tipo
tiene un mapa mtodo que toma una expresin de cierre como su argumento nico. El
cierre se llama una vez para cada elemento de la matriz, y devuelve un valor asignado
alternativo (posiblemente de algn otro tipo) para dicho elemento. La naturaleza de la
cartografa y el tipo del valor devuelto se deja hasta el cierre de especificar.
Despus de aplicar el cierre proporcionada a cada elemento de la matriz,
el mapa mtodo devuelve una nueva matriz que contiene todos los nuevos valores
mapeadas, en el mismo orden que los valores correspondientes en la matriz original.
He aqu cmo usted puede utilizar el mapa mtodo con un cierre posterior para
convertir una serie de Intvalores en una matriz de Cuerda valores. La matriz [16,
58, 510] se utiliza para crear la nueva matriz["OneSix", "FiveEight",
"FiveOneZero"] :

let digitNames = [

0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",

5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"

let numbers = [16, 58, 510]


El cdigo anterior crea un diccionario de asignaciones entre los dgitos enteros y
versiones en idioma Ingls de sus nombres. Tambin define una matriz de enteros, listo
para ser convertido en cuerdas.
Ahora puede utilizar el nmero de serie para crear una matriz de Cuerda valores,
pasando una expresin de cierre a la matriz de mapa mtodo como cierre final. Tenga
en cuenta que la llamada a numbers.map no necesita incluir ningn parntesis

110

despus de mapa , porque el mapa mtodo tiene slo un parmetro, y ese parmetro se
proporciona como un cierre de arrastre:

let strings = numbers.map {

(var number) -> String in

var output = ""

while number > 0 {

output = digitNames[number % 10]! + output

number /= 10

return output

// cuerdas se infiere a ser de tipo [cadena]

// Su valor es ["OneSix", "FiveEight", "FiveOneZero"]


El mapa mtodo llama a la expresin de cierre una vez para cada elemento de la
matriz. No es necesario especificar el tipo de parmetro de entrada de la clausura, el
nmero , porque el tipo se puede deducir de los valores de la matriz para ser asignada.
En este ejemplo, el cierre de nmero de parmetro se define como un parmetro
variable , como se describe en parmetros constantes y variables , de manera que el
valor del parmetro puede ser modificada dentro del cuerpo de cierre, en lugar de
declarar una nueva variable local y asignando el pasado nmero de valor a ella.La
expresin de cierre tambin especifica el tipo de devolucin de cuerdas , para
indicar el tipo que se almacena en la matriz de salida asignada.
La expresin de cierre genera una cadena llamada de salida cada vez que se
llama. Calcula el ltimo dgito del nmero mediante el operador resto ( % nmero
10 ), y utiliza este dgito para buscar una cadena apropiada en
el digitNames diccionario. El cierre se puede utilizar para crear una representacin
de cadena de cualquier nmero entero mayor que cero.
NOTA
La llamada a la digitNames subndice del diccionario es seguido por un signo de
exclamacin ( ! ), porque subndices Diccionario devuelven un valor opcional para
indicar que la consulta de diccionarios puede fallar si no existe la clave. En el ejemplo
anterior, se garantiza que el nmero de 10% ser siempre una clave subndice
vlido para la digitNames diccionario, y por lo tanto un signo de exclamacin se usa
para forzar-desenvolver la Cadena de valor almacenado en valor de retorno opcional
del subndice.
La cadena recuperada de la digitNames diccionario se aade a la parte
delantera de la salida , para aprovechar efectivamente una versin de cadena del
nmero en sentido inverso. (La expresin nmero 10% da un valor
de 6 a 16 , 8 por 58 , y 0 por 510 .)
El nmero variable se divide por 10 . Debido a que es un nmero entero, se
redondear a la baja durante la divisin, por lo que 16 se convierte en 1 , 58 se
convierte en 5 , y 510 se convierte en 51 .

111

El proceso se repite hasta que el nmero / = 10 es igual a 0 , en cuyo punto


la salida de cadena se devuelve por el cierre, y se aade a la matriz de salida por
el mapa de funcin.
El uso de la sintaxis de cierre de salida en el ejemplo anterior encapsula perfectamente
la funcionalidad del cierre inmediatamente despus de la funcin que soporta el cierre,
sin necesidad de envolver todo el cierre dentro del mapa parntesis exteriores de
funcin.
La captura de Valores
Un cierre puede capturar las constantes y variables del contexto que rodean en la que se
define. El cierre entonces puede referirse y modificar los valores de esas constantes y
variables desde el interior de su cuerpo, incluso si el alcance original que define las
constantes y variables ya no existe.
La forma ms simple de un cierre en Swift es una funcin anidada, escrito dentro del
cuerpo de otra funcin.Una funcin anidada puede capturar cualquiera de los
argumentos de la funcin externa y tambin puede capturar cualquier constantes y
variables definidas dentro de la funcin externa.
He aqu un ejemplo de una funcin llamada makeIncrementor , que contiene una
funcin anidada denominadaincrementor . El anidado incrementor funcin
captura dos valores, RunningTotal y cantidad , de su contexto
circundante. Despus de la captura de estos valores, incrementor es devuelto
por makeIncrementor como un cierre que se
incrementa RunningTotal por importe cada vez que se llama.

func makeIncrementor(forIncrement amount: Int) -> () -> Int {

var runningTotal = 0

func incrementor() -> Int {

runningTotal += amount

return runningTotal

return incrementor

}
El tipo de retorno de makeIncrementor es () -> Int . Esto significa que
devuelve una funcin , en lugar de un valor simple. La funcin devuelve no tiene
parmetros y devuelve un int valor cada vez que se llama. Para aprender las funciones
pueden devolver otras funciones, consulte Tipos de funcin como tipo de retorno .
El makeIncrementor funcin define una variable entera llamada RunningTotal ,
para almacenar el total de ejecucin actual del incrementor que ser devuelto. Esta
variable se inicializa con un valor de 0 .
El makeIncrementor funcin tiene un nico int parmetro con un nombre externo
de forIncrement , y un nombre local de cantidad . El valor del argumento
pasado a este parmetro especifica cunto RunningTotaldebe ser incrementado por
cada vez que la funcin de volver incrementor se llama.

112

makeIncrementor define una funcin denominada anidada incrementor , que


realiza la incremental real. Esta funcin no hace sino aumentar la
cantidad de RunningTotal , y devuelve el resultado.
Cuando se considera en forma aislada, el anidado incrementor funcin podra
parecer inusual:

func incrementor() -> Int {

runningTotal += amount

return runningTotal

}
El incrementor funcin no tiene parmetros, y sin embargo, se refiere
a RunningTotal y cantidad de dentro de su cuerpo de la funcin. Lo hace
mediante la captura de los existentes valores de RunningTotal y cantidad de su
funcin alrededores y utilizarlos dentro de su propio cuerpo de la funcin.
Debido a que no modifica la cantidad , incrementor realmente capta y
almacena una copia del valor almacenado en cantidad . Este valor se almacena junto
con el nuevo incrementor funcin.
Sin embargo, ya que modifica la RunningTotal variable cada vez que se
llama, incrementor captura unareferencia a la actual RunningTotal variables, y
no slo una copia de su valor inicial. Captura de una referencia asegura
que RunningTotal no desaparece cuando la llamada
a makeIncrementor termina y asegura queRunningTotal seguir siendo
disponible la prxima vez que la funcin incrementor se llama.
NOTA
Swift determina lo que debe ser capturado por referencia y lo que debera ser copiada
por valor. No es necesario anotar la cantidad o RunningTotal decir que se
pueden utilizar dentro del anidado incrementorfuncin. Swift tambin se encarga de
toda la gestin de memoria que supone la colocacin de RunningTotalcuando ya no
es necesaria por la funcin incrementor.
He aqu un ejemplo de makeIncrementor en accin:

let incrementByTen = makeIncrementor(forIncrement: 10)


En este ejemplo se establece una constante llamada incrementByTen para referirse a
una funcin incrementor que aade 10 a su RunningTotal variable cada vez que se
llama. Llamar a la funcin varias veces muestra este comportamiento en la accin:

incrementByTen()

// returns a value of 10

incrementByTen()

// returns a value of 20

incrementByTen()

// Devuelve un valor de 30
Si se crea una segunda incrementor, tendr su propia referencia almacenado a una
nueva, separadaRunningTotal variables:

let incrementBySeven = makeIncrementor(forIncrement: 7)


113

// Devuelve un valor de 7
Llamar a la incrementor originales ( incrementByTen ) de nuevo contina para
incrementar su propiaRunningTotal variables, y no afecta a la variable capturada
por incrementBySeven :

incrementBySeven()

incrementByTen()

// Devuelve un valor de 40
NOTA
Si asigna un cierre a una propiedad de una instancia de clase, y el cierre captura ese
ejemplo haciendo referencia a la instancia o de sus miembros, crear un fuerte ciclo de
referencia entre el cierre y la instancia.Swift utiliza listas de captura para romper estos
ciclos de referencia fuertes. Para obtener ms informacin, consulte Ciclos de referencia
fuertes para cierres .
Los cierres son tipos de referencia
En el ejemplo anterior, incrementBySeven y incrementByTen son constantes,
pero los cierres de estas constantes se refieren a son todava capaces de incrementar
los RunningTotal variables que se han capturado. Esto se debe a que las funciones y
los cierres son los tipos de referencia .
Cada vez que se asigna una funcin o un cierre a una constante o una variable, en
realidad se est configurando esa constante o variable para ser una referencia a la
funcin o el cierre. En el ejemplo anterior, es la eleccin de cierre
que incrementByTen se refiere a que es constante, y no los contenidos del propio
cierre.
Esto tambin significa que si asigna un cierre de dos constantes o variables diferentes,
tanto de esas constantes o variables se refieren a la misma de cierre:

let alsoIncrementByTen = incrementByTen

alsoIncrementByTen()

// Devuelve un valor de 50
Funciones
Las enumeraciones
Las enumeraciones
Una enumeracin define un tipo comn de un grupo de valores relacionados y le
permite trabajar con los valores de una manera con seguridad de tipos dentro de su
cdigo.
Si est familiarizado con C, sabrs que C enumeraciones asignan nombres relacionados
a un conjunto de valores enteros. Las enumeraciones de Swift son mucho ms flexibles,
y no tienen que proporcionar un valor para cada miembro de la enumeracin. Si un
valor (conocido como valor de "prima") se proporciona para cada miembro de la
enumeracin, el valor puede ser una cadena, un carcter o un valor de nmero entero o
tipo de punto flotante.
Alternativamente, los miembros de enumeracin pueden especificar valores asociados
de cualquier tipo para ser almacenados junto con cada valor de miembro diferente, tanto
como los sindicatos o variantes hacen en otras lenguas. Puede definir un conjunto

114

comn de miembros relacionados como parte de una enumeracin, cada uno de los
cuales tiene un conjunto diferente de valores de tipos apropiados asociados.
Las enumeraciones de Swift son tipos de primera clase en su propio derecho. Adoptan
muchas caractersticas que tradicionalmente slo compatibles con las clases, como las
propiedades calculadas para proporcionar informacin adicional sobre el valor actual de
la enumeracin, y los mtodos de instancia para proporcionar funcionalidad relacionada
con los valores de la enumeracin representa. Las enumeraciones pueden definir
tambin inicializadores para proporcionar un valor inicial miembro; se puede extender
para ampliar su funcionalidad ms all de su aplicacin original; y puede ajustarse a los
protocolos para proporcionar una funcionalidad estndar.
Para ms informacin sobre estas funciones,
consulte Properties, Methods, Initialization, Extensions, and Protocols.
Sintaxis Enumeracin
Introduces enumeraciones con la enumeracin de palabras clave y colocar toda su
definicin dentro de un par de llaves:

enum SomeEnumeration {

// Definicin enumeracin va aqu

}
He aqu un ejemplo de los cuatro puntos principales de una brjula:

enum CompassPoint {

case North

case South

case East

case West

}
Los valores definidos en la enumeracin (como Norte , Sur , Este y Oeste ) son
los valores de los miembros(o miembros ) de esa enumeracin. El caso de palabras
clave indica que una nueva lnea de valores de los miembros est por ser definido.
NOTA
A diferencia de C y Objective-C, miembros de la enumeracin Swift no se les asigna un
valor entero por defecto cuando se crean. En el CompassPoint ejemplo
anterior, Norte , Sur , Este y Oeste no lo hacen implcitamente
igual 0 , 1 , 2 y 3 . En su lugar, los diferentes miembros de la enumeracin son valores
de pleno derecho en su propio derecho, con un tipo definido de forma explcitade CompassPoint .
Valores de los miembros mltiples pueden aparecer en una sola lnea, separados por
comas:

enum Planet {

case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune

}
Each enumeration definition defines a brand new type. Like other types in Swift, their
Cada definicin de enumeracin define un nuevo tipo de marca. Al igual que otros tipos

115

de Swift, sus nombres (como CompassPoint y Planeta ) deben comenzar con una
letra mayscula. Dale tipos de enumeracin singulares en lugar de nombres en plural,
para que se lean como evidente:

var directionToHead = CompassPoint.West


El tipo de directionToHead se infiere cuando se inicializa con uno de los valores
posibles de CompassPoint .Una vez directionToHead se declara como
un CompassPoint , se puede establecer en un diferenteCompassPoint valor
utilizando una sintaxis con punto ms corto:

directionToHead =. Oriente
El tipo de directionToHead ya se conoce, y por lo que puede bajar el tipo al
establecer su valor. Esto lo convierte en cdigo muy legible cuando se trabaja con
valores de enumeracin explcita mecanografiadas-.
Coincidencia de Valores de enumeracin con una sentencia switch
Puede coincidir con los valores de enumeracin individuales con un interruptor
de declaracin:

directionToHead = .South

switch directionToHead {

case .North:

println("Lots of planets have a north")

case .South:

println("Watch out for penguins")

case .East:

println("Where the sun rises")

case .West:

println("Where the skies are blue")

// prints "Watch out for penguins"

// imprime "Ten cuidado con los pinginos"


Usted puede leer este cdigo como:
"Considere el valor de directionToHead . En el caso en el que es igual .North ,
impresin "Un montn de planetas tienen un norte" . En el caso en el
que es equals.South , imprimir "Cuidado con los pinginos"".
... Etctera.
Como se describe en el control de flujo , un switch de declaracin debe ser
exhaustiva cuando se considera miembros de una enumeracin. Si el for.West se
omite, el cdigo no se compila, porque no tiene en cuenta la lista completa
de CompassPoint miembros. Exigir exhaustividad garantiza que los miembros de
enumeracin no se incluyeron, accidentalmente.
Cuando no es conveniente establecer un caso para cada miembro de la enumeracin,
puede proporcionar un default case para cubrir los miembros que no se tratan de
forma explcita:

116

let somePlanet = Planet.Earth

switch somePlanet {

case .Earth:

println("Mostly harmless")

default:

println("Not a safe place for humans")

// imprime "Sobre todo inofensivo"


Valores asociados
Los ejemplos de la seccin anterior muestran cmo los miembros de una enumeracin
son un valor definido (y escrito) por derecho propio. Puede definir una constante o
variable a Planet.Earth , y comprobar si este valor ms adelante. Sin embargo, a
veces es til poder almacenar valores asociados de otros tipos junto a estos valores de
miembro. Esto le permite almacenar informacin personalizada adicional junto con el
valor de miembro, y permite que esta informacin para variar cada vez que utilice ese
miembro en el cdigo.
Puede definir enumeraciones Swift para almacenar valores asociados de cualquier tipo
dado, y los tipos de valor puede ser diferente para cada miembro de la enumeracin, si
es necesario. Las enumeraciones similares a stos se conocen como uniones
discriminadas , etiquetados sindicatos , o variantes en otros lenguajes de programacin.
Por ejemplo, supongamos que un sistema de seguimiento de inventario necesita para
rastrear productos por dos tipos diferentes de cdigo de barras. Algunos productos estn
etiquetados con cdigos de barras 1D en UPC-A formato, que utiliza los nmeros
de 0 a 9 . Cada cdigo de barras tiene un dgito "sistema de numeracin", seguida de
cinco "cdigo de fabricante" dgitos y cinco "cdigo de producto" dgitos. Estos son
seguidos por un dgito "check" para verificar que el cdigo ha sido escaneado
correctamente:


Otros productos que estn etiquetados con cdigos de barras 2D en forma de cdigos
QR, que pueden usar cualquiera de caracteres ISO 8859-1 y puede codificar una cadena
de hasta 2.953 caracteres de longitud:

117


Sera conveniente para un sistema de seguimiento de inventario para poder almacenar
los cdigos de barras UPC-A como una tupla de cuatro enteros, y los cdigos de barras
de cdigos QR como una cadena de cualquier longitud.
En Swift, una enumeracin para definir los cdigos de barras de productos de cualquier
tipo podra tener este aspecto:

enum Barcode {

case UPCA(Int, Int, Int, Int)

case QRCode(String)

}
Esto puede leerse como:
"Definir un tipo de enumeracin llamado cdigo de barras , el cual puede tomar
un valor de UPCA con un valor asociado de tipo ( Int , Int , Int , Int ), o un valor
de QRCode con un valor asociado de tipo Cadena . "
Esta definicin no ofrece reales Int o de Cuerda valores-que slo define el tipo de
valores asociados que de cdigo de barras constantes y variables se almacenan
cuando son iguales a Barcode.UPCA oBarcode.QRCode .
Nuevos cdigos de barras a continuacin, se pueden crear utilizando cualquier tipo:
var productBarcode = cdigo de barras . UPCA ( 8 , 85909 ,

51226 , 3 )
En este ejemplo se crea una nueva variable llamada productBarcode y le asigna un
valor de Barcode.UPCAcon un valor asociado de tupla (8, 85909, 51226,
3) .
El mismo producto se puede asignar un tipo diferente de cdigo de barras:

productBarcode = .QRCode("ABCDEFGHIJKLMNOP")
En este punto, el original Barcode.UPCA sus valores enteros y se sustituyen por el
nuevo Barcode.QRCode y su valor de cadena. Constantes y variables de tipo de
cdigo de barras se pueden almacenar ya sea un .UPCAo una .QRCode (junto
con sus valores asociados), pero slo pueden almacenar uno de ellos en un momento
dado.
Los diferentes tipos de cdigos de barras se pueden verificar utilizando una sentencia
switch, como antes.Esta vez, sin embargo, los valores asociados puede ser extrada
como parte de la instruccin switch. Extraer cada valor asociado como una constante

118

(con la let prefijo) o una variable (con la var prefijo) para su uso en
el interruptor del cuerpo de caso:

switch productBarcode {

case .UPCA(let numberSystem, let manufacturer, let product, let check):

println("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).")

case .QRCode(let productCode):

println("QR code: \(productCode).")

// prints "QR code: ABCDEFGHIJKLMNOP."


Si todos los valores asociados para un miembro de la enumeracin se extraen como
constantes, o si todo se extraen como variables, se puede colocar una
sola var o dejar de anotacin antes de que el nombre de miembro, por razones de
brevedad:

switch productBarcode {

case let .UPCA(numberSystem, manufacturer, product, check):

println("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).")

case let .QRCode(productCode):

println("QR code: \(productCode).")

// imprime "cdigo QR: ABCDEFGHIJKLMNOP".


Valores primas
El ejemplo de cdigo de barras en valores asociados muestra cmo los miembros de una
enumeracin pueden declarar que almacenan valores asociados de diferentes
tipos. Como una alternativa a los valores asociados, los miembros de enumeracin
pueden venir rellena previamente con valores predeterminados (denominados valores en
bruto ), que son todos del mismo tipo.
He aqu un ejemplo que almacena valores ASCII prima junto a los miembros de la
enumeracin designados:

enum ASCIIControlCharacter: Character {

case Tab = "\t"

case LineFeed = "\n"

case CarriageReturn = "\r"

}
En este caso, los valores de primas para una enumeracin
denominada ASCIIControlCharacter se definen como de tipo de
caracteres , y se ponen a algunos de los personajes ms comunes de control
ASCII.Carcter valores se describen en Cuerdas y Personajes .
Tenga en cuenta que los valores de primas son no lo mismo que los valores
asociados. Valores primas se ajustan a los valores rellenados previamente cuando defina
primero la enumeracin en el cdigo, como los tres cdigos ASCII anteriores. El valor

119

en bruto para un miembro de la enumeracin particular es siempre la misma. Valores


asociados se establecen cuando se crea una nueva constante o variable en funcin de
uno de los miembros de la enumeracin, y puede ser diferente cada vez que lo haga.
Valores crudos pueden ser cadenas, caracteres o cualquiera de los nmeros enteros o de
punto flotante tipos de nmeros. Cada valor en bruto debe ser nico en su declaracin
de la enumeracin. Cuando se utilizan nmeros enteros para los valores de primas, que
de incremento automtico si no se especifica ningn valor para algunos de los miembros
de la enumeracin.
La enumeracin a continuacin es un refinamiento de la anterior Planet enumeracin,
con valores enteros primas para representar el fin de cada planeta del sistema solar:

enum Planet: Int {

case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune

}
Auto-incrementacin significa que Planet.Venus tiene un valor en bruto de 2 , y as
sucesivamente.
Acceder al valor bruto de un miembro de la enumeracin con su toRaw mtodo:

let earthsOrder = Planet.Earth.toRaw()

// earthsOrder is 3
Utilizar de una enumeracin fromRaw mtodo para tratar de encontrar un miembro de
la enumeracin con un valor bruto particular. En este ejemplo se identifica Urano de su
valor bruto de 7 :

let possiblePlanet = Planet.fromRaw(7)

// possiblePlanet is of type Planet? and equals Planet.Uranus


No todos los posibles Int valores encontrarn un planeta a juego, sin embargo. Debido
a esto, la fromRawmtodo devuelve un opcional miembro de enumeracin. En el
ejemplo anterior, possiblePlanet es de tipoPlanet? , o "opcional Planet . "
Si usted trata de encontrar un planeta con una posicin de 9 , el opcional Planet valor
devuelto por fromRawser nula :

let positionToFind = 9

if let somePlanet = Planet.fromRaw(positionToFind) {

switch somePlanet {

case .Earth:

println("Mostly harmless")

default:

println("Not a safe place for humans")

} else {

println("There isn't a planet at position \(positionToFind)")

// imprime "No hay un planeta en la posicin 9"


120

En este ejemplo se utiliza opcional vinculante para tratar de acceder a un planeta con un
valor bruto de 9 . La declaracin si dejar somePlanet = Planet.fromRaw
(9) recupera un opcional Planet , y establecesomePlanet al contenido de ese
opcional Planet si puede ser recuperada. En este caso, no es posible recuperar un
planeta con una posicin de 9 , por lo que la otra rama se ejecuta en su lugar.

Clases y estructuras
Las clases y las estructuras son de uso general, construcciones flexibles que se
convierten en los componentes bsicos del cdigo de su programa. Usted define las
propiedades y mtodos para agregar funcionalidad a sus clases y estructuras utilizando
exactamente la misma sintaxis que para las constantes, variables y funciones.
A diferencia de otros lenguajes de programacin, Swift no le requiere para crear
archivos de interfaz y de aplicacin nica para las clases y estructuras
personalizadas. En Swift, se define una clase o una estructura en un solo archivo, y la
interfaz externa a esa clase o estructura se hace automticamente disponible para otro
cdigo a utilizar.
NOTA
Una instancia de una clase se conoce tradicionalmente como un objeto . Sin embargo,
las clases y las estructuras de Swift estn mucho ms cerca en la funcionalidad que en
otros idiomas, y gran parte de este captulo se describe la funcionalidad que se puede
aplicar a instancias de cualquiera de una clase o un tipo de estructura. Debido a esto, el
trmino ms general de ejemplo se utiliza.
La comparacin de clases y estructuras
Clases y estructuras en Swift tienen muchas cosas en comn. Ambos pueden:
Definir propiedades para almacenar valores
Definir los mtodos para proporcionar funcionalidad
Definir subndices para dar acceso a sus valores usando la sintaxis subndice
Definir inicializadores para establecer su estado inicial
Se ampliar para ampliar su funcionalidad ms all de una implementacin por
defecto
Conformarse a protocolos para proporcionar una funcionalidad estndar de un cierto
tipo
Para obtener ms informacin,
vea Propiedades , Mtodos , subndices , inicializacin , extensiones , yProtocolos .
Las clases tienen capacidades adicionales que las estructuras no hacen:
La herencia permite a una clase a heredar las caractersticas de otro.
Tipo de fundicin permite comprobar e interpretar el tipo de una instancia de clase
en tiempo de ejecucin.
Deinitializers permiten una instancia de una clase para liberar todos los recursos que
tiene asignados.
El conteo de referencias permite ms de una referencia a una instancia de clase.
Para obtener ms informacin, vea Herencia , la conversin de
tipos , deinicializacin y conteo automtico de referencia .
NOTA

121

Estructuras siempre se copian cuando se pasan alrededor de su cdigo, y no utilizan el


recuento de referencias.
Sintaxis Definicin
Clases y estructuras tienen una sintaxis definicin similar. Introduces clases con
la clase de palabras clave y las estructuras con la estructura de palabras
clave. Tanto colocar toda su definicin dentro de un par de llaves:

class SomeClass {

// Definicin de clase va aqu

struct SomeStructure {

// Estructura de definicin va aqu

}
NOTA
Cada vez que se define una nueva clase o estructura, se definen de manera efectiva un
nuevo tipo Swift marca. Dale tipos UpperCamelCase nombres
(como AlgunaClase y SomeStructure aqu) para que coincida con la
capitalizacin de los tipos Swift estndar (tales como cuerdas , Int , y Bool ). Por
el contrario, siempre dan propiedades y mtodos lowerCamelCase nombres
(como frameRate y incrementCount ) para diferenciarlos de los nombres de los
tipos.
He aqu un ejemplo de una definicin de la estructura y una definicin de clase:

struct Resolution {

var width = 0

var height = 0

class VideoMode {

var resolution = Resolution()

var interlaced = false

var frameRate = 0.0

var name: String?

}
El ejemplo anterior define una nueva estructura llamada Resolucin , para describir
una resolucin de pantalla basado en pxeles. Esta estructura tiene dos propiedades
almacenado llamado anchura y altura .Propiedades almacenados son constantes o
variables que se empaquetan y almacenan como parte de la clase o estructura. Estas dos
propiedades se infieren a ser de tipo Int estableciendo su valor a un valor entero inicial
de 0 .
El ejemplo anterior tambin define una nueva clase llamada VideoMode , para
describir un modo de vdeo especfico para la visualizacin de vdeo. Esta clase tiene
cuatro propiedades almacenadas variables. La primera, la resolucin , se
inicializa con una nueva Resolucin instancia de estructura, lo que infiere un tipo de
propiedad de la Resolucin . Para las otras tres propiedades,

122

nuevas Videomode casos se pueden inicializar con un entrelazado de


ajuste falsa (que significa "de vdeo no entrelazado"), una velocidad de fotogramas
de reproduccin de 0.0 opcional, y Cadena valor llamado nombre . El nombre
de la propiedad se le asigna automticamente un valor por defecto de cero , o
"no nombre de valor ", ya que es de un tipo opcional.
Instancias de clase y estructura
La Resolucin definicin de la estructura y la VideoMode definicin de clase slo
describen lo que unaresolucin o VideoMode se ver as. Ellos mismos no
describen una resolucin especfica o en el modo de vdeo. Para ello, es necesario crear
una instancia de la estructura o clase.
La sintaxis para la creacin de instancias es muy similar para ambas estructuras y
clases:

let someResolution = Resolution()

let someVideoMode = VideoMode()


Estructuras y clases tanto usan la sintaxis de inicializador de nuevos casos. La forma
ms simple de la sintaxis de inicializador utiliza el nombre del tipo de la clase o
estructura seguida de parntesis vacos, como la Resolucin () o VideoMode
() . Esto crea una nueva instancia de la clase o estructura, con propiedades
inicializados a sus valores predeterminados. Inicializacin de la clase y la estructura se
describe con ms detalle en la inicializacin .
Acceso a las propiedades
Puede acceder a las propiedades de una instancia utilizando la sintaxis con punto . En la
sintaxis con punto, se escribe el nombre de la propiedad inmediatamente despus de que
el nombre de la instancia, separados por un punto ( . , sin espacios):

// imprime "El ancho de someResolution es 0"


En este ejemplo, someResolution.width se refiere a la anchura de la
propiedad de someResolution , y devuelve su valor inicial por defecto de 0 .
Puede profundizar en sub-propiedades, como el ancho de la propiedad en
la resolucin de la propiedad de unVideoMode :

println("The width of someResolution is \(someResolution.width)")

println("The width of someVideoMode is \(someVideoMode.resolution.width)")

// imprime "El ancho de someVideoMode es 0"


Tambin puede utilizar la sintaxis con punto para asignar un nuevo valor a una
propiedad de variable:

someVideoMode.resolution.width = 1280

println("The width of someVideoMode is


now\(someVideoMode.resolution.width)")

// imprime "El ancho de someVideoMode es ahora 1280"


NOTA
A diferencia de Objective-C, Swift le permite establecer directamente sub-propiedades
de una estructura de propiedad. En el ltimo ejemplo de arriba, la anchura de la
propiedad de la resolucin de la propiedad desomeVideoMode se establece

123

directamente, sin la necesidad de configurar toda la resolucin de la propiedad a


un nuevo valor.
Miembro por miembro Inicializadores de Estructura Tipos
Todas las estructuras tienen una generada automticamente inicializador miembro por
miembro , que se puede utilizar para inicializar las propiedades de los miembros de las
nuevas instancias de estructura. Los valores iniciales de las propiedades de la nueva
instancia se pueden pasar a la inicializador miembro por miembro por su nombre:

let vga = Resolution(width: 640, height: 480)


A diferencia de las estructuras, instancias de clase no reciben un inicializador de
miembro por miembro por defecto. Inicializadores se describen con ms detalle en la
inicializacin .
Estructuras y enumeraciones son tipos de valor
Un tipo de valor es un tipo cuyo valor es copiado cuando se asigna a una variable o
constante, o cuando se pasa a una funcin.
En realidad se ha estado utilizando los tipos de valor extensivamente a travs de los
captulos anteriores. De hecho, todos los tipos bsicos en Swift-nmeros enteros,
nmeros de punto flotante, booleanos, cadenas, matrices y diccionarios-son tipos de
valor, y se implementan como estructuras detrs de las escenas.
Todas las estructuras y enumeraciones son tipos de valor en Swift. Esto significa que
todas las instancias de la estructura y la enumeracin que crear-y de cualquier tipo de
valor que tienen, como siempre, son propiedades-copian cuando se pasan alrededor de
su cdigo.
Considere este ejemplo, que utiliza la Resolucin estructura del ejemplo anterior:

let hd = Resolution(width: 1920, height: 1080)

var cinema = hd
En este ejemplo se declara una llamada constante hd y lo establece en
un Resolucin instancia inicializada con el ancho y la altura de vdeo Full HD
( 1920 pxeles de ancho por 1080 pxeles de alto).
A continuacin, declara una variable de llamada del cine y lo establece en el valor
actual de hd . DebidoResolucin es una estructura, una copia est hecha de la
instancia existente, y esta nueva copia se asigna acine . Aunque hd y el
cine tienen ahora la misma anchura y altura, son dos casos completamente diferentes
entre bastidores.
A continuacin, el ancho de la propiedad del cine se modifica para ser el ancho de
la 2K estndar ligeramente ms amplio utilizado para la proyeccin de cine digital
( 2048 pxeles de ancho por 1080 pxeles de alto):

cine . ancho = 2048


Comprobacin de la anchura de la propiedad de cine muestra que ha cambiado de
hecho a ser 2048 :

println("cinema is now \(cinema.width) pixels wide")

// Imprime "el cine es ahora 2.048 pxeles de ancho"


Sin embargo, la anchura de la propiedad del original hd ejemplo todava tiene el
valor antiguo de 1920 :

println("hd is still \(hd.width) pixels wide")


124

// Impresiones "hd es todava 1920 pxeles de ancho"


Cuando cinema se le dio el valor actual del hd , los valores almacenados en hd se
copian en el nuevo cinemainstancia. El resultado final es dos instancias
completamente separados, que acaba de pasar a contener los mismos valores
numricos. Debido a que son instancias separadas, establecer el ancho
de cine a 2048 no afecta a la anchura almacenada en HD .
El mismo comportamiento se aplica a las enumeraciones:

enum CompassPoint {

case North, South, East, West

var currentDirection = CompassPoint.West

let rememberedDirection = currentDirection

currentDirection = .East

if rememberedDirection == .West {

println("The remembered direction is still .West")

// imprime "La direccin es recordado todava .West"


Cuando rememberedDirection se le asigna el valor de currentDirection ,
en realidad est ajustado a una copia de ese valor. Cambiar el valor
de currentDirection a partir de entonces no afecta a la copia del valor original
que se guarda en rememberedDirection .
Las clases son tipos de referencia
A diferencia de los tipos de valor, los tipos de referencia no son copiados cuando se les
asigna a una variable o constante, o cuando se pasan a una funcin. En lugar de una
copia, una referencia a la misma instancia existente se utiliza en su lugar.
He aqu un ejemplo, usando el VideoMode clase definido anteriormente:

let tenEighty = VideoMode()

tenEighty.resolution = hd

tenEighty.interlaced = true

tenEighty.name = "1080i"

tenEighty.frameRate = 25.0
En este ejemplo se declara una nueva constante llamada Teneighty y establece que
para referirse a una nueva instancia de la VideoMode clase. El modo de vdeo se le
asigna una copia de la resolucin HD de 1.920por 1.080 de antes. Se fija para ser
entrelazadas, y se le da un nombre de "1080i" . Finalmente, se establece a una
velocidad de 25,0 fotogramas por segundo.
A continuacin, Teneighty se asigna a una nueva constante,
llamado alsoTenEighty , y la velocidad de fotogramas de alsoTenEighty se
modifica:

let alsoTenEighty = tenEighty


125

alsoTenEighty.frameRate = 30.0
Debido a que las clases son tipos de
referencia, Teneighty y alsoTenEighty realidad ambos se refieren a
lamisma VideoMode instancia. Efectivamente, son slo dos nombres diferentes para la
misma instancia nica.
Comprobacin del frameRate propiedad de Teneighty muestra que informa
correctamente la nueva velocidad de fotogramas de 30,0 desde el
subyacente VideoMode ejemplo:

println("The frameRate property of tenEighty is now \(tenEighty.frameRate)")

// imprime "La propiedad frameRate de Teneighty es ahora


30.0"
Tenga en cuenta que Teneighty y alsoTenEighty se declaran como constantes ,
en lugar de variables. Sin embargo, todava puede
cambiar tenEighty.frameRate y alsoTenEighty.frameRate debido a que
los valores de la Teneighty y alsoTenEighty constantes de s mismos en
realidad no cambian. Teneighty y alsoTenEightymismos no "tienda"
del VideoMode ejemplo-en vez, ambos se refieren a un VideoMode instancia detrs
de las escenas. Es la frameRate propiedad del subyacente VideoMode que se
cambia, no los valores de las constantes referencias a que VideoMode .
Operadores de identidad
Debido a que las clases son tipos de referencia, es posible que varias constantes y
variables que se refieren a la misma instancia nica de una clase detrs de las
escenas. (Lo mismo no es cierto para las estructuras y enumeraciones, porque se copian
siempre cuando se les asigna a una constante o variable, o se pasan a una funcin.)
A veces puede ser til para averiguar si dos constantes o variables se refieren a
exactamente la misma instancia de una clase. Para permitir esto, Swift proporciona dos
operadores de identidad:
Idntico al ( === )
No idntica a ( ! == )
Utilice estos operadores para comprobar si dos constantes o variables se refieren a la
misma instancia nica:

if tenEighty === alsoTenEighty {

println("tenEighty and alsoTenEighty refer to the same VideoMode instance.")

// Impresiones "Teneighty y alsoTenEighty se refieren a la


misma instancia VideoMode."
Tenga en cuenta que "idntico a" (representado por tres signos de igual, o === ) no
significa lo mismo que "igual" (representado por dos signos de igual, o == ):
"Igual que" significa que dos constantes o variables de tipo de clase se refieren
exactamente a la misma instancia de clase.
"Igual a" significa que dos casos son considerados "iguales" o "equivalente" en el
valor, por algn significado apropiado de "iguales", como se define por el diseador
del tipo.

126

Al definir sus propias clases y estructuras personalizadas, es su responsabilidad de


decidir lo que califica como dos casos de ser "igual". El proceso de definicin de sus
propias implementaciones de la "igual a" y "no es igual a" operadores se describe
en Operadores de equivalencia .
Punteros
Si usted tiene experiencia con C, C ++ o Objective-C, usted puede saber que estos
idiomas utilizan punterospara hacer referencia a direcciones en la memoria. Una
constante Swift o variable que hace referencia a una instancia de un tipo de referencia es
similar a un puntero en C, pero no es un puntero directo a una direccin en la memoria,
y no requiere que usted escriba un asterisco ( * ) para indicar que estn creando una
referencia. En lugar de ello, estas referencias se definen como cualquier otra constante o
variable en Swift.
Elegir entre clases y estructuras
Puede utilizar ambas clases y estructuras para definir tipos de datos personalizados para
su uso como los bloques de construccin de cdigo de su programa.
Sin embargo, las instancias de la estructura siempre se pasan por valor , y las instancias
de clase siempre se pasan por referencia . Esto significa que son adecuados para
diferentes tipos de tareas. Al considerar las construcciones de datos y funcionalidad que
usted necesita para un proyecto, decidir si cada construccin de datos debe ser definido
como una clase o como una estructura.
Como pauta general, considerar la creacin de una estructura cuando una o ms de estas
condiciones:
El propsito principal de la estructura es encapsular unos valores de datos
relativamente simples.
Es razonable esperar que los valores encapsulados se copiarn en lugar de referencia
cuando se asigna o pasar alrededor de una instancia de esa estructura.
Todas las propiedades almacenados por la estructura son ellos mismos tipos de
valores, que tambin se esperara que se va a copiar en lugar de referencia.
La estructura no necesita heredar propiedades o comportamiento de otro tipo
existente.
Ejemplos de buenos candidatos para estructuras incluyen:
El tamao de una forma geomtrica, tal vez la encapsulacin de una anchura
de propiedad y una altura de la propiedad, tanto de tipo doble .
Una forma para referirse a rangos dentro de una serie, tal vez encapsula
un inicio la propiedad y unalongitud de la propiedad, tanto de tipo int .
Un punto en un sistema de 3D, tal vez encapsulacin de
coordenadas x , Y y Z propiedades, cada uno de tipo doble .
En todos los dems casos, definir una clase, y crear instancias de esa clase se gestionen
y se pasan por referencia. En la prctica, esto significa que la mayora de las
construcciones de datos personalizados deben ser clases, no a estructuras.

127

Asignacin y Copiar Comportamiento de cadenas, matrices, y Diccionarios


De Swift de Cuerda , de matriz , y Diccionario tipos se implementan como
estructuras. Esto significa que se copian cadenas, matrices y diccionarios cuando son
asignados a una nueva constante o variable, o cuando se pasan a una funcin o mtodo.
Este comportamiento es diferente de NSString , NSArray y NSDictionary en
Fundacin, que se implementan como clases, no
estructuras. NSString , NSArray y NSDictionary casos siempre se asignan y se
pasa alrededor como una referencia a una instancia existente, en lugar de como una
copia.
NOTA
La descripcin anterior se refiere a la "copia" de las cadenas, matrices y diccionarios. El
comportamiento que se observa en el cdigo siempre ser como si una copia se llev a
cabo. Sin embargo, Swift slo realiza unaverdadera copia en segundo plano cuando es
absolutamente necesario hacerlo. Swift gestiona toda la copia de valores para garantizar
un rendimiento ptimo, y usted no debe evitar la asignacin para tratar de anticiparse a
esta optimizacin.

Propiedades
Propiedades asocian valores con una clase, estructura o enumeracin
particular. Propiedades almacenados almacenar valores constantes y variables como
parte de una instancia, mientras que las propiedades calculadas calculan (en lugar de la
tienda) un valor. Propiedades calculadas son proporcionados por las clases, estructuras y
enumeraciones. Propiedades almacenados se proporcionan slo por las clases y
estructuras.
Propiedades almacenadas y calculadas se asocian generalmente a instancias de un tipo
particular. Sin embargo, las propiedades tambin pueden estar asociados con el propio
tipo. Dichas propiedades se conocen como propiedades de tipo.
Adems, puede definir la propiedad observadores para monitorear los cambios en el
valor de una propiedad, que se puede responder con acciones
personalizadas. Observadores de propiedad pueden ser aadidos a las propiedades
almacenados definidas por usted, y tambin a las propiedades que una subclase hereda
de su superclase.
Propiedades guardadas
En su forma ms simple, una propiedad almacenada es una constante o una variable que
se almacena como parte de una instancia de una clase o estructura
particular. Propiedades almacenados pueden ser opropiedades de las variables
almacenadas (introducidas por la var palabra clave) o propiedades almacenadas
constantes (introducidos por el let palabra clave).
Puede proporcionar un valor predeterminado para una propiedad almacenada como
parte de su definicin, como se describe en los valores de propiedad
predeterminados . Tambin puede establecer y modificar el valor inicial de una
propiedad almacenada durante la inicializacin. Esto es cierto incluso para constantes
propiedades almacenadas, como se describe en Modificacin de las propiedades
constantes durante la inicializacin .

128

El ejemplo siguiente define una estructura llamada FixedLengthRange , que


describe un rango de enteros cuya longitud rango no se puede cambiar una vez que se
crea:

struct FixedLengthRange {

var firstValue: Int

let length: Int

var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)

// the range represents integer values 0, 1, and 2

rangeOfThreeItems.firstValue = 6

// La gama ahora representa valores enteros 6, 7, y 8


Las instancias de FixedLengthRange tienen una propiedad de variable almacenado
llamado firstValue y una propiedad almacenada constante
llamada longitud . En el ejemplo anterior, la longitud se inicializa cuando se
crea la nueva gama y no puede ser cambiado a partir de entonces, debido a que es una
propiedad constante.
Propiedades almacenados de Estructura instancias constantes
Si crea una instancia de una estructura y asigna esa instancia a una constante, no puede
modificar las propiedades de la instancia, aunque hayan sido declarados como
propiedades de las variables:

let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)

// this range represents integer values 0, 1, 2, and 3

rangeOfFourItems.firstValue = 6

// Esto reportar un error, a pesar de que firstValue es


una propiedad de variable
Debido rangeOfFourItems se declara como una constante (con la let palabra
clave), no es posible cambiar sufirstValue propiedad, a pesar de
que firstValue es una propiedad variable.
Este comportamiento se debe a que las estructuras son tipos de valor . Cuando una
instancia de un tipo de valor est marcado como una constante, por lo que son todas sus
propiedades.
Lo mismo no es cierto para las clases, que son los tipos de referencia . Si asigna una
instancia de un tipo de referencia a una constante, siempre ser posible modificar
propiedades de las variables de esa instancia.
Propiedades almacenados Lazy
Una propiedad almacenado perezoso es una propiedad cuyo valor inicial no se calcula
hasta que la primera vez que se utiliza. Usted indica un perezoso propiedad almacenada
escribiendo el perezoso modificador antes de su declaracin.
NOTA
Siempre hay que declarar una propiedad perezoso como una variable (con
la var palabra clave), ya que su valor inicial no podra ser recuperada hasta despus de
que finalice inicializacin de instancia. Propiedades constantes siempre deben tener un

129

valor antes de la inicializacin completa, y por lo tanto no pueden ser declarados como
perezoso.
Lazy propiedades son tiles cuando el valor inicial de una propiedad depende de
factores externos, cuyos valores no se conocen hasta despus de la inicializacin de una
instancia se ha completado. Lazy propiedades tambin son tiles cuando el valor inicial
de una propiedad requiere configuracin compleja o costosa computacionalmente que
no debe realizarse a menos que o hasta que se necesite.
El ejemplo siguiente utiliza una propiedad almacenada perezosa para evitar la
inicializacin innecesaria de una clase compleja. Este ejemplo define dos clases
llamadas DataImporter y DataManager , ninguno de los cuales se muestra en su
totalidad:

class DataImporter {

/ *

DataImporter es una clase para importar datos de un archivo


externo.

La clase se supone que tomar una cantidad no trivial de


tiempo para inicializar.

* /

var fileName = "data.txt"

// La clase DataImporter proporcionara datos importadores


funcionalidad aqu

class DataManager {

lazy var importer = DataImporter()

var data = [String]()

// La clase DataManager proporcionara la funcionalidad de


gestin de datos aqu

let manager = DataManager()

manager.data.append("Some data")

manager.data.append("Some more data")

// An no se ha creado la instancia DataImporter para la


propiedad importador
El DataManager clase tiene una propiedad almacenado llamado de datos , que se
inicia con una nueva matriz, vaco de Cuerda valores. Aunque no se muestra el resto
de su funcionalidad, el propsito de este DataManagerclase es gestionar y facilitar el
acceso a esta matriz de cadena de datos.

130

Parte de la funcionalidad del DataManager clase es la capacidad de importar datos de


un archivo. Esta funcionalidad es proporcionada por el DataImporter clase, que se
supone que tomar una cantidad no trivial de tiempo para inicializar. Esto podra ser
debido a un DataImporter instancia tiene que abrir un archivo y leer su contenido
en la memoria cuando el DataImporter se inicializa la instancia.
Es posible que un DataManager ejemplo para administrar sus datos sin importar
datos de un archivo, lo que no hay necesidad de crear un
nuevo DataImporter ejemplo, cuando el DataManager se crea en s. En cambio,
tiene ms sentido para crear la DataImporter ejemplo, si y cuando se utiliz por
primera vez.
Debido a que est marcado con el perezoso modificador,
el DataImporter instancia para el importador slo se crea la propiedad cuando
el importador de propiedad se accede por primera vez, como cuando
su nomArchivopropiedad se consulta:

println(manager.importer.fileName)

// Ahora se ha creado la instancia DataImporter para la


propiedad importador

// Impresiones "data.txt"


Propiedades almacenados y variables de instancia
Si usted tiene experiencia con Objective-C, usted puede saber que ofrece dos formas de
almacenar los valores y las referencias como parte de una instancia de clase. Adems de
las propiedades, puede utilizar las variables de instancia como un almacn de respaldo
para los valores almacenados en una propiedad.
Swift unifica estos conceptos en una nica declaracin de propiedad. Una propiedad
Swift no tiene una variable de instancia correspondiente, y el almacn de respaldo para
una propiedad no se accede directamente. Este enfoque evita la confusin acerca de
cmo se accede al valor en diferentes contextos y simplifica la declaracin de la
propiedad en una sola sentencia, definitiva. Toda la informacin sobre la propiedadincluyendo su nombre, caractersticas-es el tipo y la gestin de memoria definen en un
solo lugar, como parte de la definicin del tipo.
Propiedades calculadas
Adems de las propiedades almacenados, clases, estructuras y enumeraciones pueden
definir propiedades calculadas , que en realidad no almacenan un valor. En su lugar,
proporcionan un getter y un setter opcional para recuperar y establecer otras
propiedades y valores de manera indirecta.

struct Point {

var x = 0.0, y = 0.0

struct Size {

var width = 0.0, height = 0.0

}
131

struct Rect {

var origin = Point()

var size = Size()

var center: Point {

get {

let centerX = origin.x + (size.width / 2)

let centerY = origin.y + (size.height / 2)

return Point(x: centerX, y: centerY)

set(newCenter) {

origin.x = newCenter.x - (size.width / 2)

origin.y = newCenter.y - (size.height / 2)

var square = Rect(origin: Point(x: 0.0, y: 0.0),

size: Size(width: 10.0, height: 10.0))

let initialSquareCenter = square.center

square.center = Point(x: 15.0, y: 15.0)

println("square.origin is now at (\(square.origin.x), \(square.origin.y))")

// Impresiones "square.origin se encuentra ahora en (10.0,


10.0)"
Este ejemplo define tres estructuras para trabajar con formas geomtricas:
Punto encapsula una (x, y) de coordenadas.
Tamao encapsula una anchura y una altura .
Rect define un rectngulo por un punto de origen y un tamao.
El Rect estructura tambin proporciona una propiedad calculada llamado centro . La
posicin central actual de un Rect siempre se puede determinar a partir de
su origen y tamao , y por lo que no es necesario almacenar el punto central como
un explcito Point valor. En su lugar, Rect define un captador de encargo y setter
para una variable de llamada computarizada centro , para que pueda trabajar con el
rectngulo del centro como si fuera una propiedad real almacenado.
El ejemplo anterior crea una nueva Rect variable
llamada plaza . El cuadrado variable se inicializa con un punto de origen de (0,
0) , y una anchura y una altura de 10 . Esta plaza est representado por el cuadrado
azul en el diagrama a continuacin.
La plaza de la variable centro propiedad se accede luego a travs de la sintaxis con
punto ( square.center ), lo que hace que el captador de centro para ser llamado,
para recuperar el valor actual de la propiedad. En lugar de devolver un valor existente,
el comprador realmente calcula y devuelve un nuevo punto para representar el centro

132

de la plaza. Como se puede ver arriba, el getter devuelve correctamente un punto central
de (5, 5) .
El centro de la propiedad se establece a continuacin, a un nuevo valor de (15,
15) , que se mueve a la plaza arriba y hacia la derecha, a la nueva posicin mostrada
por el cuadrado de color naranja en el siguiente diagrama. Ajuste del centro de la
propiedad llama al colocador de centro , que modifica la x y Y los valores de la
almacenada origen propiedad, y se mueve hacia la plaza a su nueva posicin.



Taquigrafa Declaracin Setter
Si seleccionador de propiedades computarizada no define un nombre para el nuevo
valor que se determine, el nombre predeterminado nuevoValor se utiliza. Aqu hay
una versin alternativa de la Rect estructura, que se aprovecha de esta notacin
abreviada:

struct AlternativeRect {

var origin = Point()

var size = Size()

var center: Point {

get {

let centerX = origin.x + (size.width / 2)

let centerY = origin.y + (size.height / 2)

return Point(x: centerX, y: centerY)

133

set {

origin.x = newValue.x - (size.width / 2)

origin.y = newValue.y - (size.height / 2)

}
Slo lectura Propiedades calculadas
Una propiedad calculada con un captador pero ningn organismo que se conoce como
una propiedad calculada de slo lectura . Una propiedad de slo lectura computarizada
siempre devuelve un valor, y se puede acceder a travs de la sintaxis con punto, pero no
se puede ajustar a un valor diferente.
NOTA
Debe declarar propiedades-incluyendo calculados propiedades de slo lectura-como
propiedades de las variables calculadas con la var palabra clave, porque su valor no es
fijo. El let palabra clave slo se utiliza para propiedades constantes, para indicar que
sus valores no se pueden cambiar una vez que se establecen como parte de inicializacin
de instancia.
Se puede simplificar la declaracin de un solo lectura propiedad calculada mediante la
eliminacin de la getpalabra clave y sus apoyos:

struct Cuboid {

var width = 0.0, height = 0.0, depth = 0.0

var volume: Double {

return width * height * depth

let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)

println("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")

// imprime "el volumen de fourByFiveByTwo es 40.0"


En este ejemplo se define una nueva estructura llamada Cuboide , lo que representa
una caja rectangular 3D con anchura , altura y profundidad propiedades. Esta
estructura tambin tiene una propiedad de slo lectura computarizada
llamado volumen , que calcula y devuelve el volumen actual del cuboides. No tiene
sentido queel volumen sea configurable, porque sera ambiguo en cuanto a qu
valores de anchura , altura y profundidadse debe utilizar para un
determinado volumen de valor. Sin embargo, es til para un cuboide para
proporcionar una propiedad de slo lectura computarizada para permitir a los usuarios
externos para descubrir su volumen calculado actual.
Los observadores de la propiedad
Observadores de Propiedad observan y responden a los cambios en el valor de una
propiedad.Observadores de propiedad son llamados cada vez que el valor de una

134

propiedad se establece, incluso si el nuevo valor es el mismo que el valor actual de la


propiedad.
Puede agregar observadores de propiedad a ninguna propiedad en que se definen,
adems de propiedades almacenadas perezosos. Tambin puede agregar los
observadores de propiedad a cualquier propiedad heredada (si almacena o calcula) por
razones imperiosas de la propiedad dentro de una subclase. Primordial de la propiedad
se describe en Overriding .
NOTA
No es necesario definir los observadores de propiedad para propiedades calculadas no
anulado, ya que se puede observar y responder a los cambios de su valor directamente
desde setter de la propiedad calculada.
Usted tiene la opcin de definir uno o ambos de estos observadores a una propiedad:
willSet se llama justo antes de que el valor se almacena.
didSet se llama inmediatamente despus de que el nuevo valor se almacena.
Si implementa un willSet observador, se pasa el nuevo valor de la propiedad como
un parmetro constante.Puede especificar un nombre para este parmetro como parte de
su willSet aplicacin. Si decide no escribir el nombre del parmetro y los parntesis
dentro de su aplicacin, el parmetro todava estar disponible con un nombre de
parmetro por defecto de nuevoValor .
Del mismo modo, si implementa un didSet observador, se le pasar un parmetro
constante que contiene el valor de la propiedad antigua. Puede nombrar el parmetro si
lo desea, o utilizar el nombre del parmetro por defecto de oldValue .
NOTA
willSet y didSet observadores no son llamados cuando una propiedad se inicializa
primero. Ellos slo son llamados cuando el valor de la propiedad se establece fuera de
un contexto de inicializacin.
He aqu un ejemplo de willSet y didSet en accin. El ejemplo siguiente define una
nueva clase llamadastepcounter , que rastrea el nmero total de pasos que una
persona toma al caminar. Esta clase puede utilizarse con datos de entrada de un
podmetro u otro contador de pasos para realizar un seguimiento del ejercicio de una
persona durante su rutina diaria.

class StepCounter {

var totalSteps: Int = 0 {

willSet(newTotalSteps) {

println("About to set totalSteps to \(newTotalSteps)")

didSet {

if totalSteps > oldValue {

println("Added \(totalSteps - oldValue) steps")

}
135

let stepCounter = StepCounter()

stepCounter.totalSteps = 200

// Acerca establecer totalSteps a 200

// Aadido 200 pasos

stepCounter.totalSteps = 360

// Acerca establecer totalSteps al 360

// Aadido 160 escalones

stepCounter.totalSteps = 896

// Acerca establecer totalSteps al 896

// Aadido 536 pasos


El stepcounter clase declara un totalSteps propiedad de tipo int . Esta es una
propiedad almacenada conwillSet y didSet observadores.
Los willSet y didSet observadores de totalSteps son llamados cada vez que la
propiedad se le asigna un nuevo valor. Esto es cierto incluso si el nuevo valor es el
mismo que el valor actual.
De este ejemplo willSet observador utiliza un nombre de parmetro personalizado
de newTotalSteps para el prximo valor nuevo. En este ejemplo, simplemente
imprime el valor que se va a establecer.
El didSet observador se llama despus de que el valor de totalSteps se
actualiza. Se compara el nuevo valor de totalSteps contra el valor antiguo. Si el
nmero total de pasos se ha incrementado, se imprime un mensaje para indicar la
cantidad de pasos nuevos se han tomado. El didSet observador no proporciona un
nombre de parmetro personalizado para el valor anterior, y el nombre predeterminado
de oldValue se utiliza en su lugar.
NOTA
Si se asigna un valor a una propiedad dentro de su propio didSet observador, el nuevo
valor que asigne sustituir a la que se acaba de establecer.
Variables globales y locales
Las capacidades descritas anteriormente para la informtica y las propiedades de
observacin tambin estn disponibles para las variables globales y las variables
locales . Las variables globales son variables que se definen fuera de cualquier funcin,
mtodo de cierre, o contexto de tipo. Las variables locales son variables que se definen
dentro de una funcin, mtodo, o el contexto de cierre.
Las variables globales y locales que pueda haber tenido en los captulos anteriores,
todos se hanalmacenado las variables . Variables almacenadas, como propiedades
almacenadas, proporcionan almacenamiento para un valor de un determinado tipo y
permiten que el valor que se fijar y se recupera.
Sin embargo, tambin se pueden definir variables calculadas y definir observadores
para las variables almacenadas, ya sea en un mbito global o local. Las variables
calculadas calculan en lugar de almacenar un valor, y se escriben de la misma manera
como las propiedades calculadas.
NOTA

136

Constantes y variables globales se calculan siempre con pereza, de una manera similar
a to Lazy Stored Properties. A diferencia de las propiedades almacenados perezosos,
constantes y variables globales no necesitan ser marcados con el lazy modificador.
Constantes y variables locales no se calculan perezosamente.
Tipo de Propiedades
Propiedades de instancia son las propiedades que pertenecen a una instancia de un tipo
particular. Cada vez que se crea una nueva instancia de ese tipo, tiene su propio
conjunto de valores de la propiedad, separada de cualquier otra instancia.
Tambin puede definir propiedades que pertenecen al tipo de s mismo, no a cualquier
instancia de ese tipo.Slo habr alguna vez una copia de estas propiedades, no importa
cuntas instancias de ese tipo que crean.Estos tipos de propiedades se
denominan propiedades de tipo .
Propiedades de tipo son tiles para definir los valores que son universales para todas
las instancias de un tipo particular, tal como una propiedad constante que todas las
instancias pueden utilizar (como una constante esttica en C), o una propiedad variable
que almacena un valor que es global para todos los instancias de ese tipo (como una
variable esttica en C).
Para los tipos de valor (es decir, estructuras y enumeraciones), puede definir
almacenado y calculado propiedades de tipo. Para las clases, puede definir slo
propiedades de tipo computados.
Propiedades de tipo almacenados para los tipos de valor pueden ser variables o
constantes. Propiedades de tipo calculadas siempre se declaran como propiedades de las
variables, en la misma forma que las propiedades de instancia computados.
NOTA
A diferencia de propiedades de la instancia almacenados, siempre hay que dar
propiedades de tipo almacenado un valor por defecto. Esto es porque el tipo en s no
tiene un inicializador que puede asignar un valor a una propiedad de tipo almacenado en
tiempo de inicializacin.
Escriba Propiedad Sintaxis
En C y Objective-C, se define constantes estticas y variables asociadas a un tipo
como globales variables estticas. En Swift, sin embargo, las propiedades del tipo se
escriben como parte de la definicin del tipo, entre llaves exteriores del tipo, y cada
propiedad tiene el mbito de tipo explcitamente al tipo que soporta.
Usted define las propiedades del tipo para los tipos de valor con la esttica de
palabras clave y propiedades de tipo para los tipos de clase con la clase de palabras
clave. El siguiente ejemplo muestra la sintaxis de propiedades de tipo almacenados y
calculados:

struct SomeStructure {

static var storedTypeProperty = "Some value."

static var computedTypeProperty: Int {

// return an Int value here

}
137

enum SomeEnumeration {

static var storedTypeProperty = "Some value."

static var computedTypeProperty: Int {

// Devuelve un valor int aqu

class SomeClass {

class var computedTypeProperty: Int {

// Devuelve un valor int aqu

}
NOTA
Los ejemplos calculados tipo de propiedad anteriores son para propiedades de tipo de
slo lectura computados, pero tambin es posible definir propiedades de estilo
calculados con la misma sintaxis que para las propiedades de instancia calculados de
lectura-escritura.
Consulta y ajuste del tipo de Propiedades
Tipo propiedades se consultan y establecen con la sintaxis con punto, al igual que las
propiedades de instancia. Sin embargo, las propiedades del tipo se consultan y
establecen en el tipo , no en una instancia de ese tipo. Por ejemplo:

println(SomeClass.computedTypeProperty)

// imprime "42"

println(SomeStructure.storedTypeProperty)

// imprime "algn valor."

SomeStructure.storedTypeProperty = "Another value."

println(SomeStructure.storedTypeProperty)

// imprime "otro valor."


Los ejemplos que siguen utilizan dos propiedades de tipo almacenados como parte de
una estructura que los modelos de un metro de nivel de audio para un nmero de canales
de audio. Cada canal tiene un nivel de audio de nmero entero entre 0 y 10 inclusive.
La siguiente figura ilustra cmo dos de estos canales de audio se pueden combinar para
modelar un medidor de nivel de audio estreo. Cuando el nivel de audio de un canal
es 0 , ninguna de las luces de ese canal estn encendidos Cuando el nivel de audio
es 10 , todas las luces de ese canal son lit. En esta figura, el canal de la izquierda tiene
un nivel de corriente de 9 , y el canal derecho tiene un nivel actual de 7 :

138


Los canales de audio descritos anteriormente estn representados por instancias de
la AudioChannelestructura:

struct AudioChannel {

static let thresholdLevel = 10

static var maxInputLevelForAllChannels = 0

var currentLevel: Int = 0 {

didSet {

if currentLevel > AudioChannel.thresholdLevel {

// cap the new audio level to the threshold level

currentLevel = AudioChannel.thresholdLevel

if currentLevel > AudioChannel.maxInputLevelForAllChannels {

// store this as the new overall maximum input level

AudioChannel.maxInputLevelForAllChannels = currentLevel

}
El AudioChannel estructura define dos propiedades de tipo almacenados en apoyo
de su funcionalidad. El primero, thresholdLevel , define el valor de umbral
mximo un nivel de audio puede tomar. Este es un valor constante de 10 para todos
los AudioChannel casos. Si una seal de audio llega con un valor superior a 10 , que
se limitar a este valor de umbral (como se describe a continuacin).

139

La segunda propiedad type es una variable almacenada propiedad


llamada maxInputLevelForAllChannels .Esto hace un seguimiento del valor de
entrada mximo que haya sido recibida por cualquier AudioChannelinstancia. Se
inicia con un valor inicial de 0 .
El AudioChannel estructura tambin define una propiedad de instancia almacenado
llamado CurrentLevel , que representa el nivel de audio actual del canal en una
escala de 0 a 10 .
El CurrentLevel propiedad tiene un didSet observador propiedad para comprobar
el valor de CurrentLevelcada vez que se establece. Este observador realiza dos
comprobaciones:
Si el nuevo valor de CurrentLevel es mayor que el
permitido thresholdLevel , las tapas de observadores
propiedad CurrentLevel a thresholdLevel .
Si el nuevo valor de CurrentLevel (despus de cualquier nivelacin) es mayor
que cualquier valor previamente recibida por cualquier AudioChannel ejemplo,
el observador propiedad almacena el nuevoCurrentLevel valor en
los maxInputLevelForAllChannels propiedad esttica.
NOTA
En el primero de estos dos controles, los didSet conjuntos de
observacin CurrentLevel a un valor diferente.Esto no significa, sin embargo,
hacen que el observador que se llamar de nuevo.
Usted puede utilizar el AudioChannel estructura para crear dos nuevos canales de
audio llamados leftChannely rightChannel , para representar los niveles de
audio de un sistema de sonido estreo:

var leftChannel = AudioChannel()

var rightChannel = AudioChannel()


If you set the currentLevel of the left channel to 7, you can see that
the maxInputLevelForAllChannels type property is updated to equal 7:

leftChannel.currentLevel = 7

println(leftChannel.currentLevel)

// prints "7"

println(AudioChannel.maxInputLevelForAllChannels)

// imprime "7"
Si se intenta establecer la CurrentLevel de la derecha del canal a 11 , se puede ver
que el canal derechoCurrentLevel propiedad est limitado al valor mximo de 10 ,
y el maxInputLevelForAllChannels tipo de propiedad se ha actualizado a la
igualdad 10 :

rightChannel.currentLevel = 11

println(rightChannel.currentLevel)

// imprime "10"

println(AudioChannel.maxInputLevelForAllChannels)

// imprime "10"

140

Mtodos
En esta pgina
Mtodos son funciones que estn asociadas con un tipo particular. Las clases,
estructuras y enumeraciones todos pueden definir mtodos de instancia, que encapsulan
tareas y funciones especficas para trabajar con una instancia de un tipo dado. Las
clases, estructuras y enumeraciones tambin pueden definir mtodos de tipo, que se
asocian con el propio tipo. Tipo mtodos son similares a los mtodos de clase en
Objective-C.
El hecho de que las estructuras y enumeraciones pueden definir mtodos en Swift es
una gran diferencia con C y Objective-C. En Objective-C, las clases son los nicos tipos
que pueden definir mtodos. En Swift, puede elegir si desea definir una clase, estructura
o enumeracin, y an as tener la flexibilidad de definir mtodos en el tipo que cree.
Mtodos de instancia
Los mtodos de instancia son funciones que pertenecen a instancias de una clase,
estructura o enumeracin particular. Apoyan a la funcionalidad de los casos, ya sea
proporcionando formas de acceder y modificar las propiedades de instancia, o
proporcionando una funcionalidad relacionada con el propsito de la instancia.Los
mtodos de instancia tienen exactamente la misma sintaxis que las funciones, como se
describe enFunciones .
Usted escribe un mtodo de instancia dentro de las llaves de apertura y cierre del tipo al
que pertenece. Un mtodo de instancia tiene acceso implcito a todos los dems
mtodos de instancia y las propiedades de ese tipo. Un mtodo de instancia slo se
puede llamar a una instancia especfica del tipo al que pertenece. No se puede llamar de
forma aislada, sin una instancia existente.
He aqu un ejemplo que define un sencillo contador de la clase, que se puede
utilizar para contar el nmero de veces que se produce una accin:

class Counter {

var count = 0

func increment() {

count++

func incrementBy(amount: Int) {

count += amount

func reset() {

count = 0

}
El contador de clase define tres mtodos de instancia:
Valor mnimo incrementa el contador por 1 .
incrementBy (cantidad: Int) incrementa el contador por un importe
entero especificado.

141

restablecer restablece el contador a cero.


El contador de la clase tambin declara una propiedad de variable, cuenta , para
no perder de vista el valor actual del contador.
Usted llama a los mtodos de instancia con el mismo sintaxis con punto como
propiedades:

let counter = Counter()

// the initial counter value is 0

counter.increment()

// the counter's value is now 1

counter.incrementBy(5)

// the counter's value is now 6

counter.reset()

// the counter's value is now 0


Nombres locales y parmetros externos para los mtodos
Parmetros de la funcin pueden tener tanto un nombre local (para el uso en el cuerpo
de la funcin) y un nombre externo (para su uso cuando se llama a la funcin), como se
describe en el parmetro External Nombres . Lo mismo es cierto para los parmetros del
mtodo, porque los mtodos son slo funciones que estn asociadas con un tipo. Sin
embargo, el comportamiento predeterminado de los nombres locales y nombres
externos es diferente para las funciones y mtodos.
Mtodos de Swift son muy similares a sus contrapartes en Objective-C. Como en
Objective-C, el nombre de un mtodo en el Swift se refiere tpicamente a primer
parmetro del mtodo que utiliza una preposicin comocon , para , o por , como se
ve en la incrementBy mtodo de la anterior Contador ejemplo de la clase. El uso
de una preposicin permite el mtodo para ser ledo como una sentencia cuando se le
llama. Swift hace que esta convencin de nombres mtodo establecido fcil escribir
utilizando un enfoque predeterminado diferente para los parmetros del mtodo que se
utiliza para los parmetros de funcin.
En concreto, Swift da la primera nombre de parmetro en un mtodo un nombre de
parmetro local de forma predeterminada, y da los nombres de los parmetros segundo
y siguientes ambos locales y nombres de los parmetros externos de manera
predeterminada. Esta convencin coincide con la denominacin tpica y el convenio de
llamada que usted estar familiarizado con los mtodos de escritura de Objective-C, y lo
convierte en mtodo expresivo llamadas sin la necesidad de calificar los nombres de los
parmetros.
Considere esta versin alternativa del contador de clase, que define una forma ms
compleja de laincrementBy mtodo:

class Counter {

var count: Int = 0

func incrementBy(amount: Int, numberOfTimes: Int) {

count += amount * numberOfTimes


142

}
Esta incrementBy mtodo tiene dos parmetroscantidad y numberOfTimes . De forma predeterminada, Swift
trata cantidad tan slo un nombre local, pero trata numberOfTimes como tanto
local y un nombre externo.Llamar al mtodo de la siguiente manera:

let counter = Counter()

counter.incrementBy(5, numberOfTimes: 3)

// Valor del contador es ahora de 15 aos


No es necesario definir un nombre de parmetro externo para el primer valor del
argumento, porque su propsito es claro desde el nombre de la
funcin incrementBy . El segundo argumento, sin embargo, es calificado por un
nombre de parmetro externo para realizar su propsito claro cuando se llama al
mtodo.
Este comportamiento predeterminado trata con eficacia el mtodo como si hubiera
escrito un smbolo de almohadilla ( # ) antes de la numberOfTimes parmetro:

func incrementBy(amount: Int, #numberOfTimes: Int) {

count += amount * numberOfTimes

}
El comportamiento predeterminado descrito anteriormente significa que las definiciones
de mtodo en Swift se escriben con el mismo estilo gramatical como Objective-C, y se
llaman de una manera natural, expresiva.
Modificacin de parmetros externos Comportamiento Nombre de Mtodos
A veces es til para proporcionar un nombre de parmetro externo para el primer
parmetro de un mtodo, a pesar de que este no es el comportamiento
predeterminado. Usted puede aadir un nombre externo explcito a ti mismo, o puede
anteponer el nombre del primer parmetro con un smbolo de hash para utilizar el
nombre local como un nombre externo tambin.
Por el contrario, si usted no desea proporcionar un nombre externo para el segundo o
subsiguiente parmetro de un mtodo, reemplazar el comportamiento predeterminado
mediante un carcter de subrayado ( _ ) como un nombre de parmetro externo explcito
para ese parmetro.
El auto de la propiedad
Cada instancia de un tipo tiene una propiedad llamada implcita auto , que es
exactamente equivalente a la propia instancia. Se utiliza el auto propiedad para hacer
referencia a la instancia actual dentro de sus propios mtodos de instancia.
El incremento de mtodo en el ejemplo anterior se podra haber escrito as:

func increment() {

self.count++

}
En la prctica, no es necesario escribir uno mismo en su cdigo muy a menudo. Si
usted no escribe explcitamente auto , Swift asume que se est haciendo referencia a

143

una propiedad o mtodo de la instancia actual cada vez que utilice una propiedad
conocida o nombre de mtodo dentro de un mtodo. Esta suposicin se demostr
mediante el uso de recuento (en lugar de self.count ) dentro de los tres mtodos
de instancia para Contador .
La principal excepcin a esta regla se produce cuando un nombre de parmetro para un
mtodo de instancia tiene el mismo nombre que una propiedad de esa instancia. En esta
situacin, el nombre del parmetro tiene prioridad, y se hace necesario hacer referencia
a la propiedad de forma ms cualificada. Se utiliza el autopropiedad de distinguir entre
el nombre del parmetro y el nombre de la propiedad.
Aqu, por cuenta de ambigedad entre un parmetro de mtodo llamado x y una
propiedad de instancia que tambin se llama x :

struct Point {

var x = 0.0, y = 0.0

func isToTheRightOfX(x: Double) -> Bool {

return self.x > x

let somePoint = Point(x: 4.0, y: 5.0)

if somePoint.isToTheRightOfX(1.0) {

println("This point is to the right of the line where x == 1.0")

// Impresiones "Este punto est a la derecha de la lnea en


la que x == 1.0"
Sin el auto prefijo, Swift sera asumir que ambos usos de x hace referencia al
parmetro de mtodo llamado x.
Modificacin de tipos de valor desde dentro de los mtodos de instancia
Estructuras y enumeraciones son tipos de valor . De forma predeterminada, las
propiedades de un tipo de valor no se puede modificar desde dentro de sus mtodos de
instancia.
Sin embargo, si tiene que modificar las propiedades de su estructura o enumeracin
dentro de un mtodo en particular, se puede optar por la mutacin de comportamiento
para ese mtodo. El mtodo puede entonces mutar (es decir, cambiar) sus propiedades
desde dentro del mtodo, y cualquier cambio que haga en se escriben de nuevo a la
estructura original cuando el mtodo termina. El mtodo tambin se puede asignar una
nueva instancia a su implcita auto propiedad, y esta nueva instancia reemplazar a la
existente cuando el mtodo termina.
Usted puede optar por este comportamiento mediante la colocacin de la mutacin
de la palabra clave antes de la func palabra clave para ese mtodo:

struct Point {

var x = 0.0, y = 0.0

mutating func moveByX(deltaX: Double, y deltaY: Double) {


144

x += deltaX

y += deltaY

var somePoint = Point(x: 1.0, y: 1.0)

somePoint.moveByX(2.0, y: 3.0)

println("The point is now at (\(somePoint.x), \(somePoint.y))")

// imprime "El punto es ahora en (3.0, 4.0)"


El Punto estructura anterior define una mutacin moveByX mtodo, que mueve
un Punto de ejemplo, por una cierta cantidad. En lugar de devolver un nuevo punto,
este mtodo en realidad modifica el punto en el que se llama. La mutacin de la
palabra clave se aade a su definicin para que pueda modificar sus propiedades.
Tenga en cuenta que usted no puede llamar a un mtodo mutando en una constante del
tipo de estructura, ya que sus propiedades no se pueden cambiar, incluso si son
propiedades de las variables, como se describe enPropiedades almacenados de
Estructura instancias constantes :

let fixedPoint = Point(x: 3.0, y: 3.0)

fixedPoint.moveByX(2.0, y: 3.0)

// Esta informar de un error


Asignar a la libre dentro de un mtodo Mutating
Mtodos mutantes pueden asignar una instancia completamente nueva de lo
implcito auto propiedad. ElPunto ejemplo anterior podra haber sido escrito de la
siguiente manera en su lugar:

struct Point {

var x = 0.0, y = 0.0

mutating func moveByX(deltaX: Double, y deltaY: Double) {

self = Point(x: x + deltaX, y: y + deltaY)

}
This version of the mutating moveByX method creates a brand new structure Esta
versin de la mutacin moveByX mtodo crea una nueva estructura de marcas
cuya x y Y los valores se establecen en la ubicacin de destino. El resultado final de
llamar a esta versin alternativa del mtodo ser exactamente la misma que para llamar
a la versin anterior.
La mutacin de los mtodos para enumeraciones puede establecer el
implcito auto parmetro que ser miembro diferente de la misma enumeracin:

enum TriStateSwitch {

case Off, Low, High

mutating func next() {

switch self {
145

case Off:

self = Low

case Low:

self = High

case High:

self = Off

var ovenLight = TriStateSwitch.Low

ovenLight.next()

// OvenLight es ahora igual a .high

ovenLight.next()

// OvenLight es ahora igual a .OFF


Este ejemplo define una enumeracin para un interruptor de tres estados. Los ciclos de
conmutacin entre los tres estados de energa diferentes ( Off , Bajo y Alto ) cada
vez que su siguiente mtodo se llama.
Tipo Mtodos
Los mtodos de instancia, como se describe ms arriba, son los que se denominan en
una instancia de un tipo particular. Tambin puede definir los mtodos que se llaman en
el propio tipo. Estos tipos de mtodos son llamados mtodos de tipo . Usted indica
mtodos de tipo para las clases escribiendo la palabra clave de clase antes del
mtodo func palabra clave, y escribe mtodos para estructuras y enumeraciones
escribiendo la palabra clave static antes del mtodo func palabra clave.
NOTA
En Objective-C, se pueden definir mtodos de nivel de tipo slo para las clases de
Objective-C. En Swift, se pueden definir mtodos de nivel de tipo para todas las clases,
estructuras y enumeraciones. Cada mtodo tiene el mbito de tipo explcitamente al tipo
que soporta.
Tipo mtodos se denominan con la sintaxis con punto, al igual que los mtodos de
instancia. Sin embargo, se llama a mtodos de tipo del tipo, no en una instancia de ese
tipo. He aqu cmo se llama a un mtodo de tipo en una clase llamada AlgunaClase :

class SomeClass {

class func someTypeMethod() {

// type method implementation goes here

SomeClass.someTypeMethod()
Dentro del cuerpo de un mtodo de tipo, lo implcito auto propiedad se refiere al tipo
en s, en lugar de una instancia de ese tipo. Para las estructuras y enumeraciones, esto
significa que usted puede utilizar auto para eliminar la ambigedad entre las

146

propiedades estticas y parmetros del mtodo esttico, tal como lo hace para las
propiedades de instancia y los parmetros del mtodo de instancia.
Ms en general, cualquier mtodo y propiedad nombres no calificados que se utilizan
dentro del cuerpo de un mtodo tipo se referirn a otros mtodos y propiedades de nivel
de tipo. Un mtodo de tipo puede llamar a otro mtodo de tipo con el nombre del otro
mtodo, sin necesidad de un prefijo con el nombre del tipo. Del mismo modo, los
mtodos de tipo de estructuras y enumeraciones pueden tener acceso a las propiedades
estticas utilizando el nombre de la propiedad esttica sin un prefijo de nombre de tipo.
El ejemplo siguiente define una estructura llamada LevelTracker , que rastrea el
progreso del jugador a travs de los diferentes niveles o etapas de un juego. Es un juego
para un solo jugador, pero puede almacenar informacin para mltiples jugadores en un
solo dispositivo.
Todos los niveles del juego (aparte de nivel uno) estn bloqueadas cuando el partido se
jug por primera vez.Cada vez que un jugador termina un nivel, ese nivel est
desbloqueado para todos los jugadores en el dispositivo. El LevelTracker estructura
utiliza propiedades y mtodos estticos para no perder de vista que los niveles del juego
han sido desbloqueados. Tambin realiza un seguimiento del nivel actual para un
jugador individual.

struct LevelTracker {

static var highestUnlockedLevel = 1

static func unlockLevel(level: Int) {

if level > highestUnlockedLevel { highestUnlockedLevel = level }

static func levelIsUnlocked(level: Int) -> Bool {

return level <= highestUnlockedLevel

var currentLevel = 1

mutating func advanceToLevel(level: Int) -> Bool {

if LevelTracker.levelIsUnlocked(level) {

currentLevel = level

return true

} else {

return false

}
El LevelTracker estructura no pierde de vista el nivel ms alto que cualquier
jugador ha desbloqueado. Este valor se almacena en una propiedad esttica
llamada highestUnlockedLevel .
LevelTracker tambin define dos funciones de tipo para trabajar con
el highestUnlockedLevel propiedad. La primera es una funcin de tipo de

147

llamada unlockLevel , que actualiza el valor de highestUnlockedLevel cada


vez que un nuevo nivel est desbloqueado. La segunda es una funcin de tipo de
conveniencia denominadalevelIsUnlocked , que devuelve verdadero si un
nmero determinado nivel es ya desbloqueado. (Tenga en cuenta que estos mtodos de
tipo pueden acceder al highestUnlockedLevel propiedad esttica sin necesidad
de que escribirlo como LevelTracker.highestUnlockedLevel .)
Adems de sus mtodos de propiedad y de tipo esttico, LevelTracker un
seguimiento del progreso de un jugador individual a travs del juego. Utiliza una
propiedad de instancia denominada CurrentLevel para seguir el nivel de un jugador
que est jugando.
Para ayudar a administrar el CurrentLevel propiedad, LevelTracker define un
mtodo de instancia denominadoadvanceToLevel . Antes de
actualizar CurrentLevel , este mtodo comprueba si el nuevo nivel solicitado est
ya desbloqueados. El advanceToLevel mtodo devuelve un valor booleano para
indicar si es o no en realidad era capaz de establecer CurrentLevel .
El LevelTracker estructura se utiliza con el jugador de clase, se muestra a
continuacin, realizar un seguimiento y actualizar el progreso de un jugador individual:

class Player {

var tracker = LevelTracker()

let playerName: String

func completedLevel(level: Int) {

LevelTracker.unlockLevel(level + 1)

tracker.advanceToLevel(level + 1)

init(name: String) {

playerName = name

}
El player de la clase crea una nueva instancia de LevelTracker para seguir el
progreso de ese jugador.Tambin proporciona un mtodo
llamado completedLevel , que se llama cada vez que un jugador completa un nivel
particular. Este mtodo desbloquea el siguiente nivel para todos los jugadores y
actualiza el progreso del jugador para moverse al siguiente nivel. (El valor de retorno
booleano de advanceToLevel se ignora, ya que el nivel es conocido por haber sido
desbloqueado por la llamada a LevelTracker.unlockLevel en el rubro anterior.)
Puede crear una instancia del player de clase para un nuevo jugador, y ver lo que
sucede cuando el jugador completa el nivel uno:

var player = Player(name: "Argyrios")

player.completedLevel(1)

println("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)")

// imprime "ms alto nivel desbloqueado es ahora 2"


148

Si crea un segundo jugador, quien intenta mover a un nivel que todava no est
desbloqueado por cualquier jugador en el juego, el intento de establecer el nivel actual
del jugador falla:

player = Player(name: "Beto")

if player.tracker.advanceToLevel(6) {

println("player is now on level 6")

} else {

println("level 6 has not yet been unlocked")

// Impresiones "nivel 6 no ha sido desbloqueado"



Los subndices
Las clases, estructuras y enumeraciones pueden definir subndices , que son accesos
directos para acceder a los elementos de miembros de una coleccin, una lista o
secuencia. Se utiliza subndices para establecer y recuperar valores de ndice sin
necesidad de mtodos diferentes para configuracin y recuperacin. Por ejemplo, puede
acceder a los elementos de una Array instancia como someArray [Index] y
elementos en un Dictionary ejemplo como someDictionary [key] .
Se pueden definir varios subndices para un solo tipo, y la sobrecarga subndice
adecuado para su uso se selecciona en funcin del tipo de valor ndice que se pasa al
subndice. Los subndices no se limitan a una sola dimensin, y se pueden definir
subndices con mltiples parmetros de entrada para satisfacer las necesidades de su
tipo de encargo.
Sintaxis Subndice
Los subndices le permiten consultar instancias de un tipo escribiendo uno o ms
valores entre corchetes despus del nombre de la instancia. Su sintaxis es similar a las
sintaxis del mtodo de instancia y sintaxis de la propiedad calculada. Usted escribe
definiciones subndice con el subndice de palabras clave, y especificar uno o ms
parmetros de entrada y un tipo de retorno, en la misma forma que los mtodos de
instancia. A diferencia de los mtodos de instancia, los subndices pueden ser de lectura
y escritura o slo lectura. Este comportamiento se comunica por un get y set de la
misma manera que para las propiedades calculadas:

subscript(index: Int) -> Int {

get {

// return an appropriate subscript value here

set(newValue) {

// perform a suitable setting action here

149

El tipo de newValue es el mismo que el valor de retorno de la subndice. Al igual que


con las propiedades calculadas, usted puede optar por no especificar del
setter (newValue ) parmetro. Un parmetro por defecto llamada newValue se
proporciona a su organismo si no se proporciona una t mismo.
Al igual que con las propiedades calculada de slo lectura, se puede eliminar
el get palabra clave para subndices de slo lectura:

subscript(index: Int) -> Int {

// Devolver un valor apropiado en este subndice

}
He aqu un ejemplo de una aplicacin de slo lectura subndice, que define
un TimesTable estructura para representar un n -veces-tabla de enteros:

struct TimesTable {

let multiplier: Int

subscript(index: Int) -> Int {

return multiplier * index

let threeTimesTable = TimesTable(multiplier: 3)

println("six times three is \(threeTimesTable[6])")

// grabados "seis veces tres es de 18"


En este ejemplo, una nueva instancia de TimesTable se cre para representar el tres
veces a la mesa. Esto se indica mediante el paso de un valor de 3 a de la
estructura inicializador como el valor a usar para la instancia
de multiplicador de parmetros.
Puede consultar el threeTimesTable instancia llamando su subndice, como se
muestra en la llamada athreeTimesTable [6] . Esto pide la sexta entrada en el
tres veces a la mesa, que devuelve un valor de 18 , o 3veces 6 .
NOTA
Un n -veces-tabla se basa en una regla matemtica fija. No es adecuado
fijar threeTimesTable [someIndex]a un nuevo valor, por lo que el subndice
de TimesTable se define como una de slo lectura subndice.
Uso Subndice
El significado exacto de "subndice" depende del contexto en el que se utiliza. Los
subndices se utilizan tpicamente como un acceso directo para acceder a los elementos
de miembro en una coleccin, una lista o secuencia. Usted es libre de aplicar los
subndices de la manera ms apropiada para su clase o la funcionalidad de la estructura.
Por ejemplo, de Swift Diccionario tipo implementa un subndice para establecer y
recuperar los valores almacenados en un Diccionario ejemplo. Puede establecer un
valor en un diccionario, proporcionando una clave de tipo de clave del diccionario entre
llaves subndice, y la asignacin de un valor de valor de tipo de diccionario para el
subndice:

150

var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]

numberOfLegs["bird"] = 2
El ejemplo anterior define una variable llamada numberOfLegs y lo inicializa con un
diccionario literal que contiene tres pares clave-valor. El tipo de
la numberOfLegs diccionario se infiere que [Cadena: Int] . Despus de crear el
diccionario, este ejemplo utiliza la asignacin subndice aadir una cuerda clave
de "pjaro" y unInt valor de 2 al diccionario.
Para obtener ms informacin acerca de Diccionario subndices, consulte Acceso y
Modificacin de un diccionario .
NOTA
El Dictionary tipo de Swift implementa su subscripting clave-valor como un
subndice que toma y recibe unaopcional tipo. Para los numberOfLegs diccionario de
ms arriba, el subndice de clave y valor toma y devuelve un valor de tipo int? , o "int
opcional". El Diccionario de tipo utiliza un tipo subndice opcional para modelar el
hecho de que no todas las teclas tendr un valor, y para dar una forma de eliminar un
valor de una clave mediante la asignacin de un nulo valor para esa llave.
Opciones Subndice
Los subndices pueden tomar cualquier nmero de parmetros de entrada, y estos
parmetros de entrada pueden ser de cualquier tipo. Los subndices tambin pueden
devolver cualquier tipo. Los subndices se pueden utilizar parmetros variables y
parmetros variadic, pero no pueden utilizar in-out parmetros o proporcionar valores
de los parmetros por defecto.
Una clase o estructura puede proporcionar tantas implementaciones subndice ya que
necesita, y el subndice adecuado para ser utilizado se infiere sobre la base de los tipos
de valor o los valores que se encuentran dentro de las llaves de subndice en el punto
que se utiliza el subndice. Esta definicin de mltiples subndices se conoce
como sobrecarga subndice .
Si bien es ms comn para un subndice para tomar un solo parmetro, tambin puede
definir un subndice con mltiples parmetros si es apropiado para su tipo. El ejemplo
siguiente define una matriz de estructura, lo que representa una matriz
bidimensional de dobles valores. El Matrix subndice de estructura toma dos
parmetros enteros:

struct Matrix {

let rows: Int, columns: Int

var grid: [Double]

init(rows: Int, columns: Int) {

self.rows = rows

self.columns = columns

grid = Array(count: rows * columns, repeatedValue: 0.0)

func indexIsValidForRow(row: Int, column: Int) -> Bool {


151

return row >= 0 && row < rows && column >= 0 && column < columns

subscript(row: Int, column: Int) -> Double {

get {

assert(indexIsValidForRow(row, column: column), "Index out of range")

return grid[(row * columns) + column]

set {

assert(indexIsValidForRow(row, column: column), "Index out of range")

grid[(row * columns) + column] = newValue

}
Matrix proporciona un inicializador que toma dos parmetros
denominados filas y columnas , y crea una matriz que es lo suficientemente grande
para almacenar filas * columnas valores de tipo doble . Cada posicin en la
matriz se le da un valor inicial de 0,0 . Para lograr esto, el tamao de la matriz, y un
valor de la celda inicial de 0.0 , se pasan a un inicializador de matriz que crea e
inicializa una nueva matriz del tamao correcto. Este inicializador se describe con ms
detalle en la creacin e inicializacin de una matriz .
Usted puede construir una nueva matriz de ejemplo haciendo pasar una fila
adecuada y el recuento de la columna a su inicializador:

var matrix = Matrix(rows: 2, columns: 2)


El ejemplo anterior crea una nueva matriz de ejemplo con dos filas y dos
columnas. La rejilla de matriz para este Matrix ejemplo es efectivamente una
versin aplanada de la matriz, como se lee desde la parte superior izquierda a la inferior
derecha:


Los valores en la matriz pueden ser establecidas pasando los valores de fila y columna
en el subndice, separados por una coma:

matrix[0, 1] = 1.5

matrix[1, 0] = 3.2

152

Estas dos afirmaciones llaman setter del subndice para establecer un valor de 1,5 en la
posicin superior derecha de la matriz (donde fila es 0 y la columna es 1 ),
y 3,2 en la posicin inferior izquierda (donde fila es1 y la columna es 0 ):


El Matrix get y set de subndice ambos contienen una afirmacin para comprobar que
el subndice de fila ycolumna valores son vlidos. Para ayudar con estas
afirmaciones, Matrix incluye un mtodo de conveniencia
denominada indexIsValidForRow (_: :) columna , que comprueba si el
solicitado fila y columna estn dentro de los lmites de la matriz:

func indexIsValidForRow(row: Int, column: Int) -> Bool {

return row >= 0 && row < rows && column >= 0 && column < columns

}
Una afirmacin se activa si se intenta acceder a un subndice que se encuentra fuera de
los lmites de la matriz:

let someValue = matrix[2, 2]

// Esto desencadena una asercin, porque [2, 2] se


encuentra fuera de los lmites de la matriz

Herencia
Una clase puede heredar mtodos, propiedades y otras caractersticas de otra
clase. Cuando una clase hereda de otra, la clase que hereda se conoce como
una subclase , y la clase que hereda de que se conoce como su superclase . La herencia
es un comportamiento fundamental que diferencia a las clases de otros tipos en Swift.
Clases en Swift pueden llamar y acceso mtodos, las propiedades y los subndices que
pertenecen a su superclase y pueden proporcionar sus propias versiones primordiales de
esos mtodos, propiedades y subndices para refinar o modificar su
comportamiento. Swift ayuda a asegurar las sustituciones son correctos mediante la
comprobacin de que la definicin de anulacin tiene una definicin de superclase a
juego.
Las clases tambin pueden agregar observadores de propiedad de las propiedades
heredadas a fin de ser notificados cuando el valor de una propiedad
cambia. Observadores de propiedad se pueden agregar a cualquier propiedad,
independientemente de si se defini originalmente como una propiedad almacenada o
calculado.
Definicin de una base de la Clase
Cualquier clase que no hereda de otra clase se conoce como una clase base .
NOTA
Clases Swift no heredan de una clase base universal. Las clases se definen sin
especificar una superclase automticamente convertido clases base para que usted pueda
aprovechar.

153

El ejemplo siguiente define una clase base llamada Vehculo . Esta clase base define
una propiedad almacenado llamado currentspeed , con un valor por defecto
de 0.0 (inferir un tipo de propiedad de doble ). Elcurrentspeed valor de la
propiedad es utilizada por una de slo lectura computarizada Cadena propiedad
llamada descripcin para crear una descripcin del vehculo.
El vehculo de la clase base tambin define un mtodo llamado makeNoise . Este
mtodo no hace nada para una base de vehculo instancia, pero ser personalizado
por subclases de vehculos ms adelante:

class Vehicle {

var currentSpeed = 0.0

var description: String {

return "traveling at \(currentSpeed) miles per hour"

func makeNoise() {

// Hacer nada - un vehculo arbitraria no necesariamente


hace un ruido

}
Se crea una nueva instancia de vehculo con la sintaxis de inicializador , que se
escribe como un TypeNameseguida de parntesis vacos:

let someVehicle = Vehicle()


Despus de haber creado un nuevo vehculo instancia, puede acceder a
su descripcin inmueble para imprimir una descripcin legible de la velocidad
actual del vehculo:

println("Vehicle: \(someVehicle.description)")

// Vehculo: viaja a 0.0 kilmetros por hora


El vehculo clase define las caractersticas comunes de un vehculo arbitraria, pero
no sirve de mucho en s mismo. Para que sea ms til, es necesario refinarlo para
describir tipos ms especficos de vehculo.
Subclassing
Subclassing es el acto de fundar una nueva clase en una clase existente. La subclase
hereda las caractersticas de la clase existente, que luego se puede refinar. Tambin
puede aadir nuevas caractersticas a la subclase.
Para indicar que una subclase tiene una superclase, escribir el nombre de subclase antes
del nombre de superclase, separados por dos puntos:

class SomeSubclass: SomeSuperclass {

// Definicin subclase va aqu

}
El ejemplo siguiente define una subclase llamada de bicicletas , con una
superclase de vehculo :

class Bicycle: Vehicle {


154

var hasBasket = false

}
La nueva bicicleta de clase gana automticamente todas las caractersticas
del vehculo , tales como suscurrentspeed y descripcin propiedades y
su makeNoise mtodo.
Adems de las caractersticas que hereda, la bicicleta clase define una nueva
propiedad almacenada,hasBasket , con un valor predeterminado de false (inferir
un tipo de Bool para la propiedad).
Por defecto, cualquier nueva bicicleta instancia se crea no tendr una cesta. Puede
configurar el hasBasketpropiedad a true para un
particular, bicicletas instancia despus de crear esa instancia:

let bicycle = Bicycle()

bicycle.hasBasket = true
Tambin puede modificar el heredado currentspeed propiedad de
una bicicleta de instancia y consultar heredado de la instancia descripcin de
propiedad:

bicycle.currentSpeed = 15.0

println("Bicycle: \(bicycle.description)")

// Bicicletas: viaje de 15,0 kilmetros por hora


Las subclases pueden estar a su vez subclases. El siguiente ejemplo crea una subclase
de bicicletas para una bicicleta de dos asientos conocido como un "tndem":

class Tandem: Bicycle {

var currentNumberOfPassengers = 0

}
Tandem hereda todas las propiedades y mtodos de bicicletas , que a su vez
hereda todas las propiedades y mtodos de vehculo . El Tandem subclase tambin
aade una nueva propiedad almacenado llamadocurrentNumberOfPassengers ,
con un valor por defecto de 0 .
Si crea una instancia de Tandem , se puede trabajar con cualquiera de sus propiedades
nuevas y heredadas, y consultar el de slo lectura Descripcin propiedad se hereda
de vehculo :

let tandem = Tandem()

tandem.hasBasket = true

tandem.currentNumberOfPassengers = 2

tandem.currentSpeed = 22.0

println("Tandem: \(tandem.description)")

// Tandem: viaja a 22,0 millas por hora

155

Anulacin
Una subclase puede proporcionar su propia implementacin personalizada de un mtodo
de instancia, mtodo de clase, propiedad de instancia, propiedad de clase, o subndice
que de otro modo heredar de una superclase. Esto se conoce como primordial .
Para anular una caracterstica que de otro modo se hereda, escribir antes de la definicin
primordial con la override keyword. Si lo hace, aclara que tiene la intencin de
proporcionar una anulacin y no se ha proporcionado una definicin coincidente por
error. Anulacin por accidente puede provocar un comportamiento inesperado, y los
reemplazos sin la anulacin de palabras clave son diagnosticados como un error
cuando se compila el cdigo.
La anulacin de palabras clave tambin solicita al compilador Swift para comprobar
que la superclase de la clase predominante (o uno de sus padres) tiene una declaracin
que coincide con la que nos indic en el aumento al presupuesto. Esta comprobacin
asegura que su definicin primordial es correcta.
Acceso a mtodos de superclase, propiedades y subndices
Cuando usted proporciona un mtodo, propiedad o anulacin subndice para una
subclase, a veces es til usar la aplicacin superclase existentes como parte de su
anulacin. Por ejemplo, se puede refinar el comportamiento de que la aplicacin
existente o almacenar un valor modificado en una variable heredada existente.
Cuando resulte oportuno, se accede a la versin de la superclase de un mtodo, una
propiedad o subndice utilizando el sper prefijo:
Un mtodo reemplazado llamado algunMetodo puede llamar a la versin de la
superclase de algunMetodollamando super.someMethod () dentro de la
implementacin del mtodo de primer orden.
Una propiedad anulado llamado UnaPropiedad puede acceder a la versin de la
superclase deUnaPropiedad como super.someProperty dentro del
captador primordial o aplicacin setter.
Un subndice reemplazado por someIndex puede acceder a la versin de la
superclase del mismo subndice como sper [someIndex] desde dentro de la
aplicacin subndice primordial.
Sustitucin de mtodos
Puede anular un mtodo de instancia o clase heredada para proporcionar una aplicacin
a medida o alternativa del procedimiento dentro de la subclase.
El ejemplo siguiente define una nueva subclase de vehculo llamado tren , lo que
anula el makeNoise mtodo que Train hereda de vehculo :

class Train: Vehicle {

override func makeNoise() {

println("Choo Choo")

}
Si crea una nueva instancia de tren y llamar su makeNoise mtodo, se puede ver
que el tren versin subclase del mtodo se llama:

156

let train = Train()

train.makeNoise()

// Impresiones "Choo Choo"


Propiedades Anulacin
Puede reemplazar una instancia o una clase de bienes heredados para proporcionar su
propio getter y setter personalizado para esa propiedad, o para aadir observadores de
propiedad para permitir la propiedad primordial observar cuando los cambios
subyacentes valor de la propiedad.
Anulacin de la propiedad get y set
Puede proporcionar un captador de encargo (y setter, en su caso) para
anular cualquier propiedad heredada, sin importar si la propiedad heredada se
implementa como una propiedad almacenada o calculado en la fuente. La naturaleza
almacenado o calculado de una propiedad heredada no es conocido por una subclaseslo sabe que la propiedad heredada tiene un cierto nombre y tipo. Siempre se debe
indicar el nombre y el tipo de la propiedad est sustituyendo, para permitir que el
compilador para comprobar que su anulacin coincide con una propiedad superclase
con el mismo nombre y tipo.
Usted puede presentar una propiedad de slo lectura hereda como una propiedad de
lectura-escritura, proporcionando tanto un getter y un setter en su propiedad subclase de
anulacin. No puede, sin embargo, presentar una propiedad de lectura y escritura
heredado como una propiedad de slo lectura.

NOTA
Si usted proporciona un setter como parte de una anulacin de la propiedad, tambin
debe proporcionar un captador para que override. Si no desea modificar el valor de la
propiedad heredada dentro del captador primordial, slo tiene que pasar por el valor
heredado devolviendo super.someProperty del captador,
dondeUnaPropiedad es el nombre de la propiedad que est sustituyendo.
El ejemplo siguiente define una nueva clase llamada de coches , que es una subclase
de vehculo . El cocheclase introduce una nueva propiedad almacenado
llamado artes , con un valor entero por defecto de 1 . Elcoche clase tambin anula
la descripcin de propiedad que hereda de vehculo , para proporcionar una
descripcin personalizada que incluye la marcha actual:

class Car: Vehicle {

var gear = 1

override var description: String {

return super.description + " in gear \(gear)"

157

La anulacin de la descripcin de propiedad comienza


llamando super.description , que devuelve el vehculode
clase Descripcin propiedad. El coche la versin de la clase de descripcin a
continuacin, aade un poco de texto adicional al final de esta descripcin para
proporcionar informacin sobre la marcha actual.
Si crea una instancia de la Car clase y configura
su engranaje y currentspeed propiedades, se puede ver que
su descripcin propiedad devuelve la descripcin adaptada definida dentro
del coche de clase:

let car = Car()

car.currentSpeed = 25.0

car.gear = 3

println("Car: \(car.description)")

// Coche: viajando a 25,0 millas por hora en la marcha 3


Los observadores de Propiedad Anulacin
Puede utilizar la propiedad primordial para agregar observadores de propiedad a una
propiedad heredada.Esto permite que se le notifique cuando el valor de un cambio de
propiedad heredadas, independientemente de cmo se implement originalmente esa
propiedad. Para obtener ms informacin sobre los observadores de propiedades,
consulte Observadores de propiedad .
NOTA
No se puede agregar observadores de propiedad de propiedades constantes almacenado
heredadas o propiedades de slo lectura computados heredados. El valor de estas
propiedades no se puede ajustar, por lo que no es apropiada para proporcionar
una willSet o didSet aplicacin como parte de una anulacin.
Tenga en cuenta tambin que no se puede proporcionar tanto un pionero de primer
orden y un observador propiedad primordial de la misma propiedad. Si desea observar
los cambios en el valor de una propiedad, y que ya est proporcionando un setter
personalizado para esa propiedad, slo tiene que observar los cambios de valor del
interior del setter personalizado.
El ejemplo siguiente define una nueva clase llamada AutomaticCar , que es una
subclase de coches . ElAutomaticCar clase representa un coche con cambio
automtico, que selecciona automticamente una velocidad adecuada a utilizar en
funcin de la velocidad actual:

class AutomaticCar: Car {

override var currentSpeed: Double {

didSet {

gear = Int(currentSpeed / 10.0) + 1

158

Siempre que site el currentspeed propiedad de un AutomaticCar ejemplo, el


alojamiento didSet observador fija de la instancia de engranajes propiedad a
una eleccin apropiada de engranaje para la nueva velocidad. En concreto, el
observador propiedad elige un engranaje que es el nuevo currentspeed valor
dividido por 10 , redondea hacia abajo al entero ms cercano, ms 1 . Una velocidad
de 10,0 produce un engranaje de 1 , y una velocidad de 35,0 produce un engranaje
de 4 :

let automatic = AutomaticCar()

automatic.currentSpeed = 35.0

println("AutomaticCar: \(automatic.description)")

// AutomaticCar: viaja a 35,0 millas por hora en la marcha


4

Prevencin Anulaciones
Usted puede evitar que un mtodo, una propiedad o subndice se cambie marcndolo
como definitiva . Para ello, escribir el ltimo modificador antes de la palabra clave
introductor del mtodo, la propiedad o de subndice (como final var,final func, final
class func, and final subscript).
Cualquier intento de anular una final mtodo, propiedad o subndice en una subclase se
reporta como un error en tiempo de compilacin. Mtodos, propiedades o subndices
que agregue a una clase en una extensin tambin se pueden marcar como final dentro
de la definicin de la extensin.
Puede marcar toda una clase como final por escribir el final modificador antes de
la class de palabras clave en su definicin de clase ( final class). Cualquier intento de
crear una subclase de una clase final se reporta como un error en tiempo de
compilacin.

Inicializacin
Inicializacin es el proceso de preparacin de una instancia de una clase, estructura o
enumeracin para su uso. Este proceso consiste en fijar un valor inicial para cada
propiedad almacenada en esa instancia y realizar cualquier otra configuracin o
inicializacin que se requiere antes de la nueva instancia est listo para su uso.
Implemente este proceso de inicializacin definiendo inicializadores , que son como los
mtodos especiales que pueden ser llamados para crear una nueva instancia de un tipo
particular. A diferencia de los inicializadores de Objective-C, inicializadores Swift no
devuelven un valor. Su funcin principal es asegurar que las nuevas instancias de un
tipo se inicializan correctamente antes de que se utilizan por primera vez.
Las instancias de tipos de clase tambin pueden implementar una deinitializer , que
realiza cualquier limpieza a medida solo antes de que se cancela la asignacin de una
instancia de esa clase. Para obtener ms informacin acerca de deinitializers,
ver deinicializacin .

159

Establecimiento de valores iniciales para las propiedades almacenados


Clases y estructuras deben establecer todas sus propiedades almacenadas en un valor
inicial adecuado para el momento en que se crea una instancia de esa clase o
estructura. Propiedades almacenados no se pueden dejar en un estado indeterminado.
Puede establecer un valor inicial para una propiedad almacenada dentro de un
inicializador, o mediante la asignacin de un valor de propiedad predeterminado como
parte de la definicin de la propiedad. Estas acciones se describen en las siguientes
secciones.
NOTA
Al asignar un valor predeterminado a una propiedad almacenada, o establecer su valor
inicial dentro de un inicializador, el valor de esa propiedad se establece directamente,
sin tener que llamar todos los observadores de propiedad.
Inicializadores
Inicializadores estn llamados a crear una nueva instancia de un tipo particular. En su
forma ms simple, un inicializador es como un mtodo de instancia sin parmetros,
escrito usando el init palabra clave:

init() {

// perform some initialization here

}
El ejemplo siguiente define una nueva estructura llamada Fahrenheit para
almacenar las temperaturas expresadas en la escala
Fahrenheit. El Fahrenheit estructura tiene una propiedad almacenada, la
temperatura , que es de tipo doble :

struct Fahrenheit {

var temperature: Double

init() {

temperature = 32.0

var f = Fahrenheit()

println("The default temperature is \(f.temperature) Fahrenheit")

// imprime "La temperatura predeterminada es 32,0


Fahrenheit"
La estructura define un nico inicializador, init , sin parmetros, que inicializa la
temperatura almacenado con un valor de 32,0 (el punto de congelacin del agua
cuando se expresa en la escala Fahrenheit).
Defecto Valores de la propiedad
Puede establecer el valor inicial de una propiedad almacenado desde dentro un
inicializador, como se muestra arriba. Como alternativa, especifique un valor de la
propiedad por defecto como parte de la declaracin de la propiedad. Se especifica un
valor de propiedad predeterminado mediante la asignacin de un valor inicial de la
propiedad cuando se define.

160

NOTA
Si una propiedad tiene siempre el mismo valor inicial, proporcionar un valor por defecto
en lugar de establecer un valor dentro de un inicializador. El resultado final es el mismo,
pero el valor predeterminado ata inicializacin de la propiedad ms de cerca a su
declaracin. Se convierte en ms cortos, inicializadores ms claras y le permite inferir el
tipo de la propiedad de su valor original. El valor por defecto tambin hace que sea ms
fcil para que usted tome ventaja de inicializadores por defecto y la herencia de
inicializacin, como se describe ms adelante en este captulo.
Usted puede escribir la Fahrenheit estructura desde arriba en una forma ms simple,
proporcionando un valor predeterminado para su temperatura de propiedad en el
punto de que la propiedad se declara:

struct Fahrenheit {

var temperature = 32.0

Personalizacin de inicializacin
Usted puede personalizar el proceso de inicializacin de parmetros de entrada y tipos
de propiedad opcionales, o mediante la modificacin de las propiedades constantes
durante la inicializacin, como se describe en las siguientes secciones.
Parmetros de inicializacin
Usted puede proporcionar los parmetros de inicializacin , como parte de la definicin
de un inicializador, para definir los tipos y los nombres de los valores que personalizan
el proceso de inicializacin. Parmetros de inicializacin tienen las mismas capacidades
y la sintaxis como parmetros de funciones y mtodos.
El ejemplo siguiente define una estructura llamada Celsius , que almacena las
temperaturas expresadas en la escala Celsius. El Celsius estructura implementa dos
inicializadores personalizados denominados init (fromFahrenheit :) y init
(fromKelvin :) , que inicializar una nueva instancia de la estructura con un valor
de una escala de temperatura diferente:

struct Celsius {

var temperatureInCelsius: Double

init(fromFahrenheit fahrenheit: Double) {

temperatureInCelsius = (fahrenheit - 32.0) / 1.8

init(fromKelvin kelvin: Double) {

temperatureInCelsius = kelvin - 273.15

let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)

// boilingPointOfWater.temperatureInCelsius is 100.0

let freezingPointOfWater = Celsius(fromKelvin: 273.15)

// freezingPointOfWater.temperatureInCelsius is 0.0

161

La primera inicializador tiene un solo parmetro de inicializacin con un nombre


externo de fromFahrenheit y un nombre local de fahrenheit . El segundo
inicializador tiene un solo parmetro de inicializacin con un nombre externo
de fromKelvin y un nombre local de kelvin . Ambos inicializadores convertir su
nico argumento en un valor en la escala Celsius y almacenar este valor en una
propiedad llamadatemperatureInCelsius .
Los nombres de parmetros locales y externos
Al igual que con los parmetros de las funciones y mtodos, parmetros de
inicializacin pueden tener tanto un nombre local para el uso dentro del cuerpo del
inicializador y un nombre externo para su uso cuando se llama al inicializador.
Sin embargo, los inicializadores no tienen un nombre de la funcin de identificacin
antes de que sus parntesis en la forma en que las funciones y los mtodos de hacer. Por
lo tanto, los nombres y tipos de parmetros de un inicializador desempean un papel
particularmente importante en la identificacin que inicializador debe ser
llamado. Debido a esto, Swift proporciona un nombre externo automtico
para cadaparmetro en un inicializador si no se proporciona un nombre externo a ti
mismo. Este nombre externo automtico es el mismo que el nombre local, como si
hubiera escrito un smbolo de hash antes de cada parmetro de inicializacin.
El ejemplo siguiente define una estructura llamada en color , con tres propiedades
constantes llamados rojo ,verde , y azul . Estas propiedades almacenan un valor
entre 0.0 y 1.0 para indicar la cantidad de rojo, verde y azul en el color.
Color proporciona un inicializador con tres parmetros con nombres correspondientes
de tipo doble para sus componentes rojo, verde y azul. color tambin proporciona
un segundo inicializador con un nico blancoparmetro, que se utiliza para
proporcionar el mismo valor para todos los tres componentes de color.

struct Color {

let red, green, blue: Double

init(red: Double, green: Double, blue: Double) {

self.red = red

self.green = green

self.blue = blue

init(white: Double) {

red = white

green = white

blue = white

}
Ambos inicializadores se pueden utilizar para crear un nuevo color de ejemplo,
proporcionando valores con nombre para cada parmetro de inicializacin:

let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)


162

let halfGray = Color(white: 0.5)


Tenga en cuenta que no es posible llamar a estos inicializadores sin usar nombres de los
parmetros externos. Nombres externos siempre se deben utilizar en un inicializador si
estn definidos, y la omisin de ellos es un error en tiempo de compilacin:

let veryGreen = Color(0.0, 1.0, 0.0)

// Esta informa de un error de tiempo de compilacin - Se


requieren nombres externos
Parmetros inicializador sin nombres externos
Si no desea utilizar un nombre externo para un parmetro de inicializacin, escribir un
guin bajo ( _ ) en lugar de un nombre externo explcito para ese parmetro para alterar
temporalmente el comportamiento por defecto.
He aqu una versin ampliada de la Celsius ejemplo de antes, con un inicializador
adicional para crear una nueva Celsius ejemplo de un doble valor que ya est en la
escala Celsius:

struct Celsius {

var temperatureInCelsius: Double

init(fromFahrenheit fahrenheit: Double) {

temperatureInCelsius = (fahrenheit - 32.0) / 1.8

init(fromKelvin kelvin: Double) {

temperatureInCelsius = kelvin - 273.15

init(_ celsius: Double) {

temperatureInCelsius = celsius

let bodyTemperature = Celsius(37.0)

// BodyTemperature.temperatureInCelsius es 37.0
La llamada inicializador Celsius (37.0) es clara en su intencin, sin la necesidad
de un nombre de parmetro externo. Por tanto, es conveniente escribir este inicializador
como init (_ celsius: Doble) por lo que se puede llamar al proporcionar un
annimo doble valor.
Tipos de Propiedad opcionales
Si su tipo personalizado tiene una propiedad almacenado que se permite lgicamente
tener "ningn valor" -quizs porque su valor no se puede ajustar durante la
inicializacin, o porque se le permite tener "ningn valor" en algn punto ms adelantedeclarar la propiedad con un opcional tipo. Inmuebles del tipo opcional se inicializan
automticamente con un valor de cero , lo que indica que la propiedad est destinado
deliberadamente a tener "ningn valor todava" durante la inicializacin.
El ejemplo siguiente define una clase denominada SurveyQuestion , con un
opcional de cuerda llamada propiedad respuesta :

163

class SurveyQuestion {

var text: String

var response: String?

init(text: String) {

self.text = text

func ask() {

println(text)

let cheeseQuestion = SurveyQuestion(text: "Do you like cheese?")

cheeseQuestion.ask()

// prints "Do you like cheese?"

cheeseQuestion.response = "Yes, I do like cheese."


La respuesta a una pregunta de la encuesta no se puede saber hasta que se le pide, por lo
que la respuesta de la propiedad se declara con un tipo de cuerda? , o
"opcional Cadena ". Se asigna automticamente un valor por defecto de cero , que
significa "ninguna cadena todava", cuando una nueva instancia
de SurveyQuestionse inicializa.
Modificacin de las propiedades constantes durante la inicializacin
Puede modificar el valor de una propiedad constante en cualquier punto durante la
inicializacin, siempre y cuando se establece en un valor definido por los acabados de
inicializacin de tiempo.
NOTA
Para las instancias de clase, una propiedad constante slo puede ser modificado durante
la inicializacin de la clase que lo introduce. No puede ser modificado por una subclase.
Usted puede revisar el SurveyQuestion ejemplo desde arriba para utilizar una
propiedad constante en lugar de una propiedad de variable para el texto propiedad de
la cuestin, para indicar que la cuestin no cambia una vez que una instancia
de SurveyQuestion se crea. A pesar de que el texto de la propiedad es ahora
una constante, todava puede ajustarse dentro de inicializador de la clase:

class SurveyQuestion {

let text: String

var response: String?

init(text: String) {

self.text = text

func ask() {

println(text)

164

let beetsQuestion = SurveyQuestion(text: "How about beets?")

beetsQuestion.ask()

// prints "How about beets?"

beetsQuestion.response = "I also like beets. (But not with cheese.)"


Inicializadores defecto
Swift proporciona un inicializador por defecto para cualquier estructura o base clase
que proporciona valores predeterminados para todas sus propiedades y no proporciona
al menos un inicializador de s mismo. El inicializador por defecto simplemente crea
una nueva instancia con todos sus propiedades configuradas con los valores
predeterminados.
En este ejemplo se define una clase llamada ShoppingListItem , que encapsula el
nombre, cantidad y estado de compra de un artculo en una lista de la compra:

class ShoppingListItem {

var name: String?

var quantity = 1

var purchased = false

var item = ShoppingListItem()


Debido a que todas las propiedades de la ShoppingListItem clase tienen valores
por defecto, y porque es una clase base sin superclase, ShoppingListItem gana
automticamente una aplicacin inicializador por defecto que crea una nueva instancia
con todos sus propiedades configuradas con los valores predeterminados. (Elnombre
de la propiedad es una opcin de cadena de propiedad, y por lo que recibe
automticamente un valor por defecto de cero , a pesar de que este valor no est
escrito en el cdigo.) El ejemplo anterior utiliza el inicializador por defecto para
el ShoppingListItem clase para crear una nueva instancia de la clase con la
sintaxis de inicializador, escrito como ShoppingListItem () , y asigna esta nueva
instancia a una variable llamada elemento .
Miembro por miembro Inicializadores de Estructura Tipos
Tipos de estructura reciben automticamente un inicializador de miembro por
miembro , si no definen ninguna de sus propias inicializadores personalizados. Esto es
cierto incluso si las propiedades almacenados de la estructura no tienen valores por
defecto.
El inicializador de miembro por miembro es una forma abreviada para inicializar las
propiedades de los miembros de las nuevas instancias de estructura. Los valores
iniciales de las propiedades de la nueva instancia se pueden pasar a la inicializador
miembro por miembro por su nombre.

165

El ejemplo siguiente define una estructura llamada Tamao con dos propiedades
denominadas anchura y altura. Ambas propiedades se infieren a ser de
tipo doble mediante la asignacin de un valor por defecto de 0.0 .
El Tamao estructura recibe automticamente una init (ancho: alto
:) inicializador miembro por miembro, que se puede utilizar para inicializar un
nuevo Tamao ejemplo:

struct Size {

var width = 0.0, height = 0.0

let twoByTwo = Size(width: 2.0, height: 2.0)


Delegacin inicializador para tipos de valor
Inicializadores pueden llamar a otros inicializadores para realizar parte de la
inicializacin de una instancia.Este proceso, conocido como delegacin inicializador ,
evita duplicacin de cdigo en varios inicializadores.
Las reglas de cmo funciona la delegacin inicializador, y para qu formas de
delegacin se permiten, son diferentes para los tipos de valor y tipos de clase. Valor
tipos (estructuras y enumeraciones) no admiten la herencia, por lo que su proceso de
delegacin inicializador es relativamente simple, ya que slo pueden delegar en otro
inicializador que proporcionan a s mismos. Las clases, sin embargo, se pueden heredar
de otras clases, como se describe en la herencia . Esto significa que las clases tienen
responsabilidades adicionales para asegurar que todas las propiedades almacenadas que
heredan se les asigna un valor adecuado durante la inicializacin. Estas
responsabilidades se describen en la clase de herencia e inicializacin de abajo.
Para los tipos de valor, se utiliza self.init para referirse a otros inicializadores del
mismo tipo de valor al escribir sus propios inicializadores personalizados. Slo puede
llamar self.init desde un inicializador.
Tenga en cuenta que si se define un inicializador personalizado para un tipo de valor, ya
no tendr acceso a la inicializador por defecto (o el inicializador de miembro por
miembro, si se trata de una estructura) para ese tipo. Esta limitacin impide una
situacin en la que la configuracin esencial adicional proporcionada en un inicializador
ms compleja se elude por alguien usando accidentalmente uno de los inicializadores
automticos lugar.
NOTA
Si usted quiere que su tipo de valor a medida que sea initializable con el inicializador
por defecto y inicializador miembro por miembro, y tambin con sus propias
inicializadores personalizados, escriba sus inicializadores personalizados en una
extensin ms que como parte de la implementacin original del tipo de valor. Para
obtener ms informacin, vea Extensiones .
El ejemplo siguiente define una costumbre Rect estructura para representar un
rectngulo geomtrico. El ejemplo requiere dos estructuras de apoyo
llamada Tamao y Point , los cuales proporcionan valores por defecto de 0,0 para
todas sus propiedades:

struct Size {

166

var width = 0.0, height = 0.0

struct Point {

var x = 0.0, y = 0.0

}
Puede inicializar el Rect estructura por debajo de una de tres maneras: mediante el uso
de sus defecto cero inicializado- origen y tamao valores de la propiedad,
proporcionando un punto y el tamao de origen especfico, o proporcionando un punto
central especfico y tamao. Estas opciones de inicializacin estn representados por
tres inicializadores personalizadas que forman parte de la Rect definicin de la
estructura:

struct Rect {

var origin = Point()

var size = Size()

init() {}

init(origin: Point, size: Size) {

self.origin = origin

self.size = size

init(center: Point, size: Size) {

let originX = center.x - (size.width / 2)

let originY = center.y - (size.height / 2)

self.init(origin: Point(x: originX, y: originY), size: size)

}
La primera Rect inicializador, init () , es funcionalmente lo mismo que el
inicializador por defecto que la estructura habra recibido si no tuviese una fisonoma
propia inicializadores personalizados. Este inicializador tiene un cuerpo vaco,
representado por un par vaco de llaves {} , y no perfom cualquier inicializacin. Al
llamar a este inicializador devuelve un Rect instancia cuyo origen y tamao
de las propiedades se inicializan con los valores por defecto de punto (x: 0.0,
y: 0.0) y Tamao (anchura: 0.0, Altura: 0.0) de sus definiciones de
propiedad:

let basicRect = Rect()

// Origen de basicRect es (0.0, 0.0) y su tamao es (0.0,


0.0)
El segundo Rect inicializador, init (origen: tamao :) , es funcionalmente
lo mismo que el inicializador de miembro por miembro que la estructura habra recibido
si no tuviese una fisonoma propia inicializadores personalizados. Este inicializador

167

simplemente asigna los de origen y tamao valores de los argumentos de las


propiedades adecuadas almacenado:

let originRect = Rect(origin: Point(x: 2.0, y: 2.0),

size: Size(width: 5.0, height: 5.0))

// Origen de originRect es (2.0, 2.0) y su tamao es (5.0,


5.0)
La tercera Rect inicializador, init (centro: tamao :) , es un poco ms
compleja. Se inicia mediante el clculo de un punto de origen apropiado basado en
un centro de punto y un tamao valor. A continuacin, llama (odelegados )
al init (origen: tamao :) inicializador, que almacena los nuevos valores de
origen y tamao en las propiedades adecuadas:

let centerRect = Rect(center: Point(x: 4.0, y: 4.0),

size: Size(width: 3.0, height: 3.0))

// Origen de centerRect es (2.5, 2.5) y su tamao es (3.0,


3.0)
El init (centro: tamao :) inicializador podra haber asignado los nuevos
valores de origen y el tamao de las propias propiedades adecuadas. Sin embargo,
es ms conveniente (y ms claro en la intencin) para elinit (centro: tamao
:) inicializador para tomar ventaja de un inicializador existente que ya proporciona
exactamente esa funcionalidad.
NOTA
Para una forma alternativa de escribir este ejemplo sin definir el init () y init
(origen: tamao :)inicializadores ti mismo, ver las extensiones .
Clase herencia e inicializacin
Todas las propiedades-incluyendo almacenados de una clase propiedades de la clase
hereda de su superclass- debe ser asignado un valor inicial durante la inicializacin.
Swift define dos tipos de inicializadores para tipos de clase para ayudar a asegurar todas
las propiedades almacenadas reciben un valor inicial. Estos son conocidos como
inicializadores designados y los inicializadores de conveniencia.
Inicializadores Designados y Conveniencia Inicializadores
Inicializadores designados son los inicializadores primarios para una clase. Un
inicializador designado inicializa totalmente todas las propiedades introducidas por esa
clase y llama a un inicializador superclase apropiado continuar el proceso de
inicializacin en la cadena de superclase.
Las clases suelen tener muy pocos inicializadores designadas, y es muy comn que una
clase tenga slo uno. Inicializadores mencionadas son puntos "embudo" a travs del
cual tiene lugar la inicializacin, ya travs del cual el proceso de inicializacin contina
en la cadena de superclase.
Cada clase debe tener al menos un inicializador designado. En algunos casos, este
requisito se satisface con la herencia de uno o varios designado inicializadores de una
superclase, como se describe en automtico Inicializador Herencia continuacin.
Inicializadores de conveniencia son, inicializadores de apoyo secundarias para una
clase. Puede definir un inicializador conveniencia de llamar a un inicializador designado

168

de la misma clase que el inicializador de conveniencia con algunos de los parmetros


del inicializador designado establecidos a sus valores predeterminados. Tambin puede
definir un inicializador conveniencia de crear una instancia de esa clase para un caso de
uso o valor de entrada tipo especfico.
Usted no tiene que proporcionar inicializadores de conveniencia si su clase no los
requiere. Crear inicializadores de conveniencia cada vez que un acceso directo a un
patrn de iniciacin comn ahorrar tiempo o hacer que la inicializacin de la clase ms
clara en su intencin.
Sintaxis para Designados y Inicializadores de Conveniencia
Inicializadores designados para las clases se escriben de la misma manera como
inicializadores simples para los tipos de valor:

init( parameters ) {
statements

}
Inicializadores de Conveniencia estn escritos en el mismo estilo, pero con
la comodidad modificador colocado antes del inicio de palabras clave, separadas
por un espacio:

convenience init( parameters ) {


statements

}
Inicializador encadenamiento
Para simplificar las relaciones entre los inicializadores designados y de conveniencia,
Swift se aplica las siguientes tres reglas para la delegacin de llamadas entre
inicializadores:
Regla 1
Un inicializador designado debe llamar a un inicializador designado de su
superclase inmediata.
Regla 2
Un inicializador de conveniencia debe llamar a otro inicializador de
la misma clase.
Regla 3
Un inicializador de conveniencia debe en ltima instancia, llamar a un
inicializador designado.
Una forma sencilla de recordar esto es:
Inicializadores designados siempre deben delegar para arriba .
Inicializadores de Conveniencia siempre deben delegar en todo .
Estas reglas se ilustran en la siguiente figura:

169


Aqu, la superclase tiene un nico inicializador designado y dos inicializadores de
conveniencia. Un inicializador conveniencia llama a otro inicializador conveniencia,
que a su vez llama a la nica inicializador designado. Esto satisface las reglas 2 y 3 de
arriba. La superclase no en s tiene otros superclase, y lo que la regla 1 no se aplica.
La subclase de esta figura tiene dos inicializadores designados y un inicializador
conveniencia. El inicializador de conveniencia debe llamar a uno de los dos
inicializadores designados, ya que slo puede llamar a otro inicializador de la misma
clase. Esto satisface las reglas 2 y 3 de arriba. Ambos inicializadores designados deben
llamar a la nica inicializador designado de la superclase, para satisfacer a la regla 1
desde arriba.
NOTA
Estas normas no afectan a cmo los usuarios de sus clases crean instancias de cada
clase. Cualquier inicializador en el diagrama anterior se puede utilizar para crear una
instancia de inicializado completamente de la clase al que pertenecen. Las reglas slo
afectan a la forma de escribir la implementacin de la clase.
La siguiente figura muestra una jerarqua de clases ms complejo para cuatro
clases. Ilustra cmo los inicializadores designados en este acto jerarqua como puntos de
"embudo" para la inicializacin de clase, lo que simplifica las relaciones entre las clases
de la cadena:

170


Two-Phase inicializacin
Clase de inicializacin en Swift es un proceso de dos fases. En la primera fase, cada
propiedad almacenado se le asigna un valor inicial de la clase que lo introdujo. Una vez
que el estado inicial de cada propiedad almacenado ha sido determinada, la segunda fase
comienza, y cada clase se le da la oportunidad de personalizar sus propiedades
almacenadas ms antes de considerar la nueva instancia de lista para su uso.
El uso de un proceso de inicializacin de dos fases hace segura la inicializacin,
mientras que todava da flexibilidad completa a cada clase en una jerarqua de
clases. Inicializacin de dos fases impide valores de la propiedad de ser visitada antes
de que se inicializan, y evita los valores de propiedad de ser ajustado a un valor
diferente por otro inicializador inesperadamente.
NOTA
Proceso de inicializacin de dos fases de Swift es similar a la inicializacin en
Objective-C. La principal diferencia es que en la fase 1, Objective-C asigna cero o nulos
valores (como 0 o nulo ) a cada propiedad.Flujo de inicializacin de Swift es ms
flexible ya que permite establecer los valores iniciales de encargo, y puede hacer frente
a tipos a los que 0 o nulo no es un valor predeterminado vlido.
Compilador de Swift realiza cuatro controles de seguridad tiles para asegurarse de que
la inicializacin de dos fases se completa sin errores:
Comprobacin de seguridad 1
Un inicializador designado debe asegurar que todas las propiedades introducidas
por su clase se inicializan antes de que los delegados hasta un inicializador
superclase.

171

Como se mencion anteriormente, la memoria de un objeto slo se considera


inicializado completamente una vez que se conoce el estado inicial de todas sus
propiedades almacenados. Para que esta regla para estar satisfechos, un inicializador
designado debe asegurarse de que todas sus propiedades se inicializan antes de que las
manos fuera de la cadena.
Comprobacin de seguridad 2
Un inicializador designado debe delegar a un inicializador superclase antes de
asignar un valor a una propiedad heredada. Si no es as, el nuevo valor de los
cesionarios de inicializador designado ser sobrescrita por la superclase como
parte de su propia inicializacin.
Comprobacin de seguridad 3
Un inicializador de conveniencia debe delegar en otro inicializador antes de
asignar un valor a cualquierpropiedad (incluidas las propiedades definidas por la
misma clase). Si no es as, el nuevo valor de los cesionarios de inicializador de
conveniencia ser sobrescrita por inicializador designado de su propia clase.
Comprobacin de seguridad 4
Un inicializador no puede llamar a cualquier mtodo de instancia, leer los
valores de las propiedades de la instancia, o se refieren a uno mismo como un
valor de hasta una vez finalizada la primera fase de inicializacin.
La instancia de la clase no es totalmente vlida hasta que termine la primera
fase. Propiedades slo se puede acceder, y mtodos slo pueden ser convocadas, una
vez conocida la instancia de clase sea vlido al final de la primera fase.
As es como la inicializacin de dos fases se desarrolla, en base a los cuatro controles de
seguridad por encima de:
Fase 1
Un inicializador designado o conveniencia se llama en una clase.
Memoria de una nueva instancia de esa clase se asigna. La memoria an no se
inicializa.
Un inicializador designado para esa clase confirma que todas las propiedades
almacenadas introducidas por esa clase tienen un valor. La memoria de estas
propiedades almacenadas ahora inicializa.
Los inicializadores manos designadas fuera a un inicializador superclase para
realizar la misma tarea por sus propias propiedades almacenadas.
Esto contina en la cadena de herencia de clases hasta que se alcance la parte
superior de la cadena.
Una vez que se alcanza la cima de la cadena, y la clase final de la cadena se ha
asegurado de que todas sus propiedades almacenadas tienen un valor, la memoria de
la instancia se considera que est totalmente inicializado, y la fase 1 se ha
completado.
Fase 2
Trabajando hacia abajo desde la parte superior de la cadena, cada inicializador
designado de la cadena tiene la opcin de personalizar la instancia
ms. Inicializadores ahora son capaces de acceder a uno mismo y puede modificar
sus propiedades, llamar a sus mtodos de instancia, y as sucesivamente.

172

Por ltimo, cualquier inicializadores de conveniencia de la cadena tienen la opcin


de personalizar el ejemplo y trabajar con uno mismo .
As es como se ve la fase 1 para una llamada de inicializacin para una subclase y
superclase hipottica:


En este ejemplo, la inicializacin comienza con una llamada a un inicializador de
conveniencia en la subclase.Este inicializador conveniencia an no puede modificar las
propiedades. Delegados a travs a un inicializador designado de la misma clase.
El inicializador designado se asegura de que todas las propiedades de la subclase tienen
un valor, segn comprobacin de seguridad 1. A continuacin, llama un inicializador
designado en su superclase para continuar con la inicializacin de la cadena.
Inicializador designado de la superclase se asegura de que todas las propiedades de la
superclase tiene un valor. No hay ms superclases para inicializar, y as no se necesita
una mayor delegacin.
Tan pronto como todas las propiedades de la superclase tienen un valor inicial, su
memoria se considera totalmente inicializado, y la Fase 1 se ha completado.
As es como la fase 2 se ve por la misma llamada de inicializacin:


Inicializador designado de la superclase tiene ahora la oportunidad de personalizar la
instancia ms (aunque no tiene por qu).
Una vez inicializador designado de la superclase se termin, inicializador designado de
la subclase puede realizar una personalizacin adicional (aunque, de nuevo, que no tiene
por qu).

173

Por ltimo, una vez finalizado inicializador designado de la subclase, el inicializador de


conveniencia que originalmente fue llamado puede realizar una personalizacin
adicional.
Inicializador Sucesiones y Anulacin
A diferencia de las subclases en Objective-C, subclases Swift no heredan sus
inicializadores superclase de forma predeterminada. El enfoque de Swift evita una
situacin en la que un inicializador simple a partir de una superclase es heredado por
una subclase ms especializada y se utiliza para crear una nueva instancia de la subclase
que no est inicializado completamente o correctamente.
NOTA
Inicializadores superclase se heredan en ciertas circunstancias, pero slo cuando sea
seguro y apropiado para ello. Para obtener ms informacin, consulte automtica
Inicializador Herencia continuacin.
Si quieres una subclase personalizada de presentar uno o ms de los mismos
inicializadores como su superclase, puede proporcionar una implementacin
personalizada de los inicializadores dentro de la subclase.
Cuando se escribe un inicializador subclase que coincide con una
superclase designado inicializador, usted est proporcionando efectivamente un
aumento al presupuesto de ese inicializador designado. Por lo tanto, debe escribir
la anulacin modificador antes de la definicin de inicializacin de la subclase. Esto
es cierto incluso si est sustituyendo un inicializador por defecto proporcionado de
forma automtica, como se describe en Inicializadores predeterminados .
Al igual que con una propiedad, mtodo o subndice anulado, la presencia de
la anulacin modificador solicita Swift para comprobar que la superclase tiene un
inicializador de juego designado para ser anulado, y valida que se han especificado los
parmetros para su inicializador primordial como es debido.
NOTA
Siempre escribe la anulacin modificador cuando anulando una superclase
designado inicializador, incluso si la aplicacin de la subclase del inicializador es un
inicializador de conveniencia.
Por el contrario, si usted escribe un inicializador subclase que coincide con una
superclase convenienciainicializador, que inicializador conveniencia superclase nunca
puede ser llamado directamente por su subclase, de acuerdo con las reglas descritas
anteriormente en el inicializador de encadenamiento . Por lo tanto, la subclase no est
(en sentido estricto) proporcionar una sustitucin de la inicializador superclase.Como
resultado, usted no escribe la anulacin modificador cuando se proporciona una
aplicacin coincidente de un inicializador conveniencia superclase.
El ejemplo siguiente define una clase base llamada Vehculo . Esta clase base declara
una propiedad almacenado llamado numberOfWheels y su valor
predeterminado Int valor de 0 . El numberOfWheels propiedad es utilizada por una
propiedad llamada computarizada descripcin para crear una Cadena
de descripcin de las caractersticas del vehculo:

class Vehicle {

var numberOfWheels = 0

var description: String {


174

return "\(numberOfWheels) wheel(s)"

}
El vehculo clase proporciona un valor predeterminado para su propiedad slo
almacenado, y no proporciona ningn s inicializadores personalizados. Como
resultado, recibe automticamente un inicializador por defecto, como se describe
en Inicializadores predeterminados . El inicializador por defecto (si est disponible) es
siempre un inicializador designado para una clase, y se puede utilizar para crear un
nuevo vehculoejemplo con un numberOfWheels de 0 :

let vehicle = Vehicle()

println("Vehicle: \(vehicle.description)")

// Vehculo: 0 rueda (s)


El siguiente ejemplo define una subclase de vehculo llamado de bicicletas :

class Bicycle: Vehicle {

override init() {

super.init()

numberOfWheels = 2

}
La bicycle subclase define un inicializador designado costumbre, init () . Este
inicializador designado coincide con un inicializador designado de la superclase
de bicicletas , por lo que la bicicleta versin de este inicializador est
marcado con el override modificador.
El init () inicializador para bicicletas comienza llamando super.init () ,
que llama al inicializador por defecto para la bicicleta superclase de la
clase, vehculo . Esto asegura que el numberOfWheels propiedad heredada es
inicializado por el vehculo antes de bicicletas tiene la oportunidad de
modificar la propiedad.Despus de llamar a super.init () , el valor original
de numberOfWheels se sustituye con un nuevo valor de 2 .
Si crea una instancia de la bicicleta , puede llamar a su
heredada Descripcin computarizada propiedad para ver cmo
su numberOfWheels propiedad ha sido actualizada:

let bicycle = Bicycle()

println("Bicycle: \(bicycle.description)")

// Bicicletas: 2 ruedas (s)


NOTA
Las subclases slo se les permite modificar variables propiedades superclase durante la
inicializacin. Las subclases no pueden modificar heredado propiedades constantes.
Automatic Inicializador Herencia
Como se mencion anteriormente, las subclases no heredan sus inicializadores
superclase de forma predeterminada. Sin embargo, los inicializadores
superclase son heredados automticamente si se cumplen ciertas condiciones. En la

175

prctica, esto significa que no es necesario escribir las anulaciones de inicializador en


muchos escenarios comunes, y pueden heredar sus inicializadores superclase con el
mnimo esfuerzo, siempre que sea seguro hacerlo.
Suponiendo que usted proporciona valores predeterminados para las nuevas propiedades
usted introduce en una subclase, se aplican las siguientes reglas:
Regla 1
Si su subclase no define ningn inicializadores designados, hereda
automticamente todos sus superclase designado inicializadores.
Regla 2
Si su subclase proporciona una implementacin de todos los de su superclase
designado inicializadores-ya sea heredando ellos segn la regla 1, o
proporcionando una implementacin personalizada como parte de su definicinentonces hereda automticamente todos los inicializadores de conveniencia
superclase.
Estas normas se aplican incluso si su subclase aade nuevos inicializadores de
conveniencia.
NOTA
Una subclase puede aplicar una superclase inicializador designado como inicializador
conveniencia subclase como parte de la satisfaccin de la regla 2.
Designado y Conveniencia Inicializadores en Accin
El siguiente ejemplo muestra inicializadores designados, inicializadores de
conveniencia, y la herencia de inicializacin automtica en accin. En este ejemplo se
define una jerarqua de tres clases
llamadas Alimentos, recipeIngredient y ShoppingListItem , y
demuestra cmo sus inicializadores interactan.
La clase base de la jerarqua se llama la Alimentacin , que es una clase simple
para encapsular el nombre de un producto alimenticio. La Food clase introduce una
sola cuerda propiedad llamada nombre y ofrece dos inicializadores para la creacin
de Alimentos casos:

class Food {

var name: String

init(name: String) {

self.name = name

convenience init() {

self.init(name: "[Unnamed]")

}
La siguiente figura muestra la cadena de inicializacin para la Alimentacin de
clase:

176


Las clases no tienen un miembro por miembro inicializador por defecto, por lo que
la Food clase proporciona un inicializador designado que toma un solo argumento
llamado nombre . Este inicializador puede ser utilizado para crear un
nuevo Alimentacin instancia con un nombre especfico:

// Nombre de namedMeat es "tocino"


El init (name: String) inicializador de la Food clase se proporciona como
un designado inicializador, ya que asegura que todas las propiedades almacenadas de un
nuevo Alimentacin instancia estn completamente iniciados. La Food clase no
tiene una superclase, por lo que el init (name: String) inicializador no necesita
llamar super.init () para completar su inicializacin.
La Food clase tambin proporciona una mayor comodidad inicializador, init () ,
sin argumentos. El init ()inicializador proporciona un nombre de marcador de
posicin por defecto para un nuevo alimento mediante la delegacin a travs de
la Alimentacin de la clase init (name: String) con un nombre de valor
de [nombre] :

let namedMeat = Food(name: "Bacon")

let mysteryMeat = Food()

// Nombre de mysteryMeat es "[nombre]"


La segunda clase en la jerarqua es una subclase de la
Alimentacin llamado recipeIngredient . LosrecipeIngredient model
os de clase un ingrediente en una receta de cocina. Se introduce un Int propiedad
llamada cantidad (adems del nombre de la propiedad se hereda de la
Alimentacin ) y define dos inicializadores para
crear recipeIngredient casos:

class RecipeIngredient: Food {

var quantity: Int

init(name: String, quantity: Int) {

self.quantity = quantity

super.init(name: name)

override convenience init(name: String) {

self.init(name: name, quantity: 1)

}
177


La siguiente figura muestra la cadena de inicializacin para
el recipeIngredient clase:


El recipeIngredient clase tiene un nico inicializador designado, init
(name: String, cantidad: Int) , que se puede utilizar para rellenar todas las
propiedades de un nuevo recipeIngredient ejemplo. Este inicializador comienza
asignando el pasado cantidad argumento a la cantidad de propiedad, que es la
nica propiedad nueva introducida por recipeIngredient . Despus de hacerlo,
los delegados de inicializador hasta el init (name: String) inicializador de
la Alimentacin de clase. Este proceso satisface control de seguridad 1 deTwoPhase inicializacin anteriormente.
RecipeIngredient tambin define un inicializador conveniencia, init (name:
String) , que se utiliza para crear un recipeIngredient ejemplo por su nombre
solo. Este inicializador conveniencia asume una cantidad de 1 por
cualquier recipeIngredient instancia que se crea sin una cantidad explcito. La
definicin de este inicializador conveniencia hace recipeIngredient casos ms
rpido y ms conveniente para crear, y evita la duplicacin de cdigo al crear varios de
una sola cantidad recipeIngredient casos. Este inicializador conveniencia
simplemente delegados de todo a inicializador designado de la clase, que pasan en
una cantidad de valor de1 .
El init (name: String) inicializador comodidad proporcionada
por recipeIngredient toma los mismos parmetros que el init (name:
String) designado inicializador de Alimentos . Debido a que este inicializador
conveniencia anula un inicializador designado de su superclase, que debe estar marcado
con la anulacin de modificacin (como se describe en Inicializador Sucesiones y
Anulacin ).
Aunque recipeIngredient ofrece el init (name: String) inicializador
como inicializador conveniencia,recipeIngredient ha proporcionado, sin
embargo, una implementacin de todos los inicializadores designados de su

178

superclase. Por lo tanto, recipeIngredient hereda automticamente todos los


inicializadores de conveniencia de su superclase tambin.
En este ejemplo, la superclase para recipeIngredient es Alimentacin , que
tiene una sola inicializador conveniencia llamado init () . Por tanto, este
inicializador es heredado por recipeIngredient . La versin heredada de init
() funciona de la misma manera como la Food versin, salvo que los delegados a
larecipeIngredient versin de init (name: String) en lugar de
la Alimentacin versin.
Los tres de estos inicializadores se puede utilizar para crear
nuevos recipeIngredient casos:

let oneMysteryItem = RecipeIngredient()

let oneBacon = RecipeIngredient(name: "Bacon")

let sixEggs = RecipeIngredient(name: "Eggs", quantity: 6)


La tercera y ltima clase en la jerarqua es una subclase
de recipeIngredient llamado ShoppingListItem . LosShoppingListIte
m modelos de clase un ingrediente receta tal como aparece en una lista de compras.
Cada elemento de la lista de compras comienza como "unpurchased". Para representar
este hecho,ShoppingListItem introduce una propiedad booleana
denominada comprado , con un valor predeterminado
defalse . ShoppingListItem tambin aade un
computarizada Descripcin propiedad, que ofrece una descripcin textual de
un ShoppingListItem ejemplo:

class ShoppingListItem: RecipeIngredient {

var purchased = false

var description: String {

var output = "\(quantity) x \(name)"

output += purchased ? " " : " "

return output

}
NOTA
ShoppingListItem no define un inicializador para proporcionar un valor inicial
para comprar , porque los elementos de una lista de la compra (como modelados aqu)
siempre comienzan unpurchased.
Debido a que proporciona un valor predeterminado para todas las propiedades que
presenta y no define ningn inicializadores s, ShoppingListItem hereda
automticamente todos los inicializadores de conveniencia designados y de su
superclase.
La siguiente figura muestra la cadena global de inicializacin para las tres clases:

179


Puede utilizar los tres de los inicializadores heredados para crear un
nuevo ShoppingListItem ejemplo:

var breakfastList = [

ShoppingListItem(),

ShoppingListItem(name: "Bacon"),

ShoppingListItem(name: "Eggs", quantity: 6),

breakfastList[0].name = "Orange juice"

breakfastList[0].purchased = true

for item in breakfastList {

println(item.description)

// 1 x Orange juice

// 1 x Bacon

// 6 x Eggs
Aqu, una nueva matriz llamada breakfastList se crea a partir de una matriz que
contiene literal tres nuevosShoppingListItem casos. El tipo de la matriz se deduce
que [ShoppingListItem] . Una vez creada la matriz, el nombre de
la ShoppingListItem al inicio de la matriz se cambia
de "[nombre]" para "Zumo de naranja" y se marca como comprado. Impresin

180

de la descripcin de cada elemento de la matriz muestra que sus estados


predeterminados se han fijado como se esperaba.
Inicializadores Requeridos
Escriba el requerido modificador antes de la definicin de un inicializador de clase
para indicar que cada subclase de la clase debe implementar que inicializador:

class SomeClass {

required init() {

// Aplicacin inicializador va aqu

}
Tambin debe escribir el requerido modificador antes de cada aplicacin subclase
de un inicializador necesario, para indicar que el requisito de inicializacin se aplica a
otras subclases de la cadena. No escribes la anulacin modificador cuando anulando
un inicializador designado requerida:

class SomeSubclass: SomeClass {

required init() {

// Aplicacin subclase del inicializador requerida va aqu

}
NOTA
Usted no tiene que proporcionar una implementacin explcita de un inicializador
necesaria si se puede cumplir con el requisito con un inicializador heredado.
El establecimiento de un defecto Valor de la propiedad con un cierre o la
Funcin
Si el valor predeterminado de una propiedad almacenado requiere algn tipo de
personalizacin o configuracin, puede utilizar un cierre o funcin global para
proporcionar un valor por defecto a medida para esa propiedad. Siempre que una nueva
instancia del tipo que la propiedad pertenece a se inicializa, el cierre o la funcin se
llama, y su valor de retorno se asigna como valor predeterminado de la propiedad.
Este tipo de cierres o funciones suelen crear un valor temporal del mismo tipo que la
propiedad, a medida que valoran para representar el estado inicial deseado, y luego
regresan ese valor temporal que se utilizar como valor predeterminado de la propiedad.
He aqu un esbozo de cmo un esqueleto de cierre puede ser utilizado para proporcionar
un valor de propiedad predeterminado:

class SomeClass {

let someProperty: SomeType = {

// Crear un valor predeterminado para UnaPropiedad dentro


de este cierre

// SomeValue debe ser del mismo tipo que SomeType

return someValue

}()
181

}
Tenga en cuenta que extremo de la llave de cierre es seguido por un par de parntesis
vaco. Esto le dice a Swift para ejecutar el cierre inmediato. Si omite estos parntesis,
usted est tratando de asignar el propio cierre a la propiedad, y no el valor de retorno de
la clausura.
NOTA
Si utiliza un cierre para inicializar una propiedad, recuerde que el resto de la instancia
an no se ha inicializado en el punto que se ejecuta el cierre. Esto significa que no se
puede acceder a cualquier otro valor de las propiedades dentro de su cierre, incluso si
esas propiedades tienen valores por defecto. Tampoco se puede utilizar la
implcita auto propiedad, o llamar a cualquiera de los mtodos de la instancia.
El ejemplo siguiente define una estructura llamada de tablero de ajedrez , que
los modelos de un tablero para el juego de Checkers (tambin conocido como Damas ):


El juego de las Damas se juega en un tablero de diez por diez, con cuadrados blancos y
negros alternados.Para representar este tablero de juego, el tablero de
ajedrez estructura tiene una sola propiedad denominada boardColors , que es una
matriz de 100 Bool valores. Un valor de verdad de la matriz representa un cuadrado
negro y un valor de falso representa un cuadrado blanco. El primer elemento de la
matriz representa el cuadrado superior izquierda en el tablero y el ltimo elemento de la
matriz representa el cuadrado inferior derecha en el tablero.
El boardColors matriz se inicializa con un cierre para establecer sus valores de
color:

struct Checkerboard {

let boardColors: [Bool] = {

var temporaryBoard = [Bool]()

var isBlack = false

for i in 1...10 {

for j in 1...10 {

temporaryBoard.append(isBlack)

182

isBlack = !isBlack

isBlack = !isBlack

return temporaryBoard

}()

func squareIsBlackAtRow(row: Int, column: Int) -> Bool {

return boardColors[(row * 10) + column]

}
Cada vez que un nuevo tablero de ajedrez se crea una instancia, el cierre se
ejecuta, y el valor por defecto de boardColors se calcula y se volvi. El cierre en el
ejemplo anterior calcula y establece el color apropiado para cada casilla del tablero en
una matriz temporal llamado temporaryBoard , y devuelve esta matriz temporal
como valor de retorno de la clausura una vez que su configuracin se ha completado. El
valor de la matriz devuelta se almacena en boardColors y se puede consultar con
el squareIsBlackAtRow funcin de utilidad:

let board = Checkerboard()

println(board.squareIsBlackAtRow(0, column: 1))

// imprime "verdadera"

println(board.squareIsBlackAtRow(9, column: 9))

// imprime "falsa"

Deinicializacin
En esta pgina
A deinitializer se llama inmediatamente antes de que se cancela la asignacin de una
instancia de clase.Usted escribe deinitializers con la deinit palabra clave, similar a
cmo intializers se escriben con el initpalabra clave. Deinitializers slo estn
disponibles en los tipos de clase.
Cmo deinicializacin Obras
Swift desasigna automticamente los casos en los que ya no son necesarios, para liberar
recursos. Swift se encarga de la gestin de memoria de casos a travs de la cuenta de
referencias automtico ( ARC ), como se describe en la cuenta automtica de
referencia . Normalmente no es necesario para llevar a cabo manual de limpieza cuando
se desasignan las instancias. Sin embargo, cuando se est trabajando con sus propios
recursos, es posible que deba realizar alguna limpieza adicional a ti mismo. Por
ejemplo, si crea una clase personalizada para abrir un archivo y escribir algunos datos
en l, es posible que tenga que cerrar el archivo antes de que se cancela la asignacin de
la instancia de clase.
Definiciones de clase pueden tener como mximo un deinitializer por clase. El
deinitializer no toma ningn parmetro y se escribe sin parntesis:

183

deinit {

// Realizar la deinicializacin
}
Deinitializers se denominan de forma automtica, justo antes de desasignacin ejemplo
se lleva a cabo. No se le permite llamar a un deinitializer ti mismo. Deinitializers
superclase son heredados por sus subclases, y la deinitializer superclase se llama
automticamente al final de una aplicacin deinitializer subclase.Deinitializers
superclase siempre se llaman, incluso si una subclase no proporciona su propio
deinitializer.
Debido a que una instancia no se cancela la asignacin hasta despus de su deinitializer
se llama, un deinitializer puede acceder a todas las propiedades de la instancia que se
llama en y puede modificar su comportamiento sobre la base de esas propiedades (tales
como buscar el nombre de un archivo que necesita ser cerrado ).
Deinitializers en Accin
He aqu un ejemplo de un deinitializer en accin. Este ejemplo define dos nuevos
tipos, el Banco y el jugador , para un juego simple. El Banco estructura gestiona
una moneda inventada, que nunca puede tener ms de 10.000 monedas en
circulacin. No puede ser ms que un Banco en el juego, por lo que el Banco se
implementa como una estructura con propiedades y mtodos para almacenar y
administrar su estado actual estticas:

struct Bank {

static var coinsInBank = 10_000

static func vendCoins(var numberOfCoinsToVend: Int) -> Int {

numberOfCoinsToVend = min(numberOfCoinsToVend, coinsInBank)

coinsInBank -= numberOfCoinsToVend

return numberOfCoinsToVend

static func receiveCoins(coins: Int) {

coinsInBank += coins

}
Bank realiza un seguimiento del nmero actual de monedas que tiene con
su coinsInBank propiedad. Tambin ofrece dos mtodosvendCoins y receiveCoins : para manejar la distribucin y recogida de
monedas.
vendCoins comprueba que hay suficientes monedas en el banco antes de
distribuirlos. Si no hay suficientes monedas, Banco devuelve un nmero menor que el
nmero que se solicit (y devuelve cero si no hay monedas se dejan en el
banco). vendCoins declara numberOfCoinsToVend como un parmetro variable,
de modo que el nmero puede ser modificado dentro del mtodo de cuerpo sin la
necesidad de declarar una nueva variable. Devuelve un valor entero que indique el
nmero real de las monedas que se proporcionaron.

184

El receiveCoins mtodo no hace sino aumentar el nmero recibido de las monedas


de nuevo en la tienda de la moneda del banco.
El jugador clase describe un jugador en el juego. Cada jugador tiene un cierto
nmero de monedas almacenadas en su bolso en cualquier momento. Esto est
representado por el jugador coinsInPursepropiedad:

class Player {

var coinsInPurse: Int

init(coins: Int) {

coinsInPurse = Bank.vendCoins(coins)

func winCoins(coins: Int) {

coinsInPurse += Bank.vendCoins(coins)

deinit {

Bank.receiveCoins(coinsInPurse)

}
Cada Player instancia se inicializa con un subsidio inicial de un determinado nmero
de monedas del banco durante la inicializacin, aunque un Player instancia puede
recibir menos de ese nmero, si no hay suficientes monedas estn disponibles.
El player de clase define un winCoins mtodo, que recupera un cierto nmero de
monedas del banco y los agrega a la bolsa del jugador. El player de clase tambin
implementa un deinitializer, que se llama justo antes de un player se desasigna
instancia. Aqu, la deinitializer simplemente devuelve todo de monedas de los jugadores
a la orilla:

var playerOne: Player? = Player(coins: 100)

println("A new player has joined the game with \(playerOne!.coinsInPurse)


coins")

// imprime "Un nuevo jugador se ha unido a la partida con


100 monedas"

println("There are now \(Bank.coinsInBank) coins left in the bank")

// imprime "En la actualidad hay 9.900 monedas que quedan


en el banco"
Un nuevo jugador se crea una instancia, con una solicitud de 100 monedas si estn
disponibles. Este jugadorinstancia se almacena en una opcin del
jugador variable llamada Playerone . Una variable opcional se utiliza aqu, porque
los jugadores pueden abandonar el juego en cualquier momento. El opcional permite
realizar un seguimiento de si actualmente hay un jugador en el juego.

185

Debido Playerone es opcional, es calificado con un signo de exclamacin ( ! cuando


su) coinsInPurse se accede a la propiedad a imprimir su nmero predeterminado de
monedas, y siempre que su winCoins se llama al mtodo:

playerOne!.winCoins(2_000)

println("PlayerOne won 2000 coins & now has \(playerOne!.coinsInPurse)


coins")

// Impresiones "Playerone ganado 2000 monedas y ahora tiene


2.100 monedas"

println("The bank now only has \(Bank.coinsInBank) coins left")

// imprime "El banco ahora slo ha 7900 monedas de la


izquierda"
Aqu, el jugador ha ganado 2.000 monedas. Bolso del jugador ahora contiene 2.100
monedas, y el banco tiene slo 7.900 monedas fueron.

playerOne = nil

println("PlayerOne has left the game")

// Impresiones "Playerone ha dejado el juego"

println("The bank now has \(Bank.coinsInBank) coins")

// Impresiones "El banco ahora tiene 10.000 monedas"


El jugador ya ha dejado el juego. Esto se indica mediante el establecimiento de la
opcional Playerone variablenula , lo que significa "no jugador instancia. "En el
momento que esto sucede, el Playerone referencia de variable al jugador instancia
est roto. No hay otras propiedades o variables siguen refiriendo al jugadorinstancia,
y por lo que se desasignan con el fin de liberar su memoria. Justo antes de que esto
sucede, su deinitializer se llama de forma automtica, y sus monedas se devuelven al
banco.
Conteo automtico de Referencia
Swift utiliza el recuento de referencias automtico (ARC) para rastrear y administrar el
uso de la memoria de su aplicacin. En la mayora de los casos, esto significa que la
gestin de la memoria "simplemente funciona" en Swift, y usted no tiene que pensar en
la gestin de memoria usted mismo. ARC libera automticamente la memoria utilizada
por las instancias de clase cuando esos casos ya no son necesarios.
Sin embargo, en unos pocos casos ARC requiere ms informacin acerca de las
relaciones entre las partes de su cdigo con el fin de gestionar la memoria para
usted. En este captulo se describen las situaciones y muestra cmo se habilita ARC
para gestionar toda la memoria de su aplicacin.
NOTA
El conteo de referencias slo se aplica a las instancias de clases. Estructuras y
enumeraciones son tipos de valor, no hacen referencia a tipos, y no se almacenan y se
pasan por referencia.

186

Cmo ARC Obras


Cada vez que se crea una nueva instancia de una clase, ARC asigna un trozo de
memoria para almacenar informacin sobre esa instancia. Esta memoria contiene
informacin sobre el tipo de la instancia, junto con los valores de propiedades
almacenados asociados con esa instancia.
Adems, cuando ya no se necesita una instancia, ARC libera la memoria utilizada por la
instancia para que la memoria puede ser utilizado para otros fines en lugar. Esto
garantiza que las instancias de clase no ocupan espacio en la memoria cuando ya no son
necesarios.
Sin embargo, si ARC eran desasignar una instancia que todava estaba en uso, que ya no
sera posible acceder a las propiedades de esa instancia, o llamar a los mtodos de esa
instancia. De hecho, si se trat de acceder a la instancia, su aplicacin lo ms probable
accidente.
Para asegurarse de que los casos no desaparecen, mientras que todava se necesitan,
ARC rastrea cuntos propiedades, constantes y variables se refieren actualmente a cada
instancia de clase. ARC no desasignar una instancia, siempre y cuando todava existe al
menos una referencia activa a esa instancia.
Para que esto sea posible, cada vez que se asigna una instancia de clase a una propiedad,
constante o variable, propiedad, constante o variable hace una fuerte referencia a la
instancia. La referencia se llama una referencia "fuerte", ya que mantiene un firme
control sobre esa instancia, y no permitir que se cancela la asignacin durante el tiempo
que sigue siendo tan fuerte como referencia.
ARC en Accin
He aqu un ejemplo de cmo funciona automticas de referencia de conteo. Este
ejemplo comienza con una clase simple llamada persona , que define una propiedad
denominada constante almacenado nombre :

class Person {

let name: String

init(name: String) {

self.name = name

println("\(name) is being initialized")

deinit {

println("\(name) is being deinitialized")

}
La person de clase tiene un inicializador que establece la instancia de name de
propiedad e imprime un mensaje para indicar que la inicializacin est en
marcha. La person de clase tambin tiene un deinitializer que imprime un mensaje
cuando se cancela la asignacin de una instancia de la clase.
El siguiente fragmento de cdigo define tres variables de tipo person? , que se
utilizan para configurar varias referencias a una nueva person instancia en fragmentos
de cdigo siguientes. Debido a que estas variables son de tipo opcional ( person? ,

187

no person ), que se inicializa automticamente con un valor de cero , y actualmente


no hace referencia a una persona instancia.

var reference1: Person?

var reference2: Person?

var reference3: Person?


Ahora puede crear una nueva persona instancia y asignarlo a una de estas tres
variables:

reference1 = Person(name: "John Appleseed")

// Impresiones "John Appleseed se inicializa"


Tenga en cuenta que el mensaje de "John Appleseed se inicializa" se
imprime en el punto que se llama a lapersona inicializador de clase. Esto confirma
que la inicializacin ha tenido lugar.
Debido a la nueva persona instancia se ha asignado a la referencia1 variables,
ahora hay una fuerte referencia de referencia1 a la
nueva persona instancia. Debido a que existe al menos una referencia fuerte, ARC se
asegura de que esta persona se mantiene en la memoria y no se cancela la asignacin.
Si asigna la misma persona instancia a dos variables ms, dos ms fuertes referencias
a esa instancia se establecen:

reference2 = reference1

reference3 = reference1
En la actualidad hay tres referencias fuertes a esta nica persona instancia.
Si se rompe dos de estas referencias fuertes (incluyendo la referencia original)
asignando cero a dos de las variables, una sola fuertes vestigios de referencia, y
la persona instancia no se cancela la asignacin:

reference1 = nil

reference2 = nil
ARC no desasigna la persona instancia hasta que se rompe la tercera y ltima
referencia fuerte, momento en el que es evidente que ya no ests usando
la Person ejemplo:

reference3 = nil

// Impresiones "John Appleseed est siendo deinitialized"



Ciclos de referencia fuertes entre instancias de clase
En los ejemplos anteriores, ARC es capaz de rastrear el nmero de referencias a la
nueva persona instancia crear y desasignar que persona instancia cuando ya no se
necesita.
Sin embargo, es posible escribir cdigo en el que una instancia de una clase nunca llega
a un punto donde tiene cero referencias fuertes. Esto puede suceder si dos instancias de
la clase tienen una fuerte referencia el uno al otro, de tal manera que cada instancia
mantiene el otro vivo. Esto se conoce como un ciclo de referencia fuerte .
A resolver los ciclos de referencia fuertes mediante la definicin de algunas de las
relaciones entre las clases como referencias dbiles o sin dueo en lugar de referencias

188

tan fuertes. Este proceso se describe en laResolucin de Ciclos de referencia fuertes


entre instancias de clase . Sin embargo, antes de aprender cmo resolver un ciclo de
referencia fuerte, es til para entender cmo se produce tal ciclo.
He aqu un ejemplo de cmo un ciclo de referencia fuerte se puede crear por
accidente. Este ejemplo define dos clases llamadas Persona y Apartamento , cul
es el modelo de un bloque de apartamentos y sus residentes:

class Person {

let name: String

init(name: String) { self.name = name }

var apartment: Apartment?

deinit { println("\(name) is being deinitialized") }

class Apartment {

let number: Int

init(number: Int) { self.number = number }

var tenant: Person?

deinit { println("Apartment #\(number) is being deinitialized") }

}
Cada person instancia tiene un nombre de propiedad de tipo Cadena y un
opcional apartament propiedad que es
inicialmente cero . El apartament propiedad es opcional, porque una persona no
siempre puede tener un apartamento.
Del mismo modo, cada apartament instancia tiene un number property de
tipo int y tiene un opcionalinquilino propiedad que es inicialmente cero . La
propiedad es opcional porque el inquilino de un apartamento no siempre puede tener un
inquilino.
Ambas clases tambin definen un deinitializer, que imprime el hecho de que se est
deinitialized una instancia de esa clase. Esto le permite ver si las instancias
de Persona y Apartamento se desasignan como se esperaba.
Este siguiente fragmento de cdigo define dos variables de tipo opcional
llamado juan y number73 , que se establece en un
determinado Apartamento y Persona ejemplo a continuacin. Ambas variables
tienen un valor inicial de cero , en virtud de ser opcional:

var john: Person?

var number73: Apartment?


Ahora puede crear una especfica persona instancia y Apartamento instancia y
asignar estas nuevas instancias a las juan y number73 variables:

john = Person(name: "John Appleseed")

number73 = Apartment(number: 73)

189

He aqu cmo las referencias fuertes cuidan de creacin y asignacin de estas dos
instancias. El johnvariable de ahora tiene una fuerte referencia a la
nueva persona instancia, y el number73 variables tiene una fuerte referencia a la
nueva Apartamento ejemplo:


Ahora puede enlazar los dos casos juntos para que la persona tiene un apartamento, y el
apartamento tiene un inquilino. Tenga en cuenta que un signo de exclamacin ( ! se
utiliza para desenvolver y acceder a las instancias almacenadas en el interior
del) john y number73 las variables opcionales, por lo que las propiedades de esos
casos se pueden establecer:

john !. apartamento = number73

number73 !. inquilino = john


As es como las referencias fuertes cuidan de vincular los dos casos juntos:


Desafortunadamente, uniendo estos dos casos crea un fuerte ciclo de referencia entre
ellos. La Personaejemplo ahora tiene una fuerte referencia
al Apartamento ejemplo, y el Apartamento instancia tiene una fuerte referencia a
la persona de instancia. Por lo tanto, cuando se rompen las referencias fuertes en
poder de losjohn y number73 las variables, los recuentos de referencias no bajan a
cero, y los casos no se desasignan por ARC:

john = nil

number73 = nil
Tenga en cuenta que ni deinitializer fue llamado al configurar estas dos variables
a cero . El ciclo de referencia fuerte impide que la persona y Apartamento casos
que alguna vez se cancela la asignacin, causando una prdida de memoria en su
aplicacin.

190

As es como las referencias fuertes se ven despus de establecer


los john y number73 las variables a cero :


Las fuertes referencias entre la persona y la instancia Apartamento instancia
permanecen y no se pueden romper.
Resolver Ciclos de referencia fuertes entre instancias de clase
Swift proporciona dos formas de resolver los ciclos de referencia fuertes cuando se
trabaja con las propiedades de tipo de clase: referencias dbiles y referencias sin dueo.
Referencias dbiles y sin dueo permiten una instancia en un ciclo de referencia para
referirse a la otra instancia y sin mantener un fuerte control sobre el mismo. Los casos
pueden entonces referirse unos a otros sin crear un ciclo de referencia fuerte.
Utilice una referencia dbil siempre que sea vlida para que se convierta en
referencia nula en algn momento durante su vida til. Por el contrario, utilice una
referencia sin dueo cuando se sabe que la referencia nunca ser nula una vez que se
ha establecido durante la inicializacin.
Referencias dbiles
Una referencia dbil es una referencia que no mantiene una fuerte influencia en la
instancia que se refiere, por lo que no deja de ARC de la eliminacin de la instancia de
referencia. Este comportamiento impide que la referencia se conviertan en parte de un
ciclo de referencia fuerte. Usted indica una referencia dbil mediante la colocacin de
la dbil palabra clave antes de una propiedad o declaracin de variables.
Utilice una referencia dbil para evitar los ciclos de referencia, siempre que sea posible
para que la referencia a tener "ningn valor" en algn momento de su vida. Si la
referencia ser siempre tener un valor, utilizar una referencia sin dueo en su lugar,
como se describe en las referencias sin propietario . En el Apartamentoejemplo
anterior, es apropiado para un apartamento para poder tener "ningn inquilino" en algn
momento de su vida til, por lo que una referencia dbil es una forma adecuada para
romper el ciclo de referencia en este caso.
NOTA
Referencias dbiles deben ser declaradas como variables, para indicar que su valor
puede cambiar en tiempo de ejecucin. Una referencia dbil no puede ser declarada
como una constante.
Debido a las referencias dbiles se les permite tener "ningn valor", debe declarar cada
referencia dbil como tener un tipo opcional. Tipos opcionales son la mejor forma de
representar la posibilidad de que "ningn valor" en Swift.

191

Debido a una referencia dbil no mantiene una fuerte influencia en la instancia que se
refiere, es posible que esa instancia para cancelar la asignacin, mientras que la
referencia dbil todava se est refiriendo a la misma. Por lo tanto, ARC establece
automticamente una referencia dbil a cero cuando la instancia que se refiere a que se
cancela la asignacin. Usted puede comprobar la existencia de un valor en la referencia
dbil, al igual que cualquier otro valor opcional, y que nunca va a terminar con una
referencia a una instancia vlida de que ya no existe.
El siguiente ejemplo es idntico al de la persona y Apartamento ejemplo desde
arriba, con una diferencia importante. Esta vez, el Apartamento de
tipo inquilino propiedad se declara como una referencia dbil:

class Person {

let name: String

init(name: String) { self.name = name }

var apartment: Apartment?

deinit { println("\(name) is being deinitialized") }

class Apartment {

let number: Int

init(number: Int) { self.number = number }

weak var tenant: Person?

deinit { println("Apartment #\(number) is being deinitialized") }

}
Las fuertes referencias de las dos variables ( juan y number73 ) y los vnculos entre
las dos instancias se crean como antes:

var john: Person?

var number73: Apartment?

john = Person(name: "John Appleseed")

number73 = Apartment(number: 73)

john!.apartment = number73

number73!.tenant = john
As es como las referencias se ven ahora que usted ha enlazado las dos instancias a la
vez:

192


La persona instancia todava tiene una fuerte referencia al Apartamento instancia,
pero el Apartamento ejemplo ahora tiene una dbil referencia a la persona de
instancia. Esto significa que cuando se rompe la referencia fuerte en poder de
los john las variables, no hay referencias ms fuertes a la persona ejemplo:


Debido a que no existen referencias ms fuertes a la Persona ejemplo, se cancela la
asignacin:

john = nil

// Impresiones "John Appleseed est siendo deinitialized"


La fuerte referencia solamente restante al Apartamento instancia es
del number73 variable. Si usted rompe esareferencia fuerte, no hay ms fuertes
referencias al Apartamento ejemplo:


Debido a que no hay ms fuertes referencias al Apartamento ejemplo, tambin lo es
desasignada:

193

number73 = nil

// Impresiones "Apartamento # 73 est siendo deinitialized"


Los dos fragmentos de cdigo finales anteriores muestran que los deinitializers para
la persona instancia yApartamento instancia imprimen sus mensajes
"deinitialized" despus de las juan y number73 variables se ponen a cero . Esto
demuestra que el ciclo de referencia se ha roto.
Referencias sin propietario
Como referencias dbiles, una referencia sin dueo no mantiene una fuerte influencia
en la instancia que se refiere. A diferencia de una referencia dbil, sin embargo, se
supone que una referencia sin dueo parasiempre tener un valor. Debido a esto, una
referencia sin dueo siempre se define como un tipo no opcional.Usted indica una
referencia sin dueo colocando el unowned palabra clave antes de una propiedad o
declaracin de variables.
Porque una referencia sin dueo no es opcional, no es necesario para desenvolver la
referencia sin dueo cada vez que se utiliza. Una referencia sin dueo siempre se puede
acceder directamente. Sin embargo, ARC no puede establecer la referencia
a cero cuando la instancia se refiere a que se cancela la asignacin, ya que las
variables de un tipo no opcional, no se pueden establecer en cero .
NOTA
Si intenta acceder a una referencia sin dueo tras la instancia que hace referencia se
cancela la asignacin, se activar un error de ejecucin. Utilice referencias sin dueo
slo cuando est seguro de que la referencia ser siempre referirse a una instancia.
Tenga en cuenta tambin que Swift garantiza su aplicacin se bloquear si se intenta
acceder a una referencia sin dueo tras la instancia que hace referencia se cancela la
asignacin. Usted nunca va a encontrar un comportamiento inesperado en esta
situacin. Su aplicacin siempre se bloquear de forma fiable, aunque debe, por
supuesto, evitar que lo hagan.
El ejemplo siguiente define dos clases, los clientes y la tarjeta de
crdito , cul es el modelo de un cliente de un banco y de una posible tarjeta de
crdito para ese cliente. Estas dos clases de cada tienda una instancia de la otra clase
como una propiedad. Esta relacin tiene el potencial de crear un ciclo de referencia
fuerte.
La relacin entre el cliente y la tarjeta de crdito es un poco diferente de
la relacin entre la Casa y lapersona se ve en el ejemplo de referencia por encima
dbil. En este modelo de datos, un cliente puede o no puede tener una tarjeta de crdito,
una tarjeta de crdito pero ser siempre estar asociada con un cliente.Para representar
esto, el cliente de clase tiene una opcional tarjeta de propiedad, pero el la
tarjeta de crdito tiene una clase no opcional cliente propiedad.
Por otra parte, un nuevo la tarjeta de crdito instancia puede slo ser creado
al pasar un nmero de valor y un cliente de instancia a un encargo la tarjeta
de crdito inicializador. Esto asegura que una la tarjeta de
crdito instancia siempre tiene un cliente de instancia asociado con l cuando
el la tarjeta de crdito se crea una instancia.
Debido a que una tarjeta de crdito tendr siempre un cliente, definir su cliente la
propiedad como una referencia sin dueo, para evitar un ciclo de referencia fuerte:

194

class Customer {

let name: String

var card: CreditCard?

init(name: String) {

self.name = name

deinit { println("\(name) is being deinitialized") }

class CreditCard {

let number: UInt64

unowned let customer: Customer

init(number: UInt64, customer: Customer) {

self.number = number

self.customer = customer

deinit { println("Card #\(number) is being deinitialized") }

}
NOTA
El nmero de propiedad del la tarjeta de crdito de clase se define con un
tipo de UInt64 lugar de Int , para asegurar que el nmero de la capacidad de la
propiedad es lo suficientemente grande como para guardar un nmero de tarjeta de 16
dgitos en ambos sistemas de 32 bits y 64 bits.
Este siguiente fragmento de cdigo define una opcional Cliente variable
llamada John , que se utiliza para almacenar una referencia a un cliente
especfico. Esta variable tiene un valor inicial de cero, en virtud de ser opcional:

var john: Customer?


Ahora puede crear un cliente de ejemplo, y lo utilizan para inicializar y asignar un
nuevo la tarjeta de crdito como ejemplo de ese cliente la tarjeta
de propiedad:

john = Customer(name: "John Appleseed")

john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)

195

As es como se ven las referencias, ahora que usted ha enlazado las dos instancias:


El cliente de ejemplo ahora tiene una fuerte referencia a la la tarjeta de
crdito instancia, y el la tarjeta de crdito instancia tiene una referencia
sin dueo al Cliente instancia.
Debido a la unowned cliente de referencia, cuando se rompe la referencia fuerte en
poder del john variables, no hay ms fuertes referencias al Cliente ejemplo:


Debido a que no existen referencias ms fuertes al Cliente ejemplo, se cancela la
asignacin. Despus de esto, no hay ms fuertes referencias al creditcard ejemplo,
y tambin lo es desasignada:

john = nil

// Impresiones "John Appleseed est siendo deinitialized"

// Impresiones "Tarjeta # 1234567890123456 est siendo


deinitialized"
El fragmento de cdigo final anterior muestra que los deinitializers para el cliente
de la instancia y la tarjeta de crdito instancia tanto imprimir sus mensajes
de "deinitialized" despus de la john variable se establece en cero .
Referencias sin propietario y propiedades opcionales Implcitamente
Unwrapped
Los ejemplos de referencias dbiles y sin dueo por encima de la cubierta de dos de los
escenarios ms comunes en las que es necesario romper un ciclo de referencia fuerte.

196

La persona y Apartamento ejemplo muestra una situacin en la que dos


propiedades, los cuales se les permite ser nulo , tienen el potencial de causar un ciclo
de referencia fuerte. Este escenario se resuelve mejor con una referencia dbil.
El cliente y la tarjeta de crdito ejemplo muestra una situacin en la que
una propiedad que se le permite ser nulo y otra propiedad que no puede
ser nula tienen el potencial de causar un ciclo de referencia fuerte.Este escenario se
resuelve mejor con una referencia sin dueo.
Sin embargo, hay un tercer escenario, en el que ambas propiedades deben tener siempre
un valor, y ni propiedad debe nunca ser nil una vez se completa la inicializacin. En
este escenario, es til combinar una propiedad sin dueo en una clase con una propiedad
opcional implcitamente sin envolver en la otra clase.
Esto permite a ambas propiedades para acceder directamente (sin desenvolver opcional)
una vez completada la inicializacin, evitando al mismo tiempo un ciclo de
referencia. En esta seccin se muestra cmo configurar una relacin de este tipo.
El ejemplo siguiente define dos clases, Pas y ciudad , cada una de ellas con una
instancia de la otra clase como una propiedad. En este modelo de datos, cada pas debe
tener siempre una ciudad capital, y cada ciudad siempre debe pertenecer a un pas. Para
representar esto, el pas tiene una clase capitalCitypropiedad, y la Ciudad
de la clase tiene un pas de propiedad:

class Country {

let name: String

let capitalCity: City!

init(name: String, capitalName: String) {

self.name = name

self.capitalCity = City(name: capitalName, country: self)

class City {

let name: String

unowned let country: Country

init(name: String, country: Country) {

self.name = name

self.country = country

}
Para configurar la interdependencia entre las dos clases, el inicializador para la
ciudad toma un Pasinstancia, y almacena esta instancia en su pas la propiedad.
El inicializador para la ciudad se llama desde dentro del inicializador de Pas . Sin
embargo, el inicializador dePas no puede pasar a uno mismo a la Ciudad de

197

inicializacin hasta que un nuevo Pas instancia est totalmente inicializado, como se
describe en dos fase de inicializacin .
Para hacer frente a este requisito, se declara la capitalCity propiedad
del pas como una propiedad opcional implcitamente sin envolver, indicado por el
signo de exclamacin al final de su tipo de anotacin ( Ciudad! ).Esto significa que
el capitalCity propiedad tiene un valor por defecto de cero , como cualquier otro
opcional, pero se puede acceder sin necesidad de desenvolver su valor como se describe
en forma implcita Unwrapped Opcionales .
Debido capitalCity tiene un valor predeterminado cero valor, un
nuevo Pas instancia se considera totalmente inicializado tan pronto como
el Pas instancia establece su nombre de la propiedad dentro de su
inicializador.Esto significa que el Pas inicializador puede empezar a referenciar y
pasar alrededor de la implcita autopropiedad tan pronto como el nombre de la
propiedad se establece. El Pas , por lo tanto inicializador puede pasar a uno
mismo como uno de los parmetros para la Ciudad de inicializacin cuando
el Pas inicializador est estableciendo su propio capitalCity propiedad.
Todo esto significa que usted puede crear los Pas y Ciudad casos en una sola
sentencia, sin crear un ciclo de referencia fuerte, y el capitalCity propiedad se
puede acceder directamente, sin necesidad de utilizar un signo de exclamacin a
desenvolver su valor opcional:

var country = Country(name: "Canada", capitalName: "Ottawa")

println("\(country.name)'s capital city is called \(country.capitalCity.name)")

// Imprime "la capital de Canad es Ottawa llama"


En el ejemplo anterior, el uso de un opcional envolver implcitamente significa que
todos los requisitos inicializador de la clase de dos fases son
satisfechos. El capitalCity propiedad se puede utilizar y se accede como un valor
no opcional una vez completada la inicializacin, mientras que todava evitando un
ciclo de referencia fuerte.
Ciclos de referencia fuertes para cierres
Usted vio anteriormente cmo un ciclo de referencia fuerte se puede crear cuando dos
propiedades de la instancia de clase tienen una fuerte referencia a la otra. Tambin
hemos visto cmo utilizar referencias dbiles y sin dueo para romper estos ciclos de
referencia fuertes.
Un ciclo de referencia fuerte tambin puede ocurrir si asigna un cierre a una propiedad
de una instancia de clase, y el cuerpo de que el cierre capta la instancia. Esta captura
puede ocurrir porque el cuerpo del cierre de acceso a una propiedad de la instancia,
como self.someProperty , o porque el cierre llama a un mtodo en la instancia,
como self.someMethod () . En cualquiera de los casos, estos accesos causan el
cierre de la "captura" de auto , la creacin de un ciclo de referencia fuerte.
Este ciclo de referencia fuerte se produce porque los cierres, como las clases, son tipos
de referencia .Cuando se asigna un cierre a una propiedad, usted est asignando
una referencia a que el cierre. En esencia, es el mismo problema que el anterior de dos
referencias fuertes mantienen vivos unos a otros. Sin embargo, en lugar de dos

198

instancias de clase, esta vez se trata de una instancia de clase y un cierre que se
mantena vivos unos a otros.
Swift ofrece una solucin elegante a este problema, conocido como una lista de captura
de cierre . Sin embargo, antes de aprender cmo romper un ciclo de referencia fuerte
con una lista de captura de cierre, es til para entender cmo un ciclo de este tipo puede
ser causado.
El siguiente ejemplo muestra cmo se puede crear un ciclo de referencia fuerte cuando
se utiliza un cierre que hace referencia a s mismo . Este ejemplo define una clase
llamada HTMLElement , que proporciona un modelo simple para un elemento
individual dentro de un documento HTML:

class HTMLElement {

let name: String

let text: String?

lazy var asHTML: () -> String = {

if let text = self.text {

return "<\(self.name)>\(text)</\(self.name)>"

} else {

return "<\(self.name) />"

init(name: String, text: String? = nil) {

self.name = name

self.text = text

deinit {

println("\(name) is being deinitialized")

}
El HTMLElement clase define un nombre de propiedad, lo que indica el nombre del
elemento, como "p" para un elemento de prrafo, o "br" para un elemento de salto de
lnea. HTMLElement tambin define una opcin de texto propiedad, la cual se
puede establecer a un cadena que representa el texto que se dictar dentro de ese
elemento HTML.
Adems de estas dos propiedades simples, la HTMLElement clase define una
propiedad perezoso llamadoasHTML . Esta propiedad hace referencia a un cierre que

199

combina el nombre y el texto en un fragmento de cadena


HTML. El asHTML propiedad es de tipo () -> Cadena , o "una funcin que no
toma parmetros y devuelve una Cadena de Valor ".
Por defecto, el asHTML propiedad se le asigna un cierre que devuelve una
representacin de cadena de una etiqueta HTML. Esta etiqueta contiene la opcin de
texto de valor si existe, o si no el contenido de texto de texto no existe. Para un
elemento de prrafo, el cierre volvera "<p> texto </ p>" o "<p />" ,
dependiendo de si el texto propiedad es igual a "algn texto" o nula .
El asHTML propiedad se llama y usa un poco como un mtodo de instancia. Sin
embargo, debido asHTML es una propiedad de cierre en lugar de un mtodo de
instancia, puede reemplazar el valor predeterminado de laasHTML propiedad con un
cierre de encargo, si usted desea cambiar la representacin HTML para un elemento
HTML en particular.
NOTA
El asHTML propiedad se declara como una propiedad perezoso, ya que slo es
necesario si y cuando el elemento realmente necesita ser traducido como un valor de
cadena por algn objetivo de salida HTML. El hecho de que asHTML es una propiedad
perezoso significa que usted puede referirse a s mismo dentro del cierre por defecto,
ya que no se accede a la propiedad perezoso hasta despus de la inicializacin se ha
completado y s se sabe que existen.
El HTMLElement clase proporciona un nico inicializador, que tiene un nombre
de argumento y (si lo desea) untexto argumento para inicializar un nuevo
elemento. La clase tambin define un deinitializer, que imprime un mensaje para
mostrar cuando un HTMLElement se desasigna instancia.
He aqu cmo se utiliza el HTMLElement clase para crear e imprimir una nueva
instancia:

var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello,


world")

println(paragraph!.asHTML())

// imprime "<p> hola, mundo </ p>"


NOTA
El paragraph variable de arriba se define como un opcional HTMLElement , de
modo que se puede ajustar a nuloa continuacin para demostrar la presencia de un
ciclo de referencia fuerte.
Por desgracia, la HTMLElement clase, como est escrito ms arriba, crea un fuerte
ciclo de referencia entre unHTMLElement instancia y el cierre empleado para su
defecto asHTML valor. As es como se ve el ciclo:

200


Del ejemplo asHTML propiedad se mantiene una fuerte referencia a su cierre. Sin
embargo, debido a que el cierre se refiere a la auto dentro de su cuerpo (como una
forma de referencia self.name y self.text ), el cierre captura auto, lo que
significa que contiene una referencia de nuevo a la fuerte HTMLElement ejemplo. Se
crea un ciclo de referencia fuerte entre los dos. (Para obtener ms informacin acerca de
la captura de los valores en un cierre, consulte Captura de valores .)
NOTA
A pesar de que el cierre se refiere a s mismo varias veces, slo capta una fuerte
referencia a la HTMLElementinstancia.
Si establece el prrafo variable nula y romper su fuerte referencia a
la HTMLElement ejemplo, ni el HTMLElementinstancia ni su cierre se desasignan,
debido al ciclo de referencia fuerte:
prrafo = nil
Tenga en cuenta que el mensaje en el HTMLElement deinitializer no se imprime, lo
que demuestra que laHTMLElement instancia no se cancela la asignacin.
Resolver Ciclos de referencia fuertes para cierres
A resolver un fuerte ciclo de referencia entre un cierre y una instancia de clase
definiendo una lista de capturacomo parte de la definicin de la clausura. Una lista de
captura define las reglas para usar en la captura de uno o ms tipos de referencia dentro
del cuerpo del cierre. Al igual que con fuertes ciclos de referencia entre dos instancias
de la clase, se declara cada referencia capturado para ser una referencia dbil o sin
dueo en lugar de una referencia fuerte. La eleccin adecuada de dbil o sin dueo
depende de las relaciones entre las diferentes partes de su cdigo.
NOTA
Swift requiere que usted escriba self.someProperty o self.someMethod (en
lugar de slo UnaPropiedad oalgunMetodo ) siempre hace referencia a un
miembro del auto dentro de un cierre. Esto le ayudar a recordar que es posible
capturar auto por accidente.
Definicin de una lista de captura
Cada elemento de una lista de captura es un acoplamiento entre el dbil o sin
dueo palabra clave con una referencia a una instancia de clase (por
ejemplo, auto o someInstance ). Estos emparejamientos se escriben dentro de un
par de corchetes, separados por comas.

201

Coloque la lista de captura antes de la lista de parmetros de un cierre y tipo de retorno


si se les proporciona:

lazy var someClosure: (Int, String) -> String = {

[unowned self] (index: Int, stringToProcess: String) -> String in

// Cuerpo de cierre va aqu

}
Si un cierre no especifica una lista de parmetros o tipo de retorno, ya que pueden ser
inferidos a partir del contexto, coloque la lista de captura en el comienzo del cierre,
seguido por el de palabra clave:

lazy var someClosure: () -> String = {

[unowned self] in

// Cuerpo de cierre va aqu

}
Referencias dbiles y sin propietario
Definir una captura en un cierre como una referencia sin dueo cuando el cierre y la
instancia de captura siempre referirse unos a otros, y siempre se desasigna al mismo
tiempo.
Por el contrario, definir una captura como una referencia dbil cuando la referencia
capturado puede llegar a ser nula en algn momento en el futuro. Referencias dbiles
son siempre de tipo opcional, y se convierten automticamente a cero cuando se
desasigna la instancia que hacen referencia. Esto le permite comprobar su existencia
dentro del cuerpo del cierre.
NOTA
Si la referencia capturado nunca llegar a ser nula , siempre debe ser capturado como
una referencia sin dueo, en lugar de una referencia dbil.
Una referencia sin dueo es el mtodo de captura apropiado utilizar para resolver el
ciclo de referencia fuerte en el HTMLElement ejemplo de antes. He aqu cmo usted
escribe el HTMLElement clase para evitar el ciclo:

class HTMLElement {

let name: String

let text: String?

lazy var asHTML: () -> String = {

[unowned self] in

if let text = self.text {

return "<\(self.name)>\(text)</\(self.name)>"

} else {

return "<\(self.name) />"

202

init(name: String, text: String? = nil) {

self.name = name

self.text = text

deinit {

println("\(name) is being deinitialized")

}
la adicin de una lista de captura dentro de la asHTML cierre. En este caso, la lista de
captura es [auto sin dueo] , que significa "auto captura como una referencia sin
dueo en lugar de una referencia fuerte".
Puede crear e imprimir un HTMLElement ejemplo de antes:

var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello,


world")

println(paragraph!.asHTML())

// imprime "<p> hola, mundo </ p>"


He aqu cmo las referencias se ven con la lista de captura en su lugar:


Esta vez, la captura de uno mismo por el cierre es una referencia sin dueo, y no
mantiene una fuerte influencia en la HTMLElement instancia que ha capturado. Si
establece la fuerte referencia del prrafo variable en nil , la HTMLElement se
desasigna ejemplo, como se puede ver desde la impresin de su mensaje deinitializer en
el siguiente ejemplo:

paragraph = nil

// Impresiones "p est siendo deinitialized"



203

Encadenamiento Opcional
Encadenamiento opcional es un proceso para consultar y llamar a las propiedades,
mtodos y subndices en una opcin que en la actualidad podra ser nula . Si la opcin
contiene un valor, la propiedad, mtodo o llamada subndice tiene xito; si la opcin
es nula , la propiedad, mtodo o llamada subndice retornos nil .Mltiples consultas
pueden ser encadenados juntos, y toda la cadena falla con gracia si cualquier eslabn de
la cadena es nula .
NOTA
Encadenamiento Opcional en Swift es similar a la mensajera nula en Objective-C,
pero de una manera que funcione para cualquier tipo, y que se puede comprobar por el
xito o el fracaso.
El encadenamiento opcional como alternativa a forzado Unwrapping
Se especifica el encadenamiento opcional mediante la colocacin de un signo de
interrogacin ( ? ) tras el valor opcional en la que desea llamar a una propiedad, mtodo
o subndice si el opcional es no nula . Esto es muy similar a la colocacin de un signo
de exclamacin ( ! ) despus de un valor opcional para forzar el desembalaje de su
valor. La principal diferencia es que el encadenamiento opcional falla con gracia cuando
la opcin es nula , mientras que desenvolver forzada provoca un error de ejecucin
cuando el opcional es nula .
Para reflejar el hecho de que el encadenamiento opcional se puede llamar en
un nulo valor, el resultado de una llamada de encadenamiento opcional es siempre un
valor opcional, incluso si la propiedad, mtodo o subndice que est consultando
devuelve un valor que no sea opcional. Puede utilizar este valor de retorno opcional
para comprobar si la llamada encadenamiento opcional fue exitosa (opcional regresado
contiene un valor), o no tuvo xito debido a una nula valor en la cadena (el valor
opcional devuelto es nulo ).
Especficamente, el resultado de una llamada de encadenamiento opcional es del mismo
tipo que el valor de retorno esperado, pero envuelto en una opcional. Una propiedad que
normalmente devuelve un Int devuelve un int? cuando se accede a travs de
encadenamiento opcional.
Los prximos fragmentos de cdigo muestran cmo opcional encadenamiento difiere de
desenvolver forzada y le permite comprobar si hay xito.
En primer lugar, dos clases llamadas Persona y Residencia se definen:

class Person {

var residence: Residence?

class Residence {

var numberOfRooms = 1

}
Residence casos tener un nico int propiedad llamada numberOfRooms , con un
valor predeterminado de 1 .Person casos tienen un opcional residence propiedad
de tipo Residence? .

204

Si crea una nueva persona instancia, su residencia propiedad est


predeterminado inicializa a cero , en virtud de ser opcional. En el siguiente
cdigo, john tiene una residencia valor de la propiedad de nil :

let john = Person()


Si intenta acceder a la numberOfRooms propiedad de esta persona residencia ,
mediante la colocacin de un signo de exclamacin despus de la residencia para
forzar el desembalaje de su valor, que se activa un error de ejecucin, porque no hay
una residencia de valor para desenvolver:

let roomCount = john.residence!.numberOfRooms

// Esto provoca un error de ejecucin


El cdigo anterior tiene xito cuando john.residence tiene un no- nil de valor y
establecer roomCount a un Intvalor que contiene el nmero apropiado de
habitaciones. Sin embargo, este cdigo siempre provoca un error de ejecucin
cuando la residencia es nula , como se ilustra arriba.
Encadenamiento opcional proporciona una forma alternativa para acceder al valor
de numberOfRooms . Para utilizar el encadenamiento opcional, utilice un signo de
interrogacin en lugar del signo de exclamacin:

if let roomCount = john.residence?.numberOfRooms {

println("John's residence has \(roomCount) room(s).")

} else {

println("Unable to retrieve the number of rooms.")

// imprime "No se puede recuperar el nmero de


habitaciones."
Esto le dice Swift para "cadena" en la opcin de residencia y la propiedad para
recuperar el valor denumberOfRooms si residencia existe.
Debido a que el intento de acceso numberOfRooms tiene el potencial de fallar, el
intento de encadenamiento opcional devuelve un valor de tipo int? , o
"opcional Int ". Cuando residencia es cero , como en el ejemplo anterior, esto
opcional Int tambin ser nula , para reflejar el hecho de que no fue posible acceder
anumberOfRooms .
Tenga en cuenta que esto es cierto a pesar de que numberOfRooms es un no
opcional Int . El hecho de que se realiza una consulta a travs de una cadena opcional
significa que la llamada a numberOfRooms devolver siempre un int? en lugar de
un int .
Puede asignar una Residencia instancia a john.residence , por lo que ya no
tiene un nulo valor:

john.residence = Residence()
john.residence ahora contiene un real Residence ejemplo, en lugar
de cero . Si intenta acceder a numberOfRoomscon el mismo encadenamiento
opcional como antes, ser ahora devolver un int? que contiene el
defectonumberOfRooms valor de 1 :

205

if let roomCount = john.residence?.numberOfRooms {

println("John's residence has \(roomCount) room(s).")

} else {

println("Unable to retrieve the number of rooms.")

// Impresiones "residencia de John posee 1 dormitorio (s)."


Definicin de clases de modelos para opcional encadenamiento
Usted puede utilizar el encadenamiento opcional con llamadas a las propiedades,
mtodos y subndices que son ms de un nivel de profundidad. Esto le permite desglosar
subpropiedades en modelos complejos de tipos interrelacionados, y para comprobar si
es posible acceder a las propiedades, mtodos y subndices en esas subpropiedades.
Los fragmentos de cdigo a continuacin definen cuatro clases de modelo para su uso
en varios ejemplos posteriores, incluyendo ejemplos de encadenamiento opcional
multinivel. Estas clases se expanden sobre lapersona y la Residencia modelo
desde arriba mediante la adicin de una habitacin y Direccin de clase, con
propiedades asociadas, mtodos y subndices.
La persona clase se define de la misma manera que antes:

class Person {

var residence: Residence?

}
La Residencia de clase es ms complejo que antes. Esta vez, la Residencia clase
define una propiedad variable llamada habitaciones , que se inicia con una matriz
vaca de tipo [Sala] :

class Residence {

var rooms = [Room]()

var numberOfRooms: Int {

return rooms.count

subscript(i: Int) -> Room {

get {

return rooms[i]

set {

rooms[i] = newValue

func printNumberOfRooms() {

println("The number of rooms is \(numberOfRooms)")

206

var address: Address?

}
Debido a que esta versin de Residencia almacena una matriz de la
habitacin de los casos, sunumberOfRooms propiedad se implementa como una
propiedad calculada, no una propiedad almacenada. El
computarizada numberOfRooms propiedad simplemente devuelve el valor de
la cuenta de la propiedad de lahabitaciones matriz.
Como un atajo para acceder a su habitaciones matriz, esta versin
de Residencia ofrece un subndice de lectura y escritura que da acceso a la
habitacin en el ndice se solicita en la salas de matriz.
Esta versin de Residencia tambin proporciona un mtodo
llamado printNumberOfRooms , que simplemente imprime el nmero de
habitaciones en la residencia.
Por ltimo, Residencia define una propiedad opcional llamado direccin , con
un tipo de direccin? . LaDireccin tipo de clase de esta propiedad se define a
continuacin.
La Sala de clase utilizada para la salas de matriz es una clase simple con una
propiedad llamada nombre , y un inicializador para establecer esa propiedad a un
nombre local adecuado:

class Room {

let name: String

init(name: String) { self.name = name }

}
La ltima clase en este modelo se llama Direccin . Esta clase tiene tres propiedades
opcionales del tipo de cuerda? . Las dos primeras
propiedades, buildingName y buildingNumber , son formas alternativas para
identificar a un edificio en particular como parte de una direccin. La tercera
propiedad, calle , se utiliza para nombrar la calle para esa direccin:

class Address {

var buildingName: String?

var buildingNumber: String?

var street: String?

func buildingIdentifier() -> String? {

if buildingName != nil {

return buildingName

} else if buildingNumber != nil {

return buildingNumber

} else {

return nil

207

}
La Direccin de clase tambin proporciona un mtodo
llamado buildingIdentifier , que tiene un tipo de retorno de la Cadena? . Este
mtodo comprueba las buildingName y buildingNumber propiedades y
devuelvebuildingName si tiene un valor, o buildingNumber si tiene un valor,
o nil si ni la propiedad tiene un valor.
Acceso a las propiedades A travs Opcional encadenamiento
Como se demuestra en Optional Chaining as an Alternative to Forced Unwrapping,
puede utilizar encadenamiento opcional para acceder a una propiedad en un valor
opcional, y para asegurarse de que ese acceso a la propiedad es un xito.
Utilice las clases definidas anteriormente para crear una nueva persona instancia, y
tratar de acceder a sunumberOfRooms propiedad como antes:

let john = Person()

if let roomCount = john.residence?.numberOfRooms {

println("John's residence has \(roomCount) room(s).")

} else {

println("Unable to retrieve the number of rooms.")

// imprime "No se puede recuperar el nmero de


habitaciones."
Debido john.residence es nula , esta llamada de encadenamiento opcional falla
en la misma manera que antes.
Tambin puede tratar de establecer el valor de una propiedad a travs de
encadenamiento opcional:

let someAddress = Address()

someAddress.buildingNumber = "29"

someAddress.street = "Acacia Road"

john.residence?.address = someAddress
En este ejemplo, el intento de establecer la direccin de la propiedad
de john.residence fallar, porquejohn.residence es actualmente nula .
Mtodos A travs de encadenamiento opcional Calling
Usted puede utilizar el encadenamiento opcional para llamar a un mtodo en un valor
opcional, y para comprobar si ese llamado mtodo es exitoso. Usted puede hacer esto
incluso si ese mtodo no define un valor de retorno.
El printNumberOfRooms mtodo en la Residencia de clase imprime el valor
actual de numberOfRooms . As es como se ve el mtodo:

func printNumberOfRooms() {

println("The number of rooms is \(numberOfRooms)")

}
Este mtodo no especifica un tipo de retorno. Sin embargo, las funciones y los mtodos
con ningn tipo de retorno tienen un tipo de retorno implcita de vaco , como se

208

describe en Funciones Sin Valores retornados .Esto significa que devuelven un valor
de () , o una tupla vaca.
Si se llama a este mtodo en un valor opcional con el encadenamiento opcional, tipo de
retorno del mtodo ser Vaco? , no vaco , porque los valores de retorno son
siempre de tipo opcional cuando se invocan mediante el encadenamiento opcional. Esto
le permite utilizar un si declaracin para comprobar si era posible llamar a
la printNumberOfRooms mtodo, a pesar de que el mtodo no define un valor de
retorno. Compare el valor de retorno de las printNumberOfRooms llaman
contra cero para ver si la llamada al mtodo se ha realizado correctamente:

if john.residence?.printNumberOfRooms() != nil {

println("It was possible to print the number of rooms.")

} else {

println("It was not possible to print the number of rooms.")

// imprime "No fue posible imprimir el nmero de


habitaciones."
Lo mismo ocurre si se intenta establecer una propiedad a travs de encadenamiento
opcional. El ejemplo anterior de Acceso a las propiedades A travs Opcional
encadenamiento intenta establecer una direccin devalor
para john.residence , a pesar de que la residencia propiedad
es nula . Cualquier intento de establecer una propiedad a travs de encadenamiento
opcional devuelve un valor de tipo Vaco? , lo que le permite comparar
contra cero para ver si la propiedad se ha establecido con xito:

if (john.residence?.address = someAddress) != nil {

println("It was possible to set the address.")

} else {

println("It was not possible to set the address.")

// imprime "No fue posible establecer la direccin."


Acceso subndices A travs Opcional encadenamiento
Usted puede utilizar el encadenamiento opcional para tratar de recuperar y establecer un
valor de un subndice en un valor opcional, y para comprobar si esa llamada subndice
tiene xito.
NOTA
Cuando acceda a un subndice en un valor opcional a travs de encadenamiento
opcional, se coloca el signo de interrogacin antes de los apoyos del subndice, no
despus. El signo de interrogacin encadenamiento opcional siempre sigue
inmediatamente despus de la parte de la expresin que es opcional.
El siguiente ejemplo intenta recuperar el nombre de la primera habitacin en la salas
de gama de lajohn.residence establecimiento mediante el subndice definida en

209

la Residencia de clase. Debidojohn.residence es actualmente nula , la


llamada falla subndice:

if let firstRoomName = john.residence?[0].name {

println("The first room name is \(firstRoomName).")

} else {

println("Unable to retrieve the first room name.")

// imprime "No se puede recuperar el primer nombre de la


sala."
El signo de interrogacin encadenamiento opcional en la presente convocatoria
subndice se coloca inmediatamente despus john.residence , antes de que los
soportes de subndice, porque john.residence es el valor opcional en el que se est
intentando encadenamiento opcional.
Del mismo modo, se puede tratar de establecer un nuevo valor a travs de un subndice
con el encadenamiento opcional:

john.residence?[0] = Room(name: "Bathroom")


Este intento de ajuste subndice tambin falla, porque la residencia es
actualmente nula .
Si crea y asigna una real Residence instancia a john.residence , con uno o
ms Habitacin casos en su salas de matriz, puede utilizar
la Residencia subndice para acceder a los elementos reales de
la habitaciones matriz a travs de encadenamiento opcional:

let johnsHouse = Residence()

johnsHouse.rooms.append(Room(name: "Living Room"))

johnsHouse.rooms.append(Room(name: "Kitchen"))

john.residence = johnsHouse

if let firstRoomName = john.residence?[0].name {

println("The first room name is \(firstRoomName).")

} else {

println("Unable to retrieve the first room name.")

// imprime "El primer nombre de la sala es la sala."


Acceso a los subndices de Tipo Opcional
Si un subndice devuelve un valor de tipo opcional, tales como el subndice clave de
Swift Diccionario tipo-lugar un signo de interrogacin despus del parntesis de
cierre del subndice de la cadena en su valor de retorno opcional:

var testScores = ["Dave": [86, 82, 84], "Bev": [79, 94, 81]]

testScores["Dave"]?[0] = 91

testScores["Bev"]?[0]++
210

testScores["Brian"]?[0] = 72

// La matriz "Dave" es ahora [91, 82, 84] y la matriz "Bev"


es ahora [80, 94, 81]
El ejemplo anterior define un diccionario llamado testScores , que contiene dos
pares clave-valor que asignan una cuerda clave para una gran variedad
de Int valores. El ejemplo utiliza el encadenamiento opcional para establecer el primer
elemento de la "Dave" matriz a 91 ; para incrementar el primer elemento de
la "Bev" matriz por 1 ; y para tratar de establecer el primer elemento de una matriz
para una clave de "Brian" . Las dos primeras llamadas a tener xito, porque
el testScores diccionario contiene las claves para "Dave" y "Bev" . La tercera
llamada falla, porque el testScores diccionario no contiene una clave
para "Brian" .
La vinculacin de Mltiples Niveles de encadenamiento
Puede vincular mltiples niveles de encadenamiento opcional para profundizar en las
propiedades, mtodos y subndices ms profundo dentro de un modelo. Sin embargo,
mltiples niveles de encadenamiento opcional no aaden ms niveles de opcionalidad al
valor devuelto.
Para decirlo de otra manera:
Si el tipo que est tratando de recuperar no es opcional, se convertir opcional
debido al encadenamiento opcional.
Si el tipo que est tratando de recuperar es ya opcional, no se convertir
en ms opcional debido al encadenamiento.
Por lo tanto:
Si intenta recuperar un Int valor a travs de encadenamiento opcional,
un int? siempre se devuelve, no importa cmo se utilizan muchos niveles de
encadenamiento.
Del mismo modo, si usted trata de recuperar un Int? valor a travs de
encadenamiento opcional, unint? siempre se devuelve, no importa cmo se
utilizan muchos niveles de encadenamiento.
El siguiente ejemplo intenta acceder a la calle de la propiedad de la direccin
de la propiedad de laresidencia propiedad de john . Hay dos niveles de
encadenamiento opcional en uso aqu, a travs de la cadena de los de
residencia y direccin de las propiedades, las cuales son de tipo opcional:

if let johnsStreet = john.residence?.address?.street {

println("John's street name is \(johnsStreet).")

} else {

println("Unable to retrieve the address.")

// imprime "No se puede recuperar la direccin."


El valor de john.residence actualmente contiene una
vlida Residencia instancia. Sin embargo, el valor
dejohn.residence.address es actualmente nula . Debido a esto, la llamada
a john.residence? .Address? .streetfalla.

211

Tenga en cuenta que en el ejemplo anterior, usted est tratando de recuperar el valor de
la calle de la propiedad. El tipo de esta propiedad es de cuerda? . El valor de
retorno de john.residence? .Address? .streetes, por tanto, tambin de
cuerda? , a pesar de que dos niveles de encadenamiento opcional se aplican adems
del tipo opcional subyacente de la propiedad.
Si establece un real Direccin instancia como valor
para john.residence.address , y establecer un valor real para los de la
direccin de la calle propiedad, se puede acceder al valor de la calle de la
propiedad a travs de encadenamiento opcional multinivel:

let johnsAddress = Address()

johnsAddress.buildingName = "The Larches"

johnsAddress.street = "Laurel Street"

john.residence!.address = johnsAddress

if let johnsStreet = john.residence?.address?.street {

println("John's street name is \(johnsStreet).")

} else {

println("Unable to retrieve the address.")

// Impresiones "nombre de la calle de Juan es la calle


Laurel."
Tenga en cuenta el uso de un signo de exclamacin en la asignacin de una instancia de
direccin ajohn.residence.address . El john.residence propiedad tiene
un tipo opcional, y por lo que necesita para desenvolver su valor real con un signo de
exclamacin antes de acceder a la residencia de direccin de propiedad.
Encadenar sobre Mtodos de Valores de retorno opcionales
El ejemplo anterior muestra cmo recuperar el valor de una propiedad de tipo opcional
mediante el encadenamiento opcional. Tambin puede utilizar el encadenamiento
opcional para llamar a un mtodo que devuelve un valor de tipo opcional, y para la
cadena de valor de retorno de dicho mtodo, si es necesario.
El ejemplo siguiente llama a la Direccin de la
clase buildingIdentifier mtodo a travs del encadenamiento opcional. Este
mtodo devuelve un valor del tipo de cuerda? . Como se describi anteriormente, el
tipo de retorno final de este mtodo de llamada despus de encadenamiento es tambin
opcional Cadena? :

if let buildingIdentifier = john.residence?.address?.buildingIdentifier() {

println("John's building identifier is \(buildingIdentifier).")

// Impresiones "identificador edificio de Juan es Los


Alerces."

212

Si desea realizar ms de encadenamiento opcional en el valor devuelto por este mtodo,


coloque el signo de interrogacin de encadenamiento opcional despus parntesis del
mtodo:

if let beginsWithThe =

john.residence?.address?.buildingIdentifier()?.hasPrefix("The") {

if beginsWithThe {

println("John's building identifier begins with \"The\".")

} else {

println("John's building identifier does not begin with \"The\".")

// Impresiones "identificador edificio de Juan comienza


con" El "."
NOTA
En el ejemplo anterior, se coloca el signo de interrogacin de encadenamiento
opcional despus de los parntesis, ya que el valor opcional est encadenando en es
el buildingIdentifier valor de retorno del mtodo, y no
el buildingIdentifier mtodo en s.

Tipo de casting
Tipo de casting es una manera de comprobar el tipo de un ejemplo, y / o para tratar esa
instancia como si es una superclase o subclase diferente de algn otro lugar en su propia
jerarqua de clases.
Tipo de calidad en Swift se implementa con el is y as operadores. Estos dos
operadores proporcionan una forma simple y expresiva para comprobar el tipo de un
valor o convertir un valor a un tipo diferente.
Tambin puede utilizar la conversin de tipos para comprobar si un tipo es conforme a
un protocolo, como se describe en Comprobacin de Protocolo de Conformidad .
Definir una jerarqua de las clases para la conversin de tipos
Usted puede utilizar la conversin de tipos con una jerarqua de clases y subclases para
comprobar el tipo de una instancia de clase en particular y emita esa instancia a otra
clase dentro de la misma jerarqua. Los tres fragmentos de cdigo siguientes definen
una jerarqua de clases y una matriz que contiene las instancias de esas clases, para su
uso en un ejemplo de la conversin de tipos.
El primer fragmento de cdigo define una nueva clase base llamada MediaItem . Esta
clase proporciona la funcionalidad bsica para cualquier tipo de elemento que aparece
en una biblioteca de medios digitales. En concreto, se declara un nombre
de propiedad de tipo Cadena , y un nombre de inicio de inicializacin. (Se
supone que todos los elementos multimedia, incluyendo todas las pelculas y canciones,
tendrn un nombre.)

213

class MediaItem {

var name: String

init(name: String) {

self.name = name

}
El siguiente fragmento de cdigo define dos subclases de MediaItem . La primera
subclase, Pelcula , encapsula informacin adicional acerca de una pelcula o una
pelcula. Se aade un director propiedad en la parte superior de la
base MediaItem clase, con un inicializador correspondiente. La segunda
subclase, Cancin, aade un artista propiedad y inicializador en la parte superior
de la clase base:

class Movie: MediaItem {

var director: String

init(name: String, director: String) {

self.director = director

super.init(name: name)

class Song: MediaItem {

var artist: String

init(name: String, artist: String) {

self.artist = artist

super.init(name: name)

}
El fragmento final, crea una matriz constante llamada biblioteca , que contiene
dos pelculas instancias y tres canciones casos. El tipo de
la biblioteca matriz se infiere por la inicializacin con el contenido de un literal de
matriz. Tipo ortogrfico de Swift es capaz de deducir que la pelcula y la
cancin tiene una superclase comn de MediaItem , y por lo que infiere un tipo
de [MediaItem] para la biblioteca de matriz:

let library = [

Movie(name: "Casablanca", director: "Michael Curtiz"),

Song(name: "Blue Suede Shoes", artist: "Elvis Presley"),

Movie(name: "Citizen Kane", director: "Orson Welles"),

Song(name: "The One And Only", artist: "Chesney Hawkes"),


214

Song(name: "Never Gonna Give You Up", artist: "Rick Astley")

// Del tipo de "biblioteca" se infiere que [MediaItem]


Los elementos almacenados en la biblioteca son
todava Pelcula y Cancin casos detrs de las escenas.Sin embargo, si usted iterar
sobre el contenido de esta matriz, los elementos que reciba de vuelta se escriben
como MediaItem , y no como la pelcula o cancin . Con el fin de trabajar
con ellos como su tipo nativo, es necesario comprobar su tipo, o abatido a un tipo
diferente, tal como se describe a continuacin.
Comprobacin Tipo
Utilice el operador de control de tipo ( es ) para comprobar si una instancia es de un
cierto tipo de subclase. El operador de verificacin tipo devuelve verdadero si la
instancia es de ese tipo de subclase y falsa si no lo es.
El siguiente ejemplo define dos variables, movieCount y songCount , que cuentan
el nmero de pelculas y de canciones casos en la biblioteca de matriz:

var movieCount = 0

var songCount = 0

for item in library {

if item is Movie {

++movieCount

} else if item is Song {

++songCount

println("Media library contains \(movieCount) movies and \(songCount) songs")

// Impresiones "Mediateca contiene 2 pelculas y 3


canciones"
Este ejemplo recorre en iteracin todos los elementos de la biblioteca
de matriz. En cada paso, el para - enbucle establece el elemento constante a la
siguiente MediaItem en la matriz.
Articulo Movie devuelve verdadero si la corriente MediaItem es
una pelcula instancia y falsa si no lo es. Del mismo modo, el artculo es
Cancin comprueba si el elemento es una cancin instancia. Al final de la para en bucle, los valores de movieCount y songCount contienen una cuenta de
cuntas MediaItem se encontraron casos de cada tipo.
Downcasting
Una constante o variable de un cierto tipo de clase pueden referirse en realidad a una
instancia de una subclase detrs de las escenas. Dnde crees que este es el caso, usted

215

puede tratar de abatido al tipo subclase con el operador de conversin de


tipos ( como ).
Debido downcasting puede fallar, el operador de conversin de tipos se presenta en dos
formas diferentes.La forma opcional, como? , devuelve un valor opcional del tipo que
est intentando abatido a. La forma forzada, como , intenta los abatidos y fuerza
desenvuelve el resultado como una sola accin compuesto.
Utilice el formulario opcional del operador tipo elenco ( como? ) cuando no est seguro
de si el abatido tendr xito. Esta forma de la operadora siempre devolver un valor
opcional, y el valor ser nulo si el abatido no era posible. Esto le permite comprobar
de un abatido xito.
Utilice la forma forzosa del operador tipo elenco ( como ) slo cuando est seguro de
que el abatido siempre tendr xito. Esta forma de operador activar un error de
ejecucin si se intenta abatido a un tipo de clase incorrecta.
El siguiente ejemplo itera sobre cada MediaItem en la biblioteca , e imprime
una descripcin apropiada para cada elemento. Para ello, es necesario acceder a cada
elemento como una verdadera pelcula o cancin , y no slo como
un MediaItem . Esto es necesario a fin de que sea capaz de acceder
al director o artistapropiedad de una pelcula o cancin para uso en la
descripcin.
En este ejemplo, cada elemento de la matriz puede ser una pelcula , o podra ser
una cancin . Usted no sabe de antemano qu clase real a utilizar para cada elemento,
y por lo que es adecuado utilizar el formulario opcional del operador de conversin de
tipos ( como? para comprobar los abatidos cada vez en el bucle):

for item in library {

if let movie = item as? Movie {

println("Movie: '\(movie.name)', dir. \(movie.director)")

} else if let song = item as? Song {

println("Song: '\(song.name)', by \(song.artist)")

// Pelcula: 'Casablanca', dir. Michael Curtiz

// Song: "Blue Suede Shoes", de Elvis Presley

// Pelcula: 'Ciudadano Kane', dir. Orson Welles

// Cancin: 'El One And Only', por Chesney Hawkes

// Cancin: 'Nunca Gonna Give You Up', de Rick Astley


El ejemplo empieza por intentar abatido el actual artculo como la
pelcula . Debido a que el punto es unMediaItem ejemplo, es posible
que podra ser una pelcula ; igualmente, tambin es posible que podra ser
una cancin , o incluso slo una base MediaItem . Debido a esta incertidumbre,
el como? forma del operador de conversin de tipo devuelve un opcional valor al
intentar abatido a un tipo de subclase. El resultado de lapartida como
pelcula es del tipo de pelculas? , o "opcional Movie ".

216

Downcasting a Movie falla cuando se aplica a las dos canciones instancias del array
biblioteca. Para hacer frente a esto, el ejemplo anterior utiliza opcional de unin para
comprobar si la opcin Movie realidad contiene un valor (es decir, para saber si los
abatidos sucedi.) Esta unin se escribe "opcional artculo si dejar que la
pelcula = as? Pelcula ", que se puede leer como:
"Trate de acceder tema como Pelcula . Si esto tiene xito, establecer una nueva
constante temporal denominada pelcula con el valor almacenado en la opcin de
regresar Movie ".
Si el downcasting tiene xito, las propiedades de la pelcula se utilizan para
imprimir una descripcin de eseMovie ejemplo, incluyendo el nombre de
su director . Un principio similar se utiliza para comprobar si haycancin de los
casos, y para imprimir una descripcin apropiada (incluyendo artista nombre)
siempre que una cancin se encuentra en la biblioteca.
NOTA
Fundicin en realidad no modificar la instancia o cambiar sus valores. La instancia
subyacente sigue siendo el mismo; simplemente se trata y se accede como una instancia
del tipo al que se ha fundido.
Escriba Casting para Todas y AnyObject
Swift proporciona dos alias de tipo especial para trabajar con tipos no especficos:
AnyObject puede representar una instancia de cualquier tipo de clase.
Cualquier puede representar una instancia de cualquier tipo en absoluto, aparte
de los tipos de funcin.
NOTA
Utilice Cualquier y AnyObject slo cuando se necesita explcitamente el
comportamiento y las capacidades que proporcionan. Siempre es mejor ser especfico
acerca de los tipos que se pueden esperar para trabajar con en el cdigo.
AnyObject
Al trabajar con las API de cacao, es comn recibir una matriz con un tipo
de [AnyObject] , o "una matriz de valores de cualquier tipo de objeto". Esto se debe
a Objective-C no tiene matrices con tipo de forma explcita.Sin embargo, a menudo se
puede estar seguro sobre el tipo de los objetos contenidos en una gama tan slo de la
informacin que tiene sobre la API que proporciona la matriz.
En estas situaciones, puede utilizar la versin forzada del operador de conversin de
tipos ( como ) al abatido cada elemento de la matriz a un tipo de clase ms especfica
que AnyObject , sin la necesidad de desenvolver opcional.
El ejemplo siguiente define una matriz de tipo [AnyObject] y rellena esta matriz con
tres instancias de lapelcula de clase:

let someObjects: [AnyObject] = [

Movie(name: "2001: A Space Odyssey", director: "Stanley Kubrick"),

Movie(name: "Moon", director: "Duncan Jones"),

Movie(name: "Alien", director: "Ridley Scott")

]
Debido a que esta variedad se sabe que contiene slo la pelcula de los casos,
usted puede abatido y desenvolver directamente a un no opcional Pelcula con la
versin forzada del operador de conversin de tipos ( como ):

217

for object in someObjects {

let movie = object as Movie

println("Movie: '\(movie.name)', dir. \(movie.director)")

// Pelcula: "2001: Una odisea del espacio ', dir. Stanley


Kubrick

// Pelcula: 'Luna', dir. Duncan Jones

// Pelcula: 'Alien', dir. Ridley Scott


Para una forma an ms breve de este bucle, abatido el someObjects matriz a un tipo
de [Vdeo] en lugar de downcasting cada elemento:

for movie in someObjects as [Movie] {

println("Movie: '\(movie.name)', dir. \(movie.director)")

// Pelcula: "2001: Una odisea del espacio ', dir. Stanley


Kubrick

// Pelcula: 'Luna', dir. Duncan Jones

// Pelcula: 'Alien', dir. Ridley Scott



Cualquier (Any)
He aqu un ejemplo del uso de Cualquier trabajar con una mezcla de diferentes tipos,
incluyendo los tipos no-clase. El ejemplo crea una matriz denominada cosas , que
puede almacenar valores de tipo Cualquier :

var things = [Any]()

things.append(0)

things.append(0.0)

things.append(42)

things.append(3.14159)

things.append("hello")

things.append((3.0, 5.0))

things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman"))


La things matriz contiene dos Int valores, dos dobles valores, una Cadena de
valor, una tupla de tipo (Doble, doble) , y la pelcula "Los Cazafantasmas",
dirigida por Ivan Reitman.
Puede utilizar los is y as operadores en un switch de casos de declaracin para
descubrir el tipo especfico de una constante o variable que slo es conocida como de
tipo Any o AnyObject . El siguiente ejemplo itera sobre los elementos de
la things array y consulta el tipo de cada elemento con un switch

218

comunicado. Varios de los switch de los casos de declaracin de unir su valor


coincidente con una constante del tipo especificado para permitir su valor a imprimir:

for thing in things {

switch thing {

case 0 as Int:

println("zero as an Int")

case 0 as Double:

println("zero as a Double")

case let someInt as Int:

println("an integer value of \(someInt)")

case let someDouble as Double where someDouble > 0:

println("a positive double value of \(someDouble)")

case is Double:

println("some other double value that I don't want to print")

case let someString as String:

println("a string value of \"\(someString)\"")

case let (x, y) as (Double, Double):

println("an (x, y) point at \(x), \(y)")

case let movie as Movie:

println("a movie called '\(movie.name)', dir. \(movie.director)")

default:

println("something else")

// Cero como Int

// Cero como un doble

// Un valor entero de 42

// Un doble valor positivo de 3.14159

// Un valor de cadena de "hola"

// Una (x, y) en el punto 3.0, 5.0

// Una pelcula llamada 'Ghostbusters', dir. Ivan Reitman


NOTA
Los casos de un interruptor de uso Declaracin de la versin forzada del
operador de conversin de tipos (como , no como? ) para comprobar y fundido a un
tipo especfico. Esta comprobacin es siempre seguro dentro del contexto de
un interruptor de declaracin de caso.

219

Tipos anidados
Las enumeraciones son creadas a menudo para apoyar a una clase especfica o la
funcionalidad de la estructura. Del mismo modo, puede ser conveniente definir clases y
estructuras de utilidad puramente para su uso en el contexto de un tipo ms
complejo. Para lograr esto, Swift le permite definir tipos anidados , por el que usted
nido apoyar las enumeraciones, las clases y las estructuras dentro de la definicin del
tipo que soportan.
Para anidar un tipo dentro de otro tipo, escribir su definicin dentro de las llaves
externas del tipo que soporta.Los tipos pueden ser anidados a tantos niveles como son
obligatorios.
Tipos anidados en Accin
El ejemplo siguiente define una estructura llamada BlackjackCard , que modela una
tarjeta de juego tal como se utiliza en el juego de Blackjack. El BlackJack estructura
contiene dos tipos de enumeracin anidados llamados Traje y Rango .
En el Blackjack, las cartas Ace tienen un valor de uno u once. Esta caracterstica est
representada por una estructura llamada Valores , que est anidado dentro
del rango de enumeracin:

struct BlackjackCard {

// Enumeracin Traje anidada

enum Suit: Character {

case Spades = "", Hearts = "", Diamonds = "", Clubs = ""

// Anidada Rango enumeracin

enum Rank: Int {

case Two = 2, Three, Four, Five, Six, Seven, Eight, Nine, Ten

case Jack, Queen, King, Ace

struct Values {

let first: Int, second: Int?

var values: Values {

switch self {

case .Ace:

return Values(first: 1, second: 11)

case .Jack, .Queen, .King:

return Values(first: 10, second: nil)

default:

return Values(first: self.toRaw(), second: nil)


220

// BlackjackCard propiedades y mtodos

let rank: Rank, suit: Suit

var description: String {

var output = "suit is \(suit.toRaw()),"

output += " value is \(rank.values.first)"

if let second = rank.values.second {

output += " or \(second)"

return output

}
El suit enumeracin describe los cuatro juegos de la tarjeta de juego comunes, junto
con una prima de caracteres valor para representar a su smbolo.
El rango de enumeracin describe las trece posibles filas de tarjetas de juego, junto
con una prima Int valor para representar a su valor nominal. (Esta prima Int valor no
se utiliza para la Jota, Reina, Rey y As de tarjetas.)
Como se mencion anteriormente, el rango de enumeracin define una estructura
anidada adicional de sus propios, llamados valores . Esta estructura encapsula el
hecho de que la mayora de las tarjetas tienen un valor, pero la tarjeta Ace tiene dos
valores. El Valores estructura define dos propiedades para representar esto:
primero , de tipo Int
segundo , de tipo Int? , o "opcional Int "
Rango tambin define una propiedad calculada, valores , que devuelve una
instancia de la Valores estructura.Esta propiedad computarizada considera el rango
de la tarjeta y se inicializa un nuevo Valores instancia con los valores adecuados en
funcin de su rango. Utiliza valores especiales para Jack , Reina , Rey y As . Para
las tarjetas numricas, utiliza prima del rango Int valor.
El BlackjackCard estructura en s tiene dos propiedades- rango y suit. Tambin
define una propiedad calculada denominada descripcin , que utiliza los valores
almacenados en rango y suit para construir una descripcin del nombre y el valor
de la tarjeta. La descripcin de propiedad utiliza opcional vinculante para
comprobar si hay un segundo valor a mostrar, y si es as, inserta descripcin adicional
detallada para ese segundo valor.
Debido BlackjackCard es una estructura sin inicializadores personalizados, tiene un
inicializador implcito miembro por miembro, como se describe en miembro por
miembro Inicializadores de Estructura Tipos . Usted puede utilizar este inicializador
para inicializar una nueva constante llamados theAceOfSpades :

221

let theAceOfSpades = BlackjackCard(rank: .Ace, suit: .Spades)

println("theAceOfSpades: \(theAceOfSpades.description)")

// imprime "theAceOfSpades: traje est , el valor es 1 o 11"


A pesar de Rango y Suit se anidan dentro BlackjackCard , su tipo se puede
inferir a partir del contexto, por lo que la inicializacin de esta instancia es capaz de
referirse a los miembros de la enumeracin de sus nombres de los miembros
( .ace y .Spades ) solos. En el ejemplo anterior, la descripcin de la
propiedad informa correctamente que el as de espadas tiene un valor de 1 o 11 .
En referencia a los tipos anidados
Para utilizar un tipo anidado fuera de su contexto definicin, preceda su nombre con el
nombre del tipo que est anidado dentro:

let heartsSymbol = BlackjackCard.Suit.Hearts.toRaw()

// HeartsSymbol es ""
Para el ejemplo anterior, esto permite que los nombres
de Traje , Rango y valores que se mantiene deliberadamente corto, porque sus
nombres son, naturalmente, calificados por el contexto en el que se definen.

Extensiones
Extensiones de aadir nueva funcionalidad a una clase, estructura o tipo de enumeracin
existente. Esto incluye la capacidad de ampliar los tipos para los que no tiene acceso al
cdigo fuente original (conocido como el modelado retroactiva ). Las extensiones son
similares a categoras en Objective-C. (A diferencia de las categoras de Objective-C,
extensiones Swift no tienen nombres.)
Extensiones en Swift puede:
Agregar propiedades calculadas y propiedades estticas calculadas
Definir los mtodos de instancia y mtodos de tipo
Proporcionar nuevos inicializadores
Definir subndices
Definir y utilizar nuevos tipos anidados
Haz un tipo existente se ajusta a un protocolo
NOTA
Las extensiones pueden aadir nuevas funcionalidades a un tipo, pero no pueden
reemplazar la funcionalidad existente.
Sintaxis Extensin
Declarar extensiones con la extensin de la palabra clave:

extension SomeType {

// Nueva funcionalidad para aadir a SomeType va aqu

}
Una extensin puede extender un tipo existente para que adopte uno o ms
protocolos. Cuando este es el caso, los nombres de protocolo se escriben exactamente
de la misma manera que para una clase o estructura:

extension SomeType: SomeProtocol, AnotherProtocol {


222

// Implementacin de los requisitos del protocolo va aqu

}
Adicin de conformidad protocolo de esta manera se describe en Aadiendo Protocolo
de Conformidad con una extensin .
NOTA
Si se define una extensin para agregar nueva funcionalidad a un tipo existente, la
nueva funcionalidad estar disponible en todas las instancias existentes de ese tipo,
incluso si se hubieran creado antes se defini la extensin.
Propiedades calculadas
Las extensiones pueden aadir propiedades de instancia calculados y propiedades de
tipo calculados a los tipos existentes. Este ejemplo aade cinco propiedades de la
instancia computarizada para incorporado de Swift doble tipo, para proporcionar
soporte bsico para trabajar con unidades de distancia:

extension Double {

var km: Double { return self * 1_000.0 }

var m: Double { return self }

var cm: Double { return self / 100.0 }

var mm: Double { return self / 1_000.0 }

var ft: Double { return self / 3.28084 }

let oneInch = 25.4.mm

println("One inch is \(oneInch) meters")

// Impresiones "Una pulgada es 0.0254 metros"

let threeFeet = 3.ft

println("Three feet is \(threeFeet) meters")

// grabados "Tres pies es ,914399970739201 metros"


Estas propiedades calculadas que expresan un doble valor debe ser considerado como
una cierta unidad de longitud. A pesar de que se implementan como propiedades
calculadas, los nombres de estas propiedades se pueden adjuntar a un valor literal de
coma flotante con la sintaxis con punto, como una manera de utilizar ese valor literal
para realizar las conversiones de distancia.
En este ejemplo, un doble valor de 1,0 se considera que representa ", uno
meter". Esta es la razn por la mpropiedad calculada vuelve auto expresin -el 1.m se
considera para calcular un doble valor de 1.0 .
Otras unidades requieren alguna conversin para ser expresado como un valor medido
en metros. Un kilmetro es el mismo que 1.000 metros, por lo que el km propiedad
calculado multiplica el valor por 1_000.00para convertir en un nmero expresado en
metros. Del mismo modo, hay 3,28024 pies de un metro, y as elft propiedad
computarizada divide el subyacente doble valor por 3.28024 , para convertirlo de
pies a metros.

223

Estas propiedades se calcula las propiedades de slo lectura, por lo que se expresan sin
el get palabra clave, por razones de brevedad. Su valor de retorno es de tipo doble , y
se puede utilizar en clculos matemticos, cuando ese doble se acepta:

let aMarathon = 42.km + 195.m

println("A marathon is \(aMarathon) meters long")

// imprime "Un maratn es 42,195.0 metros de largo"


NOTA
Las extensiones pueden aadir nuevas propiedades calculadas, pero no pueden agregar
propiedades almacenadas, o aadir observadores de propiedad de las propiedades
existentes.
Inicializadores
Las extensiones pueden aadir nuevos inicializadores de los tipos existentes. Esto le
permite ampliar a otros tipos de aceptar sus propios tipos personalizados como
parmetros inicializadores, o para proporcionar opciones de inicializacin adicionales
que no se incluyeron como parte de la implementacin original del tipo.
Las extensiones pueden aadir nuevos inicializadores de conveniencia a una clase, pero
no pueden agregar inicializadores o deinitializers nuevos designados a una
clase. Inicializadores y deinitializers designados siempre deben ser proporcionados por
la implementacin original de la clase.
NOTA
Si utiliza una extensin para aadir un inicializador para un tipo de valor que
proporciona valores predeterminados para todas las propiedades guardadas y no define
ningn inicializadores personalizados, puede llamar al inicializador por defecto y
inicializador miembro por miembro para ese tipo de valor dentro de inicializador de su
extensin.
Este no sera el caso si hubiera escrito el inicializador como parte de la implementacin
original del tipo de valor, como se describe en Inicializador Delegacin para tipos de
valor .
El ejemplo siguiente define una costumbre Rect estructura para representar un
rectngulo geomtrico. El ejemplo tambin define dos estructuras de apoyo
llamada Tamao y Point , los cuales proporcionan valores por defecto de 0,0 para
todas sus propiedades:

struct Size {

var width = 0.0, height = 0.0

struct Point {

var x = 0.0, y = 0.0

struct Rect {

var origin = Point()

var size = Size()

224

Debido a que el Rect estructura proporciona valores predeterminados para todas sus
propiedades, que recibe un inicializador por defecto y un inicializador de miembro por
miembro automticamente, como se describe enInicializadores predeterminados . Estos
inicializadores pueden ser utilizados para crear nuevas Rect casos:

let defaultRect = Rect()

let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0),

size: Size(width: 5.0, height: 5.0))


Puede ampliar la Rect estructura para proporcionar un inicializador adicional que toma
un punto central especfico y tamao:

extension Rect {

init(center: Point, size: Size) {

let originX = center.x - (size.width / 2)

let originY = center.y - (size.height / 2)

self.init(origin: Point(x: originX, y: originY), size: size)

}
Este nuevo inicializador comienza calculando un punto de origen adecuado en funcin
de la proporcionadacentro punto y tamao valor. El inicializador luego llama de la
estructura automtica inicializador miembro por miembro init (origen: tamao
:) , que almacena los nuevos valores de origen y tamao en las propiedades adecuadas:

let centerRect = Rect(center: Point(x: 4.0, y: 4.0),

size: Size(width: 3.0, height: 3.0))

// Origen de centerRect es (2.5, 2.5) y su tamao es (3.0,


3.0)
NOTA
Si usted proporciona un nuevo inicializador con una extensin, usted sigue siendo
responsable de asegurarse de que cada instancia se inicializa totalmente una vez que el
inicializador completa.
Mtodos
Las extensiones pueden aadir nuevos mtodos de instancia y mtodos de tipo de los
tipos existentes. El ejemplo siguiente aade un nuevo mtodo de instancia
denominado repeticiones a la Int tipo:

extension Int {

func repetitions(task: () -> ()) {

for i in 0..<self {

task()

225

El repeticiones mtodo toma un nico argumento de tipo () -> () , lo que


indica una funcin que no tiene parmetros y no devuelve un valor.
Despus de definir esta extensin, puede llamar al repeticiones mtodo en
cualquier nmero entero para realizar una tarea que muchas veces:

3.repetitions({

println("Hello!")

})

// Hola!

// Hola!

// Hola!
Utilice arrastrando sintaxis de cierre para realizar la llamada ms sucinta:

3.repetitions {

println("Goodbye!")

// Adis!

// Adis!

// Adis!

Mutando Mtodos de instancia
Los mtodos de instancia aaden con una extensin tambin se puede modificar
(o mutar ) la propia instancia. Estructura y mtodos de enumeracin que modifican uno
mismo o sus propiedades deben marcar el mtodo de instancia como la mutacin ,
al igual que la mutacin de los mtodos de una implementacin original.
El ejemplo siguiente aade un nuevo mtodo mutante llamada plaza de
Swift Int tipo, que las plazas del valor original:

extension Int {

mutating func square() {

self = self * self

var someInt = 3

someInt.square()

// SomeInt es ahora 9


Los subndices
Las extensiones pueden aadir nuevos subndices para un tipo existente. En este
ejemplo se agrega un subndice entero a built-in de Swift Int tipo. Este
subndice [n] devuelve los dgitos decimales n en lugares de la derecha del nmero:
123456789 [0] devuelve 9
123456789 [1] devuelve 8

226

... Etctera:

extension Int {

subscript(var digitIndex: Int) -> Int {

var decimalBase = 1

while digitIndex > 0 {

decimalBase *= 10

--digitIndex

return (self / decimalBase) % 10

746381295[0]

// returns 5

746381295[1]

// returns 9

746381295[2]

// returns 2

746381295[8]

// returns 7
Si el Int valor no tiene suficientes dgitos para el ndice solicitado, la aplicacin
devuelve el subndice 0 , como si el nmero haba sido rellenado con ceros a la
izquierda:

746381295 [ 9 ]

// devuelve 0, que si hubiera solicitado:

0746381295 [ 9 ]

Tipos anidados
Las extensiones pueden aadir nuevos tipos anidados a clases, estructuras y
enumeraciones existentes:

extension Int {

enum Kind {

case Negative, Zero, Positive

var kind: Kind {

switch self {

case 0:

return .Zero

227

case let x where x > 0:

return .Positive

default:

return .Negative

}
En este ejemplo se agrega una nueva enumeracin anidada a Int . Esta enumeracin,
llamado Kind , expresa el tipo de nmero que un nmero entero particular
representa. Especficamente, expresa si el nmero es negativo, cero o positivo.
Este ejemplo tambin aade una nueva propiedad calculada instancia para Int ,
llamado tipo , que devuelve el apropiado Kind miembro de la enumeracin de ese
entero.
La enumeracin anidada ahora se puede utilizar con cualquier Int valor:

func printIntegerKinds(numbers: [Int]) {

for number in numbers {

switch number.kind {

case .Negative:

print("- ")

case .Zero:

print("0 ")

case .Positive:

print("+ ")

print("\n")

printIntegerKinds([3, 19, -27, 0, -6, 0, 7])

// Impresiones "+ + - 0 - 0 +"


Esta funcin, printIntegerKinds , toma una matriz de entrada de Int valores y
itera sobre esos valores, a su vez. Para cada nmero entero en la matriz, la funcin
considera el tipo calculado propiedad por ese nmero entero, e imprime una
descripcin apropiada.
NOTA
number.kind ya se sabe que es de tipo Int.Kind . Debido a esto, todos
los Int.Kind valores de los miembros se puede escribir en forma abreviada en el
interior del interruptor de la declaracin, como negativa es ms
que Int.Kind.Negative .

228

Protocolos
Un protocolo define un plano de los mtodos, propiedades y otros requisitos que se
adapten a una tarea o un pedazo de funcionalidad particular. El protocolo no
proporciona realmente una implementacin de cualquiera de estos requisitos, que slo
describe lo que una aplicacin se ver as. El protocolo puede ser adoptado por una
clase, estructura o enumeracin para proporcionar una implementacin real de esos
requisitos. Cualquier tipo que satisfaga los requisitos de un protocolo se dice
que conforme a dicho protocolo.
Los protocolos pueden requerir que se ajusten tipos tienen propiedades especficas
ejemplo, los mtodos ejemplo, los mtodos de tipo, operadores y subndices.
Sintaxis Protocolo
Usted define los protocolos de una manera muy similar a las clases, estructuras y
enumeraciones:

protocol SomeProtocol {

// protocol definition goes here

}
Tipos personalizados afirman que adopten un protocolo particular poniendo el nombre
del protocolo despus del nombre del tipo, separados por dos puntos, como parte de su
definicin. Protocolos pueden aparecer mltiples, y estn separadas por comas:

struct SomeStructure: FirstProtocol, AnotherProtocol {

// Estructura de definicin va aqu

}
Si una clase tiene una superclase, anote el nombre de la superclase antes de cualquier
protocolo de que adopte, seguido de una coma:

class SomeClass: SomeSuperclass, FirstProtocol, AnotherProtocol {

AnotherProtocol {

// Definicin de clase va aqu

}
Requisitos de Propiedad
Un protocolo puede requerir cualquier tipo conforme a proporcionar una propiedad de
instancia o tipo de propiedad con un nombre y un tipo particular. El protocolo no
especifica si la propiedad debe ser una propiedad almacenado o una computadopropiedad slo especifica el nombre de la propiedad requerida y el tipo. El protocolo
tambin especifica si cada propiedad debe ser gettable o gettable y ajustable.
Si un protocolo requiere una propiedad de ser obtenibles y configurable, que el requisito
de propiedad no puede ser satisfecha por una propiedad almacenada constante o una
propiedad calculada de slo lectura. Si el protocolo slo requiere de una propiedad para
ser gettable, el requisito puede cumplirse mediante cualquier tipo de propiedad, y es
vlida para la propiedad de ser tambin ajustable si esto es til para su propio cdigo.
Requisitos de propiedad siempre se declaran como propiedades de las variables, el
prefijo de la var palabra clave. Propiedades getTable y ajustables se indican por

229

escrito {get set} despus de su declaracin de tipo, y las propiedades getTable se


indican por escrito {get} .

protocol SomeProtocol {

var mustBeSettable: Int { get set }

var doesNotNeedToBeSettable: Int { get }

}
Siempre requisitos de propiedades de tipo prefijo con la clase de palabras clave
cuando se defina en un protocolo. Esta norma se refiere a pesar de que los requisitos de
propiedades de tipo van precedidos de laesttica palabra clave cuando se
implementa una estructura o enumeracin:

protocol AnotherProtocol {

class var someTypeProperty: Int { get set }

}
He aqu un ejemplo de un protocolo con un solo requisito de propiedad de instancia:

protocol FullyNamed {

var fullName: String { get }

}
El FullyNamed protocolo requiere un tipo de conformacin para proporcionar un
nombre totalmente calificado.El protocolo no especifica nada acerca de la naturaleza del
tipo de conformacin-slo especifica que el tipo debe ser capaz de proporcionar el
nombre completo por s mismo. El protocolo establece que cualquierFullyNamed tipo
debe tener una propiedad de instancia denominada gettable fullName , que es del
tipo de cuerda .
He aqu un ejemplo de una estructura simple que adopta y se ajusta a
la FullyNamed protocolo:

struct Person: FullyNamed {

var fullName: String

let john = Person(fullName: "John Appleseed")

// John.fullName es "John Appleseed"


Este ejemplo define una estructura llamada persona , lo que representa una persona
llamada especfica. Se afirma que adopta la FullyNamed protocolo como parte de la
primera lnea de su definicin.
Cada instancia de persona tiene una sola propiedad almacenado
llamado fullName , que es del tipo de cuerda .Esto coincide con el nico requisito
de la FullyNamed protocolo, y significa que la persona ha cumplido
correctamente con el protocolo. (Swift informa de un error en tiempo de compilacin si
un requisito de protocolo no se ha cumplido.)
Aqu hay una clase ms compleja, que tambin adopta y se ajusta a
la FullyNamed protocolo:

class Starship: FullyNamed {


230

var prefix: String?

var name: String

init(name: String, prefix: String? = nil) {

self.name = name

self.prefix = prefix

var fullName: String {

return (prefix != nil ? prefix! + " " : "") + name

var ncc1701 = Starship(name: "Enterprise", prefix: "USS")

// Ncc1701.fullName es "USS Enterprise"


Esta clase implementa la fullName requisito de propiedad como de slo lectura
computarizada-propiedad de una nave espacial. Cada Starship instancia de clase
almacena una obligatoria nombre y un opcional de
prefijo . El fullName propiedad utiliza el prefijo de valor si existe, y
antepone al comienzo de nombre para crear un nombre completo de la nave.
Requisitos del mtodo
Protocolos especficos pueden requerir mtodos de instancia y mtodos de tipos que
llevar a cabo conforme tipos. Estos mtodos estn escritos como parte de la definicin
del protocolo de la misma forma que para los mtodos de instancia y de tipo normales,
pero sin llaves o un cuerpo de mtodo. Parmetros variadic estn permitidos, sujetos a
las mismas reglas que para los mtodos normales.
NOTA
Protocolos utilizan la misma sintaxis que los mtodos normales, pero no se les permite
especificar valores predeterminados para los parmetros del mtodo.
Al igual que con los requisitos de propiedades de tipo, siempre se anteponga requisitos
del mtodo de tipo con la clase de palabras clave cuando se definen en un
protocolo. Esto es cierto a pesar de que los requisitos del mtodo de tipo van precedidos
de la esttica palabra clave cuando se implementa una estructura o enumeracin:

protocolo SomeProtocol {

clase func someTypeMethod ()

}
El ejemplo siguiente define un protocolo con un solo requisito mtodo de instancia:

protocol SomeProtocol {

class func someTypeMethod()

}
Este protocolo, RandomNumberGenerator , requiere ningn tipo de ajuste a tener
un mtodo de instancia denominado aleatorio , que devuelve un doble valor cada
vez que se le llama. Aunque no se especifica como parte del protocolo, se supone que
este valor ser un nmero desde 0,0 hasta (pero no incluyendo) 1.0 .

231

El RandomNumberGenerator protocolo no hace ninguna suposicin sobre cmo se


va a cada nmero aleatorio generado-simplemente requiere que el generador para
proporcionar una forma estndar para generar un nuevo nmero aleatorio.
Aqu hay una implementacin de una clase que adopta y se ajusta a
la RandomNumberGenerator protocolo. Esta clase implementa un algoritmo
generador de nmeros pseudoaleatorios conocido como un generador de congruencia
lineal :

class LinearCongruentialGenerator: RandomNumberGenerator {

var lastRandom = 42.0

let m = 139968.0

let a = 3877.0

let c = 29573.0

func random() -> Double {

lastRandom = ((lastRandom * a + c) % m)

return lastRandom / m

let generator = LinearCongruentialGenerator()

println("Here's a random number: \(generator.random())")

// Impresiones "Aqu est un nmero aleatorio: 0.37464991998171"

println("And another one: \(generator.random())")

// imprime "y otro: ,729023776863283"



Requisitos del mtodo Mutating
A veces es necesario un mtodo para modificar (o mutar ) la instancia al que
pertenece. Para los mtodos de instancia sobre los tipos de valor (es decir, estructuras y
enumeraciones) se coloca el mutando palabra clave antes de un mtodo func palabra
clave para indicar que se permite que el mtodo para modificar la instancia que
pertenece y / o propiedades de esa instancia. Este proceso se describe en Modificacin
de tipos de valor desde dentro de los mtodos de instancia .
Si se define un mtodo requisito instancia del protocolo que se destina a mutar
instancias de cualquier tipo que se adopta el protocolo, marque el mtodo con
la mutacin de la palabra clave como parte de la definicin del protocolo. Esto
permite que las estructuras y enumeraciones para adoptar el protocolo y el
cumplimiento de dicho requisito mtodo.
NOTA
Si marca un mtodo requisito instancia del protocolo como la mutacin , no es
necesario escribir la mutacin de la palabra clave al escribir una implementacin de
ese mtodo para una clase. La mutacin de la palabra clave slo se utiliza por las
estructuras y enumeraciones.
El ejemplo siguiente define un protocolo llamado togglable , que define un nico
mtodo de instancia llamado requisito de palanca . Como su nombre indica,

232

la toggle mtodo est pensado para cambiar o invertir el estado de cualquier tipo de
conformacin, por lo general mediante la modificacin de una propiedad de ese tipo.
La toggle mtodo est marcado con el mutando palabra clave como parte de
la togglable definicin de protocolo, para indicar que se espera que el mtodo para
mutar el estado de una instancia conforme cuando se le llama:

protocol Togglable {

mutating func toggle()

}
Si implementa la togglable protocolo para una estructura o enumeracin, que
estructura o enumeracin pueden ajustarse al protocolo al proporcionar una
implementacin de la palanca mtodo que tambin se marca como mutando .
El ejemplo siguiente define una enumeracin denominada OnOffSwitch . Esta
enumeracin alterna entre dos estados, indicados por los casos de
enumeracin On y Off . La enumeracin de toggle aplicacin se marca
como mutante , para que coincida con la togglable requisitos de protocolo:

enum OnOffSwitch: Togglable {

case Off, On

mutating func toggle() {

switch self {

case Off:

self = On

case On:

self = Off

var lightSwitch = OnOffSwitch.Off

lightSwitch.toggle()

// LightSwitch es ahora igual a .On


Requisitos inicializador
Los protocolos pueden requerir inicializadores especficos a ser implementados por
tipos conforme. Usted escribe estos inicializadores como parte de la definicin del
protocolo de la misma manera que para los inicializadores normales, pero sin llaves o
un rgano inicializador:

protocol SomeProtocol {

init(someParameter: Int)

233

Las implementaciones de clase de Requisitos Protocolo inicializador


Puede aplicar un requisito de inicializacin de protocolo en una clase de conformacin,
ya sea como un inicializador designado o un inicializador de conveniencia. En ambos
casos, debe marcar la implementacin inicializador con la requerida modificador:

class SomeClass: SomeProtocol {

required init(someParameter: Int) {

// Aplicacin inicializador va aqu

}
El uso del required modificador garantiza que usted proporciona una
implementacin explcita o heredada del requisito de inicializacin de todas las
subclases de la clase de conformacin, de tal manera que tambin cumplen con el
protocolo.
Para obtener ms informacin sobre los inicializadores necesarios,
consulte Inicializadores obligatorios .
NOTA
No es necesario marcar las implementaciones de inicializador protocolo con
la required modificador sobre las clases que estn marcados con
el ltimo modificador, porque las clases finales no pueden ser subclases. Para ms
informacin sobre el ltimo modificador, consulte Prevencin de anulaciones .
Si una subclase sobreescribe un inicializador designado de una superclase, y tambin
implementa un requisito inicializador juego de un protocolo, marque la aplicacin
inicializador tanto con los requeridos yanular modificadores:

protocol SomeProtocol {

init()

class SomeSuperClass {

init() {

// Aplicacin inicializador va aqu

class SomeSubClass: SomeSuperClass, SomeProtocol {

// "Necesaria" de conformidad SomeProtocol; "Anular" de SomeSuperClass

required override init() {

// Aplicacin inicializador va aqu

234

Protocolos como los tipos (Protocols as Types)


Protocolos en realidad no implementan ninguna funcionalidad a s mismos. No obstante,
cualquier protocolo se crea se convertir en un tipo de pleno derecho para el uso en el
cdigo.
Debido a que es un tipo, puede utilizar un protocolo en muchos lugares donde se
permiten otros tipos, incluyendo:
Como un tipo de parmetro o tipo de retorno de una funcin, mtodo o inicializador
A medida que el tipo de una constante, una variable o propiedad
Como el tipo de elementos en una matriz, diccionario, u otro recipiente
NOTA
Debido a que los protocolos son tipos, comenzar sus nombres con una letra mayscula
(como FullyNamed yRandomNumberGenerator ) para que coincida con los
nombres de otros tipos en Swift (como int , cuerdas ydoble ).
He aqu un ejemplo de un protocolo que se utiliza como un tipo:

class Dice {

let sides: Int

let generator: RandomNumberGenerator

init(sides: Int, generator: RandomNumberGenerator) {

self.sides = sides

self.generator = generator

func roll() -> Int {

return Int(generator.random() * Double(sides)) + 1

}
En este ejemplo se define una nueva clase llamada dados , lo que representa un n sided dados para su uso en un juego de mesa. Dados los casos tienen una propiedad de
entero llamado lados , lo que representa el nmero de lados que tienen, y una
propiedad llamada generador , que proporciona un azar generador de nmeros desde
el que crear los valores dados.
El generador de la propiedad es de tipo RandomNumberGenerator . Por lo
tanto, usted puede configurarlo para que una instancia de cualquier tipo que adopta
el RandomNumberGenerator protocolo. Nada ms se requiere de la instancia que
se asigna a esta propiedad, a excepcin de que la instancia debe adoptar
elRandomNumberGenerator protocolo.
Dados tambin tiene un inicializador, para establecer su estado inicial. Este
inicializador tiene un parmetro llamado generador , que tambin es de
tipo RandomNumberGenerator . Puede pasar un valor de cualquier tipo de
conformacin en este parmetro cuando se inicializa un nuevo Dados instancia.
Dados proporciona un mtodo de instancia, rodillo , que devuelve un valor entero
entre 1 y el nmero de lados de los dados. Este mtodo llama del
generador aleatorio mtodo para crear un nuevo nmero aleatorio

235

entre 0,0 y 1,0 , y utiliza este nmero aleatorio para crear un valor tirada de los dados
dentro del rango correcto. Debido a que el generador se conoce a
adoptar RandomNumberGenerator , es la garanta de tener unazar mtodo a
llamar.
As es como el de los dados clase se puede utilizar para crear un dado de seis caras
con unLinearCongruentialGenerator instancia como su generador de
nmeros aleatorios:

var d6 = Dice(sides: 6, generator: LinearCongruentialGenerator())

for _ in 1...5 {

println("Random dice roll is \(d6.roll())")

// Tirada de dados al azar es de 3

// Tirada de dados al azar es de 5

// Tirada de dados al azar es de 4

// Tirada de dados al azar es de 5

// Tirada de dados al azar es de 4


Delegacin
Delegacin es un patrn de diseo que permite a una clase o estructura en mano fuera
(o delegado ) algunas de sus responsabilidades a una instancia de otro tipo. Este patrn
de diseo se implementa mediante la definicin de un protocolo que encapsula las
responsabilidades delegadas, de tal manera que un tipo de conformacin (conocida
como delegado) est garantizado para proporcionar la funcionalidad que ha sido
delegada. Delegacin se puede utilizar para responder a una accin en particular, o para
recuperar datos de una fuente externa sin necesidad de conocer el tipo subyacente de esa
fuente.
El siguiente ejemplo define dos protocolos para el uso con los dados basados en juegos
de mesa:

protocol DiceGame {

var dice: Dice { get }

func play()

protocol DiceGameDelegate {

func gameDidStart(game: DiceGame)

func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int)

func gameDidEnd(game: DiceGame)

}
El DiceGame protocolo es un protocolo que puede ser adoptado por cualquier juego
que consiste en dados. ElDiceGameDelegate protocolo puede ser adoptado por
cualquier tipo para seguir el progreso de un DiceGame .

236

Aqu hay una versin del juego de la oca juego introducido originalmente en control de
flujo . Esta versin est adaptada para utilizar un Dados ejemplo para sus dados
rollos; adoptar el DiceGame protocolo; y para notificar a
un DiceGameDelegate sobre su progreso:

class SnakesAndLadders: DiceGame {

let finalSquare = 25

let dice = Dice(sides: 6, generator: LinearCongruentialGenerator())

var square = 0

var board: [Int]

init() {

board = [Int](count: finalSquare + 1, repeatedValue: 0)

board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02

board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08

var delegate: DiceGameDelegate?

func play() {

square = 0

delegate?.gameDidStart(self)

gameLoop: while square != finalSquare {

let diceRoll = dice.roll()

delegate?.game(self, didStartNewTurnWithDiceRoll: diceRoll)

switch square + diceRoll {

case finalSquare:

break gameLoop

case let newSquare where newSquare > finalSquare:

continue gameLoop

default:

square += diceRoll

square += board[square]

delegate?.gameDidEnd(self)

}
Para una descripcin de la Serpientes y Escaleras juego, ver la rotura seccin
del control de flujo captulo.
Esta versin del juego est envuelto en una clase llamada SnakesAndLadders , que
adopta la DiceGameprotocolo. Proporciona una gettable dados propiedad y

237

un juego mtodo con el fin de cumplir con el protocolo.(El dado de propiedad se


declara como una propiedad constante, ya que no tiene que cambiar despus de la
inicializacin, y el protocolo slo requiere que sea gettable.)
El Serpientes y Escaleras configuracin tablero de juego tiene lugar dentro de la
clase init () inicializador.Toda la lgica del juego se mueve dentro del protocolo
de juego mtodo, que utiliza el protocolo requerido dedados propiedad para
proporcionar sus valores dados.
Tenga en cuenta que el delegado de la propiedad se define como
un opcional DiceGameDelegate , debido a que un delegado no se requiere con el
fin de jugar el juego. Debido a que es de un tipo opcional, el delegado de la
propiedad se establece automticamente en un valor inicial de cero . A partir de
entonces, la instanciador juego tiene la opcin para establecer la propiedad de un
delegado adecuado.
DiceGameDelegate proporciona tres mtodos para el seguimiento del progreso de
un juego. Estos tres mtodos se han incorporado a la lgica del juego dentro
del juego mtodo anterior, y se llaman cuando un nuevo juego comienza, un nuevo
giro comienza o termina el juego.
Debido a que el delegado de la propiedad es una opcin DiceGameDelegate ,
el juego utiliza el mtodo opcional encadenamiento cada vez que se llama a un
mtodo en el delegado. Si el delegado propiedad es nulo, estas llamadas delegadas
fallan con gracia y sin error. Si el delegado propiedad es para no-nil, los mtodos de
delegado se llaman, y se pasan la SnakesAndLadders instancia como parmetro.
El siguiente ejemplo muestra una clase llamada DiceGameTracker , que adopta
la DiceGameDelegate protocolo:

class DiceGameTracker: DiceGameDelegate {

var numberOfTurns = 0

func gameDidStart(game: DiceGame) {

numberOfTurns = 0

if game is SnakesAndLadders {

println("Started a new game of Snakes and Ladders")

println("The game is using a \(game.dice.sides)-sided dice")

func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) {

++numberOfTurns

println("Rolled a \(diceRoll)")

func gameDidEnd(game: DiceGame) {

println("The game lasted for \(numberOfTurns) turns")

238

DiceGameTracker implementa los tres mtodos requeridos


por DiceGameDelegate . Utiliza estos mtodos para realizar un seguimiento del
nmero de vueltas de un juego se ha tomado. Se restablece
un numberOfTurnspropiedad a cero cuando se inicia el juego, se incrementa cada
vez que comienza un nuevo turno, e imprime el nmero total de vueltas una vez que el
juego ha terminado.
La implementacin de gameDidStart muestra arriba utiliza el juego de parmetros
para imprimir alguna informacin introductoria sobre el juego que est a punto de ser
jugado. El juego tiene un parmetro de tipo de DiceGame ,
no SnakesAndLadders , y as gameDidStart puede acceder y utilizar slo los
mtodos y propiedades que se implementan como parte de la DiceGame protocolo. Sin
embargo, el mtodo sigue siendo capaz de utilizar el tipo de colada para consultar el
tipo de la instancia subyacente. En este ejemplo, se comprueba siel juego es en
realidad una instancia de SnakesAndLadders detrs de las escenas, e imprime un
mensaje apropiado en caso afirmativo.
gameDidStart tambin accede al dado de la propiedad del pasado juego de
parmetros. Debido a que el juegose conoce para ajustarse a
la DiceGame protocolo, es la garanta de tener un dado de la propiedad, por lo que
elgameDidStart mtodo es capaz de acceder e imprimir de los
dados lados propiedad, independientemente de qu tipo de juego que se est jugando.
He aqu cmo DiceGameTracker ve en accin:

let tracker = DiceGameTracker()

let game = SnakesAndLadders()

game.delegate = tracker

game.play()

// Iniciado un nuevo juego de Serpientes y Escaleras

// El juego usa un dado de 6 lados

// Laminado a 3

// Laminado a 5

// Laminado un 4

// Laminado a 5

// El juego se prolong durante 4 vueltas


Adicin de Protocolo de conformidad con una extensin
Puede extender un tipo existente para adoptar y adaptarse a un nuevo protocolo, incluso
si usted no tiene acceso al cdigo fuente para el tipo existente. Las extensiones pueden
aadir nuevas propiedades, mtodos y subndices para un tipo existente, y por lo tanto
son capaces de aadir cualquier requisito que un protocolo puede exigir. Para obtener
ms informacin sobre las extensiones, vea Extensiones .
NOTA
Las instancias existentes de un tipo adoptan automticamente y se ajustan a un
protocolo cuando se aade que la conformidad con el tipo de la instancia en una
extensin.

239

Por ejemplo, este protocolo, llamado TextRepresentable , puede ser


implementado por cualquier tipo que tiene una manera de ser representado como
texto. Esto podra ser una descripcin de la misma, o una versin de texto de su estado
actual:

protocol TextRepresentable {

func asText() -> String

}
The Dice class from earlier can be extended to adopt and conform
to TextRepresentable:

extension Dice: TextRepresentable {

func asText() -> String {

return "A \(sides)-sided dice"

}
Esta extensin adopta el nuevo protocolo exactamente de la misma manera que
si Dados haba proporcionado en su implementacin original. El nombre del protocolo
se proporciona despus el nombre del tipo, separados por dos puntos, y una puesta en
prctica de todos los requisitos del protocolo se proporciona dentro de llaves de la
extensin.
Cualquier Dados ejemplo ahora se puede tratar como TextRepresentable :

let d12 = Dice(sides: 12, generator: LinearCongruentialGenerator())

println(d12.asText())

println ( d12 . AsText ())

// imprime "un dado de 12 lados"


Del mismo modo, la SnakesAndLadders clase de juego puede extenderse a adoptar
y ajustarse a laTextRepresentable protocolo:

extension SnakesAndLadders: TextRepresentable {

func asText() -> String {

return "A game of Snakes and Ladders with \(finalSquare) squares"

println(game.asText())

// imprime "Un juego de serpientes y escaleras con 25 plazas"


Declarando Adopcin Protocolo con una extensin
Si un tipo que ya cumple con todos los requisitos de un protocolo, pero an no ha
declarado que adopta ese protocolo, puede hacer que apruebe el protocolo con una
extensin vaca:

struct Hamster {

var name: String


240

func asText() -> String {

return "A hamster named \(name)"

extension Hamster: TextRepresentable {}


Instances of Hamster can now be used wherever TextRepresentable is the required type:

let simonTheHamster = Hamster(name: "Simon")

let somethingTextRepresentable: TextRepresentable = simonTheHamster

println(somethingTextRepresentable.asText())

// imprime "Un hmster llamado Simn"


NOTA
Tipos no adoptan automticamente un protocolo slo por la satisfaccin de sus
necesidades. Ellos siempre deben declarar explcitamente su adopcin del protocolo.
Colecciones de tipos de protocolo
Un protocolo se puede utilizar como el tipo que se almacena en una coleccin como una
matriz o un diccionario, como se menciona en protocolos como los tipos . En este
ejemplo se crea una matriz deTextRepresentable cosas:

let things: [TextRepresentable] = [game, d12, simonTheHamster]


Ahora es posible para iterar sobre los elementos de la matriz, e imprimir la
representacin textual de cada elemento:

for thing in things {

println(thing.asText())

// Un juego de serpientes y escaleras con 25 plazas

// un dado de 12 lados

// Un hmster llamado Simn


Tenga en cuenta que la cosa constante es de tipo TextRepresentable . No es del
tipo de los dados , o DiceGameo hmster , incluso si la instancia real detrs de
las escenas es de uno de esos tipos. Sin embargo, debido a que es de
tipo TextRepresentable , y todo lo que es TextRepresentable se sabe que
tiene un AsText mtodo, es seguro llamar thing.asText cada vez en el bucle.
Protocolo de Herencia
Un protocolo puede heredar uno o ms de otros protocolos y puede aadir otros
requisitos en la parte superior de los requisitos que hereda. La sintaxis de la herencia
protocolo es similar a la sintaxis de la herencia de clases, pero con la opcin a la lista de
mltiples protocolos heredados, separadas por comas:

protocol InheritingProtocol: SomeProtocol, AnotherProtocol {

// Definicin de protocolo va aqu

}
He aqu un ejemplo de un protocolo que hereda el TextRepresentable protocolo
desde arriba:

241

protocol PrettyTextRepresentable: TextRepresentable {

func asPrettyText() -> String

}
En este ejemplo se define un nuevo protocolo, PrettyTextRepresentable , que
hereda de TextRepresentable .Cualquier cosa que
adopta PrettyTextRepresentable debe satisfacer todos los requisitos impuestos
porTextRepresentable , adems de los requisitos adicionales impuestos
por PrettyTextRepresentable . En este
ejemplo, PrettyTextRepresentable aade un nico requisito de proporcionar
un mtodo de instancia denominado asPrettyText que devuelve una Cadena .
El SnakesAndLadders clase se puede extender a adoptar y cumplir
con PrettyTextRepresentable :

extension SnakesAndLadders: PrettyTextRepresentable {

func asPrettyText() -> String {

var output = asText() + ":\n"

for index in 1...finalSquare {

switch board[index] {

case let ladder where ladder > 0:

output += " "

case let snake where snake < 0:

output += " "

default:

output += " "

return output

}
Esta extensin indica que adopta la PrettyTextRepresentable protocolo y
proporciona una implementacin de la asPrettyText mtodo para
la SnakesAndLadders tipo. Cualquier cosa que
es PrettyTextRepresentable tambin debe ser TextRepresentable , por
lo que el asPrettyText aplicacin comienza llamando la AsText mtodo
delTextRepresentable protocolo para iniciar una cadena de salida. Se aade dos
puntos y un salto de lnea, y utiliza esto como el inicio de su representacin de texto
bastante. A continuacin, itera a travs de la serie de casillas del tablero, y anexa una
forma geomtrica para representar el contenido de cada cuadrado:
Si el valor del cuadrado es mayor que 0 , es la base de una escalera, y est
representado por .
Si el valor del cuadrado es inferior a 0 , que es la cabeza de una serpiente, y est
representado por .

242

De lo contrario, el valor de la plaza es 0 , y es una plaza "libre", representada por .


La implementacin del mtodo ahora se puede utilizar para imprimir una bonita
descripcin de texto de cualquier SnakesAndLadders ejemplo:

println(game.asPrettyText())

// Un juego de serpientes y escaleras con 25 plazas:

//
Protocolos-Class Slo
Puede limitar la adopcin del protocolo de tipos de clase (y no a las estructuras o
enumeraciones) mediante la adicin de la clase de palabras clave a la lista de la
herencia de un protocolo. La clase de palabras clave siempre debe aparecer primero
en la lista de la herencia de un protocolo, antes de que los protocolos heredados:

protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {

// Definicin de protocolo de clase slo va aqu

}
En el ejemplo anterior, SomeClassOnlyProtocol slo puede ser adoptada por los
tipos de clase. Se trata de un error de tiempo de compilacin para escribir una definicin
de estructura o enumeracin que intenta adoptarSomeClassOnlyProtocol .
NOTA
Utilice un protocolo de clase slo cuando el comportamiento definido por los requisitos
de ese protocolo supone o exige que un tipo de conformacin tiene una semntica de
referencia en lugar de la semntica de valor. Para ms informacin sobre referencia y
valor semntico, ver estructuras y enumeraciones son tipos de valor y las clases son
tipos de referencia .
Protocolo de Composicin
Puede ser til exigir un tipo de ajustarse a mltiples protocolos a la vez. Se pueden
combinar varios protocolos en un nico requisito con una composicin
protocolo . Composiciones Protocolo tienen la forma de protocolo
<SomeProtocol, AnotherProtocol> . Usted puede enumerar tantos
protocolos dentro del par de corchetes angulares ( <> ) como necesite, separados por
comas.
He aqu un ejemplo que combina dos protocolos llamados con
nombre y envejecido en un nico requisito composicin protocolo en un
parmetro de la funcin:

protocol Named {

var name: String { get }

protocol Aged {

var age: Int { get }

struct Person: Named, Aged {

var name: String

var age: Int


243

func wishHappyBirthday(celebrator: protocol<Named, Aged>) {

println("Happy birthday \(celebrator.name) - you're \(celebrator.age)!")

let birthdayPerson = Person(name: "Malcolm", age: 21)

wishHappyBirthday(birthdayPerson)

// imprime "Feliz cumpleaos Malcolm - usted es 21!"


En este ejemplo se define un protocolo llamado Nombrado , con un nico requisito
para un gettable Cadenapropiedad llamada nombre . Tambin define un protocolo
llamado Aged , con un nico requisito para un gettableInt propiedad
llamada edad . Estos dos protocolos son adoptadas por una estructura
llamada persona .
El ejemplo tambin define una funcin llamada wishHappyBirthday , que toma un
solo parmetro denominadocelebrator . El tipo de este parmetro es el
protocolo <Nombre, Edad> , que significa "cualquier tipo que satisfaga tanto
los nombrados y envejecidas protocolos. "No importa qu tipo especfico que se
pasa a la funcin, siempre y cuando se ajuste a tanto de los protocolos requeridos.
El ejemplo a continuacin, crea una nueva persona instancia
llamada birthdayPerson y entrega esta nueva instancia de
la wishHappyBirthday funcin. Debido persona cumple con ambos protocolos,
esto es una llamada vlida, y el wishHappyBirthday funcin es capaz de imprimir
su saludo de cumpleaos.
NOTA
Composiciones Protocolo no definen un nuevo tipo de protocolo permanente. Por el
contrario, definen un protocolo local temporal que tiene los requisitos combinados de
todos los protocolos en la composicin.
Comprobacin de la conformidad de Protocolo
Puede utilizar los es y como operadores descritos en la conversin de tipos para
comprobar el cumplimiento del protocolo, y para echar a un protocolo
especfico. Comprobacin de que emitan un protocolo sigue exactamente la misma
sintaxis que la revisin y la fundicin a un tipo:
El es operador devuelve verdadero si una instancia es conforme a un protocolo
y devuelve falso si no lo hace.
El como? versin del operador abatido devuelve un valor opcional de tipo de
protocolo, y este valor esnulo si la instancia no se ajusta a ese protocolo.
El como versin del operador abatido fuerza al abatido al tipo de protocolo y
provoca un error de ejecucin si los abatidos no tiene xito.
Este ejemplo define un protocolo llamado HasArea , con un nico requisito de
propiedad de un gettable doblepropiedad llamada rea :

@objc protocol HasArea {

var area: Double { get }

}
NOTA

244

Puede comprobar el cumplimiento del protocolo slo si el protocolo est marcado con
el objc atributo, como se ve por la HasArea protocolo anterior. Este atributo indica
que el protocolo debe ser expuesto al cdigo de Objective-C y se describe en Uso de
Swift con Cocoa y Objective-C . Incluso si usted no est interoperar con Objective-C,
tiene que marcar sus protocolos con el objc atributo si quieres ser capaz de verificar la
conformidad del protocolo.
Tenga en cuenta tambin que los objc protocolos pueden ser adoptadas por las clases,
y no por estructuras o enumeraciones. Si marca el protocolo como objc con el fin de
comprobar la conformidad, usted ser capaz de aplicar ese protocolo slo para tipos de
clase.
Aqu hay dos clases, Circle y Pas , las cuales se ajustan a la HasArea protocolo:

class Circle: HasArea {

let pi = 3.1415927

var radius: Double

var area: Double { return pi * radius * radius }

init(radius: Double) { self.radius = radius }

class Country: HasArea {

var area: Double

init(area: Double) { self.area = area }

}
El Crculo clase implementa el rea requisito de propiedad como una propiedad
calculada, en base a un almacenada radio de propiedad. El Pas clase implementa
el rea requerimiento directamente como una propiedad almacenada. Ambas clases se
ajustan correctamente a la HasArea protocolo.
Aqu hay una clase llamada Animal , que no se ajusta a la HasArea protocolo:

class Animal {

var legs: Int

init(legs: Int) { self.legs = legs }

}
Los Circle , Pas y animales clases no tienen una clase base comn. No obstante,
son todas las clases, y por lo tanto los casos de los tres tipos pueden utilizarse para
inicializar una matriz que almacena valores de tipoAnyObject :

let objects: [AnyObject] = [

Circle(radius: 2.0),

Country(area: 243_610),

Animal(legs: 4)

]
El objeto array se inicializa con un literal de matriz que contiene
un crculo instancia con un radio de 2 unidades; un Pas instancia inicializada con

245

el rea de la superficie del Reino Unido en kilmetros cuadrados;y


un Animal ejemplo, con cuatro patas.
El objeto array ahora puede repetirse, y cada objeto de la matriz se puede comprobar
para ver si se ajusta a la HasArea protocolo:

for object in objects {

if let objectWithArea = object as? HasArea {

println("Area is \(objectWithArea.area)")

} else {

println("Something that doesn't have an area")

// Area es 12.5663708

// Area es 243610.0

// Algo que no tiene un rea


Siempre que un objeto de la matriz se ajusta a la HasArea protocolo, el valor devuelto
por el opcional como?operador se desenvuelve con la unin opcional en una constante
llamada objectWithArea . El objectWithAreaconstante es conocido por ser de
tipo HasArea , por lo que su rea de la propiedad se puede acceder e imprimir de
una manera con seguridad de tipos.
Tenga en cuenta que los objetos subyacentes no se modifican por el proceso de
fundicin. Ellos siguen siendo un crculo , un pas y un animal . Sin embargo, en
el punto que se almacenan en la objectWithAreaconstante, slo se sabe que son de
tipo HasArea , y as slo su rea se puede acceder a la propiedad.
Protocolo de Requisitos opcionales
Puede definir los requisitos facultativos para los protocolos, Estos requisitos no tienen
que ser aplicadas por los tipos que cumplen con el protocolo. Requisitos opcionales van
precedidos por el opcional modificador como parte de la definicin del protocolo.
Un requisito de protocolo facultativo puede ser llamado con el encadenamiento
opcional, para dar cuenta de la posibilidad de que el requisito no fue implementado por
un tipo que cumpla con el protocolo. Para obtener informacin sobre el encadenamiento
opcional, consulte encadenamiento opcional .
Te registras para una implementacin de un requisito opcional, escribiendo un signo de
interrogacin despus del nombre de dicho requisito cuando se llama,
como someOptionalMethod? (someArgument) .Requisitos de propiedades
opcionales, y los requisitos del mtodo opcional que devuelven un valor, siempre
devolver un valor opcional del tipo apropiado cuando se accede a ellos o llaman, para
reflejar el hecho de que el requisito opcional no pudo ejecutarse.
NOTA
Requisitos del protocolo opcionales slo se pueden especificar si el protocolo est
marcado con el objcatributo. Incluso si usted no est interoperar con Objective-C,
tiene que marcar sus protocolos con el objcatributo si desea especificar requisitos
opcionales.

246

Tenga en cuenta tambin que los objc protocolos pueden ser adoptadas por las clases,
y no por estructuras o enumeraciones. Si marca el protocolo como objc con el fin de
especificar los requisitos opcionales, slo ser capaz de aplicar ese protocolo para tipos
de clase.
El ejemplo siguiente define una clase entera de conteo llamado Contador , que utiliza
una fuente de datos externa para proporcionar a su importe mnimo de la subasta. Esta
fuente de datos se define por laCounterDataSource protocolo, que tiene dos
requisitos opcionales:

@objc protocol CounterDataSource {

optional func incrementForCount(count: Int) -> Int

optional var fixedIncrement: Int { get }

}
El CounterDataSource protocolo define un requisito mtodo opcional
llamado incrementForCount y un requisito de propiedad opcional
llamado fixedIncrement . Estos requisitos definen dos maneras diferentes para
fuentes de datos para proporcionar una cantidad de incremento apropiado para
un contador de instancia.
NOTA
En rigor, se puede escribir una clase personalizada que se ajuste
a CounterDataSource sin implementar ya sea requisito protocolo. Ellos son ambos
opcionales, despus de todo. Aunque tcnicamente permitido, esto no hara por una muy
buena fuente de datos.
El contador de la clase, se define a continuacin, tiene un
opcional dataSource propiedad de tipoCounterDataSource? :

@objc class Counter {

var count = 0

var dataSource: CounterDataSource?

func increment() {

if let amount = dataSource?.incrementForCount?(count) {

count += amount

} else if let amount = dataSource?.fixedIncrement? {

count += amount

}
El contador de la clase almacena su valor actual en una propiedad variable
llamada count . El contador de la clase tambin define un mtodo llamado de
incremento , lo que incrementa el recuento de propiedad cada vez que se llama
al mtodo.
El incremento mtodo primero intenta recuperar un importe mnimo de la subasta
mediante la bsqueda de una implementacin de la incrementForCount mtodo en
su origen de datos. El incremento mtodo utiliza el encadenamiento opcional para

247

tratar de llamar incrementForCount , y pasa el actual conteo valor como nico


argumento del mtodo.
Nota dos niveles de encadenamiento opcional en juego aqu. En primer lugar, es posible
que dataSourcepuede ser nulo , y as dataSource tiene un signo de
interrogacin despus de su nombre para indicar queincrementForCount slo se
debe llamar si dataSource es no-nil. En segundo lugar, incluso
si dataSource noexiste, no hay ninguna garanta de que
aplique incrementForCount , porque es un requisito opcional. Esta es la razn
por incrementForCount tambin se escribe con un signo de interrogacin despus
de su nombre.
Debido a que la llamada a incrementForCount puede fallar por cualquiera de estas
dos razones, la llamada devuelve un opcional Int valor. Esto es cierto a pesar de
que incrementForCount se define como devolver un no opcional Int valor en la
definicin de CounterDataSource .
Despus de llamar incrementForCount , el opcional Int que devuelve se
desenvolvi en una constante llamadacantidad , usando opcional de unin. Si el
opcional Int contiene un valor, es decir, si el delegado y el mtodo tanto existen, y el
mtodo devuelve un valor sin envolver la cantidad se aade a la
almacenada recuento depropiedad, y de incremento es completa.
Si es no posible recuperar un valor de la incrementForCount mtodo-ya sea
porque dataSource es nula, o porque la fuente de datos no
implementa incrementForCount -entonces el incremento mtodo intenta
recuperar un valor de de la fuente de datos fixedIncrement propiedad en
lugar. El fixedIncrement propiedad es tambin un requisito opcional, por lo que su
nombre tambin se escribe con el encadenamiento opcional con un signo de
interrogacin en el extremo, para indicar que el intento de acceder a el valor de la
propiedad puede fallar.Como antes, el valor devuelto es un opcional Int valor,
aunque fixedIncrement se define como una no opcional Int propiedad como
parte de la CounterDataSource definicin de protocolo.
He aqu una sencilla CounterDataSource aplicacin donde la fuente de datos
devuelve un valor constante de 3cada vez que se consulta. Lo hace mediante la
aplicacin de la opcin fixedIncrement requisito de propiedad:

class ThreeSource: CounterDataSource {

let fixedIncrement = 3

}
Puede utilizar una instancia de ThreeSource como origen de datos para un
nuevo contador ejemplo:

var counter = Counter()

counter.dataSource = ThreeSource()

for _ in 1...4 {

counter.increment()

println(counter.count)

}
248

// 3

// 6

// 9

// 12
El cdigo anterior crea un nuevo contador de instancia; establece su fuente de datos
para ser un nuevoThreeSource instancia; y pide del contador incremento mtodo
de cuatro veces. Como era de esperar, el contador count propiedad aumenta por tres
cada vez que la subasta se llama.
He aqu una fuente de datos ms compleja llamada TowardsZeroSource , lo que
hace un contador de instancia contar hacia arriba o hacia abajo a cero de su
actual cuenta de valor:

class TowardsZeroSource: CounterDataSource {

func incrementForCount(count: Int) -> Int {

if count == 0 {

return 0

} else if count < 0 {

return 1

} else {

return -1

}
El TowardsZeroSource clase implementa la
opcional incrementForCount mtodo del CounterDataSource protocolo y
utiliza el conteo valor del argumento de averiguar qu direccin para contar.
Si cuenta ya es cero, el mtodo devuelve 0 para indicar que no hay ms de conteo
debe tener lugar.
Puede utilizar una instancia de TowardsZeroSource con el
vigente Contador instancia a contar desde -4 a cero.Una vez que el contador llegue a
cero, no ms de conteo se lleva a cabo:

counter.count = -4

counter.dataSource = TowardsZeroSource()

for _ in 1...5 {

counter.increment()

println(counter.count)

// -3

// -2

// -1

249

// 0

// 0

Genricos
Cdigo genrico le permite escribir, funciones flexibles reutilizables y tipos que pueden
trabajar con cualquier tipo, con sujecin a los requisitos que se definan. Se puede
escribir cdigo que evite la duplicacin y expresa su intencin de una manera clara
abstrado.
Los genricos son una de las caractersticas ms potentes de Swift, y gran parte de la
biblioteca estndar de Swift est construido con cdigo genrico. De hecho, usted ha
estado utilizando los genricos en toda la gua de idiomas , incluso si usted no se dio
cuenta. Por ejemplo, de Swift matriz y Diccionario tipos son ambas colecciones
genricas. Puede crear una matriz que contiene Int valores, o una matriz que
contiene Cuerdavalores, o incluso una matriz de cualquier otro tipo que se puede crear
en Swift. Del mismo modo, se puede crear un diccionario para almacenar valores de
cualquier tipo especificado, y no hay limitaciones en lo que ese tipo puede ser.
El problema que Generics Resuelva
Aqu hay un estndar de funcin, no genrica llamada swapTwoInts , que
intercambia dos Int valores:

func swapTwoInts(inout a: Int, inout b: Int) {

let temporaryA = a

a=b

b = temporaryA

}
Esta funcin hace uso de parmetros de salida para cambiar los valores de una y b ,
como se describe enParmetros In-Out .
El swapTwoInts funcin intercambia el valor original de b en una , y el valor
original de una en b . Usted puede llamar a esta funcin para intercambiar los valores
de dos Int variables:

var someInt = 3

var anotherInt = 107

swapTwoInts(&someInt, &anotherInt)

println("someInt is now \(someInt), and anotherInt is now \(anotherInt)")

// Impresiones "someInt es ahora 107, y anotherInt es ahora


3"
El swapTwoInts funcin es til, pero slo se puede utilizar con Int valores. Si usted
quiere intercambiar dos de Cuerda valores, o dos dobles valores, tienes que
escribir ms funciones, como las swapTwoStrings yswapTwoDoubles funciones
que se muestran a continuacin:

func swapTwoStrings(inout a: String, inout b: String) {


250

let temporaryA = a

a=b

b = temporaryA

func swapTwoDoubles(inout a: Double, inout b: Double) {

let temporaryA = a

a=b

b = temporaryA

}
Usted puede haber notado que los cuerpos de
los swapTwoInts , swapTwoStrings y swapTwoDoubles funciones son
idnticas. La nica diferencia es el tipo de los valores que se aceptan ( Int , Cuerda ,
y dobles ).
Sera mucho ms til, y considerablemente ms flexible, para escribir una sola funcin
que podran intercambiar dos valores de cualquier tipo. Cdigo genrico le permite
escribir una funcin de este tipo. (Una versin genrica de estas funciones se define a
continuacin.)
NOTA
En todas las tres funciones, es importante que los tipos de una y b se definen para ser el
mismo que el uno al otro. Si una y b no eran del mismo tipo, no sera posible cambiar
sus valores. Swift es un lenguaje de tipo seguro, y no permite que (por ejemplo) una
variable de tipo de cadena y una variable de tipo doble para intercambiar valores
entre s. Si lo intenta, se inform como un error en tiempo de compilacin.
Funciones Genricas
Funciones genricas pueden trabajar con cualquier tipo. Aqu hay una versin genrica
del swapTwoIntsfuncin de lo alto, llamados swapTwoValues :

func swapTwoValues<T>(inout a: T, inout b: T) {

let temporaryA = a

a=b

b = temporaryA

}
El cuerpo de la swapTwoValues funcin es idntica a la del cuerpo de
la swapTwoInts funcin. Sin embargo, la primera lnea de swapTwoValues es
ligeramente diferente de swapTwoInts . He aqu cmo se comparan las primeras
lneas:

func swapTwoInts(inout a: Int, inout b: Int)

func swapTwoValues<T>(inout a: T, inout b: T)


La versin genrica de la funcin utiliza un marcador de posicin el nombre del tipo
(llamado T , en este caso) en lugar de un verdadero nombre de tipo
(como int , cuerdas , o doble ). El nombre del tipo de marcador de posicin no

251

dice nada acerca de lo que T debe ser, pero no decir que tanto una y b deben ser del
mismo tipo T, lo que T representa. El tipo real para usar en lugar de T ser determinado
cada vez que el swapTwoValues funcin es llamada.
La otra diferencia es que el nombre de la funcin genrica ( swapTwoValues ) es
seguido por el nombre del tipo de marcador de posicin ( T ) dentro de corchetes
angulares ( <T> ). Los corchetes indican que Swift T es un nombre de tipo de marcador
de posicin dentro de la swapTwoValues definicin de la funcin. Debido a que T es
un marcador de posicin, Swift no busca un tipo real llamado T .
El swapTwoValues funcin puede ser llamado ahora en la misma manera
que swapTwoInts , excepto que se puede pasar dos valores de cualquier tipo,
siempre y cuando ambos de esos valores son del mismo tipo que el uno al otro. Cada
vez swapTwoValues se llama, el tipo a utilizar para T se infiere de los tipos de
valores pasados a la funcin.
En los dos ejemplos siguientes, T se infiere ser Int y de cadena , respectivamente:

var someInt = 3

var anotherInt = 107

swapTwoValues(&someInt, &anotherInt)

// SomeInt es ahora 107, y anotherInt es ahora 3

var someString = "hello"

var anotherString = "world"

swapTwoValues(&someString, &anotherString)

// SomeString es ahora "mundo", y anotherString es ahora


"hola"
NOTA
El swapTwoValues funcin definida anteriormente se inspira en una funcin
genrica llamada de intercambio , que es parte de la biblioteca estndar de Swift,
y se hace automticamente disponible para su uso en sus aplicaciones. Si usted necesita
el comportamiento de la swapTwoValues funcin en su propio cdigo, puede utilizar
existente de Swift canje funcin en lugar de proporcionar su propia implementacin.
Parmetros de tipo
En la swapTwoValues ejemplo anterior, el tipo de marcador de posicin T es un
ejemplo de un parmetro de tipo. Los parmetros de tipo especifican y nombrar un tipo
de marcador de posicin, y se escriben inmediatamente despus del nombre de la
funcin, entre un par de corchetes angulares coincidentes (como<T> ).
Una vez que se especifica un parmetro de tipo, se puede utilizar para definir el tipo de
parmetros de una funcin (por ejemplo, los unos y b parmetros
del swapTwoValues funcin), o como tipo de retorno de la funcin, o como una
anotacin de tipo dentro del cuerpo de la funcin. En cada caso, el tipo de marcador de
posicin representado por el parmetro de tipo se reemplaza con un real tipo cada vez
que la funcin se llama. (En laswapTwoValues ejemplo anterior, T fue sustituido
por Int la primera vez que la funcin se llama, y fue reemplazado con cuerdas la
segunda vez que se llamaba.)

252

Puede proporcionar ms de un parmetro de tipo escribiendo mltiples nombres de los


parmetros de tipo dentro de los corchetes angulares, separadas por comas.
Nombrar parmetros de tipo
En los casos en los que una funcin genrica o tipo genrico se refiere a un solo tipo de
marcador de posicin (como el swapTwoValues funcin genrica anteriormente, o
una coleccin genrica que almacena un solo tipo, tales como la matriz ), es
tradicional usar el nombre de un solo carcter T para el parmetro de tipo. Sin embargo,
puede utilizar cualquier identificador vlido como nombre de parmetro de tipo.
Si va a definir funciones genricas ms complejas, o tipos genricos con mltiples
parmetros, es til para proporcionar nombres de los parmetros de tipo ms
descriptivos. Por ejemplo, de Swift Diccionario tipo tiene dos parmetros de un
tipo para sus claves y otra para sus valores. Si estuviera escribiendo Diccionario ti
mismo, podra denominar estos dos parmetros de tipo KeyType y ValueType para
recordarle de su propsito como usted los utiliza en el cdigo genrico.
NOTA
Siempre dar parmetros de tipo UpperCamelCase nombres (como T y KeyType )
para indicar que son un marcador de posicin para un tipo , no un valor.
Tipos genricos
Adems de las funciones genricas, Swift le permite definir sus propios tipos
genricos . Estas son clases personalizadas, estructuras y enumeraciones que pueden
trabajar con cualquier tipo, de una manera similar a la matriz y Diccionario .
Esta seccin le muestra cmo escribir un tipo de coleccin genrica
llamada Pila . Una pila es un conjunto ordenado de valores, similar a una matriz, pero
con un conjunto ms restringido de las operaciones que los de Swift matriz tipo. Una
matriz permite a los nuevos elementos que se insertan y se retiran en cualquier
ubicacin en la matriz. Una pila, sin embargo, permite que los nuevos elementos que se
aaden slo al final de la coleccin (conocido como empujando un nuevo valor en la
pila). Del mismo modo, una pila permite que los elementos que se eliminan slo desde
el final de la coleccin (conocido como apareciendo un valor de la pila).
NOTA
El concepto de una pila es utilizado por el UINavigationController clase para
modelar los controladores de vista en su jerarqua de navegacin. Se llama a
la UINavigationController clase pushViewController:
animada: mtodo para agregar (o empujar) un controlador de vista en la pila de
navegacin, y supopViewControllerAnimated: mtodo para eliminar (o pop)
un controlador de vista de la pila de navegacin.Una pila es un modelo til coleccin
siempre cuando necesite estricta "ltimo en entrar, primero en salir" para la gestin de
una coleccin.
La siguiente ilustracin muestra el comportamiento push / pop para una pila:

253


1. En este momento hay tres valores en la pila.
2. Un cuarto valor es "empujada" en la parte superior de la pila.
3. La pila ahora tiene cuatro valores, con el ms reciente en la parte superior.
4. El elemento superior de la pila se elimina, o "estallar".
5. Despus de hacer estallar un valor, la pila tiene una vez ms tres valores.
Aqu se explica cmo escribir una versin no genrica de una pila, en este caso para una
pila de Int valores:

struct IntStack {

var items = [Int]()

mutating func push(item: Int) {

items.append(item)

mutating func pop() -> Int {

return items.removeLast()

}
Esta estructura utiliza una matriz de propiedad denominado artculos para
almacenar los valores en la pila.Stack proporciona dos mtodos, empuje y pop ,
para impulsar y valores emergentes y fuera de la pila. Estos mtodos estn marcados
como mutante , porque tienen que modificar (o mutar ) de la estructura de los
elementos de matriz.
El IntStack tipo mostrado anteriormente solamente se puede utilizar
con Int valores, sin embargo. Sera mucho ms til para definir
un genrico Pila clase, que puede administrar una pila de cualquier tipo de valor.
Aqu hay una versin genrica del mismo cdigo:

struct Stack<T> {

var items = [T]()

mutating func push(item: T) {


254

items.append(item)

mutating func pop() -> T {

return items.removeLast()

}
Ntese cmo la versin genrica de la pila es esencialmente la misma que la
versin no genrica, pero con un parmetro de tipo de marcador de posicin
denominada T en lugar de un tipo real de Int . Este parmetro tipo se escribe dentro de
un par de corchetes angulares ( <T> ) inmediatamente despus del nombre de la
estructura.
T define un nombre de marcador de posicin para "Tipo de alguna T "para proporcionar
ms adelante. Este tipo futuro puede ser referido como " T "en cualquier lugar dentro de
la definicin de la estructura. En este caso, T se utiliza como un marcador de posicin
en tres lugares:
Para crear una propiedad llamada artculos , que se inicia con una matriz vaca
de valores de tipo T
Para especificar que el empuje mtodo tiene un nico parmetro llamado tema ,
que debe ser de tipo T
Para especificar que el valor devuelto por el pop mtodo ser un valor de tipo T
Debido a que es un tipo genrico, Stack se puede utilizar para crear una pila
de cualquier tipo vlido en Swift, de una manera similar a
la matriz y Diccionario .
Se crea una nueva pila instancia escribiendo el tipo que se almacena en la pila dentro
de parntesis angulares. Por ejemplo, para crear una nueva pila de cuerdas,
escribes Stack <String> () :

var stackOfStrings = Stack<String>()

stackOfStrings.push("uno")

stackOfStrings.push("dos")

stackOfStrings.push("tres")

stackOfStrings.push("cuatro")

// La pila ahora contiene 4 cuerdas


As es como stackOfStrings se ve despus de empujar a estos cuatro valores en la
pila:

255


Hacer estallar un valor a partir de las declaraciones de la pila y elimina el valor de la
parte superior, "cuatro" :

let fromTheTop = stackOfStrings.pop()

// FromTheTop es igual a "cuatro", y la pila ahora contiene


3 cadenas
As es como la pila se ocupa de hacer estallar su valor superior:


La extensin de un tipo genrico
Al ampliar un tipo genrico, no proporciona una lista de parmetros de tipo como parte
de la definicin de la extensin. En cambio, la lista de parmetros de tipo de la original
de definicin de tipo se encuentra disponible dentro del cuerpo de la extensin, y los
nombres de los parmetros de tipo originales se utilizan para referirse a los parmetros
de tipo de la definicin original.
El siguiente ejemplo extiende la genrica Stack tipo para agregar una propiedad de
slo lectura computarizada llamada topItem , que devuelve el elemento superior de la
pila sin estallar de la pila:

extension Stack {

var topItem: T? {

return items.isEmpty ? nil : items[items.count - 1]

256

El topItem propiedad devuelve un valor opcional de tipo T . Si la pila est


vaca, topItem devuelve nil ; Si la pila no est vaca, topItem devuelve el
elemento final en el artculos matriz.
Tenga en cuenta que esta extensin no define una lista de parmetros de tipo. En
cambio, la pila existente nombre de parmetro de tipo de tipo, T , se utiliza dentro de
la extensin para indicar el tipo opcional de latopItem propiedad computarizada.
El topItem propiedad calculado ahora se puede utilizar con cualquier Pila ejemplo,
para acceder y consultar su elemento superior sin sacarlo:

if let topItem = stackOfStrings.topItem {

println("The top item on the stack is \(topItem).")

// imprime "El primer elemento en la pila es tres."


Tipo Restricciones
El swapTwoValues funcin y la Pila tipo pueden trabajar con cualquier tipo. Sin
embargo, a veces es til para hacer cumplir ciertas restricciones de tipo de los tipos que
se pueden utilizar con las funciones genricas y tipos genricos. Tipo restricciones
especifican que un parmetro de tipo debe heredar de una clase especfica, o se ajustan a
una composicin de protocolo o protocolo particular.
Por ejemplo, de Swift Diccionario tipo coloca una limitacin en los tipos que
pueden ser usadas como claves en un diccionario. Como se describe en Diccionarios , el
tipo de teclas de un diccionario debe ser Hashable .Es decir, se debe proporcionar una
forma de hacerse de forma nica representable. Diccionario necesita sus claves
para ser Hashable para que pueda comprobar si ya contiene un valor para una clave
particular. Sin este requisito, Diccionario no poda decir si se debe insertar o
cambiar un valor para una clave determinada, ni sera capaz de encontrar un valor para
una clave determinada que ya est en el diccionario.
Este requisito es exigido por una restriccin de tipo en el tipo de clave
de diccionario , que especifica que el tipo de clave debe ser conforme a
la Hashable protocolo, un protocolo especial definido en la librera estndar de
Swift. Todos los tipos bsicos de Swift (tales como cuerdas , Int , doble ,
y Bool ) son Hashable por defecto.
Puede definir sus propias restricciones de tipo al crear tipos personalizados genricos, y
estas limitaciones proporcionar gran parte de la potencia de la programacin
genrica. Los conceptos abstractos como Hashablecaracterizan tipos en trminos de
sus caractersticas conceptuales, ms que su tipo explcito.
Escriba Sintaxis Restriccin
Usted escribe restricciones de tipo mediante la colocacin de una sola clase o restriccin
protocolo despus del nombre de un parmetro de tipo, separados por dos puntos, como
parte de la lista de parmetros de tipo.La sintaxis bsica de restricciones de tipo en una
funcin genrica se muestra a continuacin (aunque la sintaxis es la misma para tipos
genricos):

func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {

// Cuerpo de la funcin va aqu

257

La funcin hipottica anterior tiene dos parmetros de tipo. El primer parmetro de


tipo, T , tiene una restriccin que requiere tipo T de ser una subclase
de AlgunaClase . El segundo parmetro de tipo, U , tiene una restriccin que
requiere tipo U para adaptarse al protocolo SomeProtocol .
Escriba Restricciones en Accin
Aqu est una funcin no genrica llamada findStringIndex , que se da
una Cadena de valor de encontrar y una gran variedad de Cuerda valores dentro de la
cual para encontrarlo. El findStringIndex funcin devuelve un
opcional Int valor, que ser el ndice de la primera cadena coincidente de la matriz, si
se comprueba, o nilsi la cadena no se puede encontrar:

func findStringIndex(array: [String], valueToFind: String) -> Int? {

for (index, value) in enumerate(array) {

if value == valueToFind {

return index

return nil

}
El findStringIndex funcin se puede utilizar para encontrar un valor de cadena en
una matriz de cadenas:

let strings = ["cat", "dog", "llama", "parakeet", "terrapin"]

if let foundIndex = findStringIndex(strings, "llama") {

println("The index of llama is \(foundIndex)")

// imprime "El ndice de la llama es de 2"


El principio de encontrar el ndice de un valor en una matriz no slo es til para las
cadenas, sin embargo.Usted puede escribir la misma funcionalidad que una funcin
genrica llamada FindIndex , mediante la sustitucin de cualquier mencin de
cadenas con valores de un cierto tipo T en su lugar.
He aqu cmo usted puede ser que espere una versin genrica
de findStringIndex , llamado FindIndex , para ser escrito. Tenga en cuenta que
el tipo de retorno de esta funcin es todava Int? , porque la funcin devuelve un
nmero de ndice opcional, no un valor opcional de la matriz. Se advirti, sin embargo,
esta funcin no se compila, por razones que se explican a ejemplo:

func findIndex<T>(array: [T], valueToFind: T) -> Int? {

for (index, value) in enumerate(array) {

if value == valueToFind {

return index

258

return nil

}
Esta funcin no se compila lo escrito anteriormente. El problema radica en la
comprobacin de igualdad, " si el valor == valueToFind ". No todos los
tipos de Swift se puede comparar con el operador igual a ( == ). Si crea su propia clase
o estructura para representar un modelo de datos complejos, por ejemplo, entonces el
significado de "igual" para esa clase o estructura no es algo que Swift puede adivinar
por ti. Debido a esto, no es posible garantizar que el cdigo funciona para cada tipo
posible T , y se informa de un error apropiado cuando intenta compilar el cdigo.
No todo est perdido, sin embargo. La librera estndar Swift define un protocolo
llamado equatable , que requiere cualquier tipo de conformacin para aplicar el
operador igual a ( == ) y el operador no es igual a ( ! =) para comparar dos valores de
ese tipo. Todos los tipos estndar de Swift apoyan automticamente
elequatable protocolo.
Cualquier tipo que es equiparable se puede utilizar de manera segura con
la FindIndex funcin, ya que se garantiza la compatibilidad de la igual al
operador. Para expresar este hecho, usted escribe una restriccin de tipo
de equatable como parte de la definicin del tipo de parmetro cuando se define la
funcin:

func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? {

for (index, value) in enumerate(array) {

if value == valueToFind {

return index

return nil

}
El nico parmetro de tipo para FindIndex se escribe como T: equatable , que
significa "cualquier tipo T que se ajusta a la equatable protocolo. "
El FindIndex funcin ahora compila con xito y se puede utilizar con cualquier tipo
que sea equiparable , tales como doble o de cadena :

let doubleIndex = findIndex([3.14159, 0.1, 0.25], 9.3)

// DoubleIndex es un Int opcional con ningn valor, porque


no es 9,3 en la matriz

let stringIndex = findIndex(["Mike", "Malcolm", "Andrea"], "Andrea")

// StringIndex es un Int opcional que contiene un valor de


2

Tipos Asociados
En la definicin de un protocolo, a veces es til para declarar uno o ms tipos de
asociados como parte de la definicin del protocolo. Un tipo asociado da un nombre de

259

marcador de posicin (o alias ) a un tipo que se utiliza como parte del protocolo. El tipo
real de utilizar para ese tipo asociado no se ha especificado hasta que se adopte el
protocolo. Tipos asociados se especifican con el typealias palabra clave.
Tipos Asociados en Accin
He aqu un ejemplo de un protocolo llamado Container , que declara un tipo
asociado llamado ItemType :

protocol Container {

typealias ItemType

mutating func append(item: ItemType)

var count: Int { get }

subscript(i: Int) -> ItemType { get }

}
El Contenedor protocolo define tres capacidades necesarias que cualquier
contenedor debe proporcionar:
Debe ser posible aadir un nuevo elemento en el contenedor con
un append mtodo.
Debe ser posible acceder a un recuento de los artculos en el recipiente a travs de
un recuento depropiedad que devuelve un Int valor.
Debe ser posible para recuperar cada elemento en el recipiente con un subndice que
toma un Int valor de ndice.
Este protocolo no especifica cmo los elementos en el contenedor deben ser
almacenados o qu tipo se les permite ser. El protocolo slo especifica los tres bits de
funcionalidad que cualquier tipo debe proporcionar a fin de ser considerado
un Contenedor . Un tipo de conformacin puede proporcionar funcionalidad
adicional, con tal de que satisface estos tres requisitos.
Cualquier tipo que se ajusta a la Container protocolo debe ser capaz de especificar el
tipo de valores que almacena. En concreto, se debe asegurar que slo los elementos del
tipo correcto se aaden al recipiente, y tiene que tener claro el tipo de los elementos
devueltos por su subndice.
Para definir estos requisitos, el Container protocolo necesita una forma de referirse
al tipo de los elementos que caben en este recipiente, sin saber lo que el tipo es un
contenedor especfico. El Contenedor protocolo debe especificar que cualquier valor
pasado al append mtodo debe tener el mismo tipo que el tipo de elemento del
contenedor, y que el valor devuelto por el subndice del contenedor ser del mismo tipo
que el tipo de elemento del contenedor.
Para lograrlo, el Container protocolo declara un tipo asociado llamado ItemType ,
escrito como typealias ItemType . El protocolo no define lo ItemType es un
alias para informacin -es se deja para cualquier tipo de conformacin para
proporcionar. No obstante, el ItemType alias proporciona una manera de referirse al
tipo de los elementos de un Contenedor , y para definir un tipo para su uso con
el append mtodo y subndice, para asegurar que el comportamiento que se espera de
cualquier Container se hace cumplir.
Aqu hay una versin de la no genrica IntStack tipo de anterior, adaptado para
ajustarse a la Containerprotocolo:

260

struct IntStack: Container {

// Aplicacin IntStack originales

var items = [Int]()

mutating func push(item: Int) {

items.append(item)

mutating func pop() -> Int {

return items.removeLast()

// La conformidad con el protocolo de contenedores

typealias ItemType = Int

mutating func append(item: Int) {

self.push(item)

var count: Int {

return items.count

subscript(i: Int) -> Int {

return items[i]

}
El IntStack tipo implementa los tres de la Container requisitos del protocolo, y
en cada caso envuelve parte del IntStack funcionalidad existente de tipo para
satisfacer estos requisitos.
Adems, IntStack especifica que para esta implementacin de contenedores , la
apropiada ItemType a utilizar es un tipo de Int . La definicin de typealias
ItemType = Int convierte el tipo abstracto de ItemType en un tipo concreto
de Int para esta aplicacin de la Container protocolo.
Gracias a la inferencia de tipos de Swift, que en realidad no necesita declarar un
hormign ItemType de Intcomo parte de la definicin
de IntStack . Debido IntStack cumple con todos los requisitos de
la Containerprotocolo, Swift se puede inferir la adecuada ItemType de usar,
simplemente mirando el tipo de la anexin del mtodo de elemento de parmetros
y el tipo de retorno del subndice. De hecho, si elimina las typealias ItemType
= Int lnea del cdigo anterior, todo sigue funcionando, porque est claro qu tipo se
debe utilizar para ItemType .
Tambin puede hacer que el genrico Pila tipo se ajusta a la Container protocolo:

struct Stack<T>: Container {

// Pila <T> implementacin original


261

var items = [T]()

mutating func push(item: T) {

items.append(item)

mutating func pop() -> T {

return items.removeLast()

// La conformidad con el protocolo de contenedores

mutating func append(item: T) {

self.push(item)

var count: Int {

return items.count

subscript(i: Int) -> T {

return items[i]

}
Esta vez, el parmetro de tipo de marcador de posicin T se utiliza como el tipo de
la anexin del mtodo deelemento de parmetros y el tipo de retorno del
subndice. Por lo tanto, Swift puede inferir que T es el tipo adecuado para utilizar como
el ItemType para este contenedor particular.
La extensin de un tipo existente para especificar un tipo asociado
Puede extender un tipo existente para agregar la conformidad con un protocolo, como se
describe en Adicin de Protocolo de conformidad con una extensin . Esto incluye un
protocolo con un tipo asociado.
De Swift Matriz tipo ya ofrece un append mtodo, un recuento de la propiedad,
y un subndice con un Intndice para recuperar sus elementos. Estas tres capacidades
coinciden con los requisitos de la Containerprotocolo. Esto significa que usted
puede extender la matriz para ajustarse a la Container protocolo simplemente
declarando que la matriz adopta el protocolo. Esto se hace con una extensin vaca,
como se describe en Declarando Adopcin Protocolo con una extensin :

extensin de matriz : Contenedor {}


Existente de matriz append mtodo y el subndice Swift permiten inferir el tipo
apropiado a utilizar paraItemType , al igual que para el genrico Pila tipo
anterior. Despus de definir esta extensin, se puede utilizar
cualquier matriz como de contenedores .
Dnde Clusulas
Tipo de limitaciones, como se describe en Tipo restricciones , permiten definir los
requisitos sobre los parmetros de tipo asociadas a una funcin genrica o tipo.

262

Tambin puede ser til para definir los requisitos para los tipos asociados. Esto se hace
mediante la definicin de dnde clusulas como parte de una lista de parmetros de
tipo. Una clusula where le permite exigir que un tipo asociado se ajusta a un
determinado protocolo, y / o que ciertos parmetros de tipo y tipos asociados a ser el
mismo. Usted escribe una clusula where colocando el donde la palabra clave
inmediatamente despus de la lista de parmetros de tipo, seguido de una o ms
restricciones para los tipos de asociados, y / o una o ms relaciones de igualdad entre los
tipos y tipos asociados.
El ejemplo siguiente define una funcin genrica llamada allItemsMatch , que
comprueba si dos contenedorescasos contienen los mismos elementos en el mismo
orden. La funcin devuelve un valor booleano de true si todos los elementos
coinciden y un valor de falso si no lo hacen.
Los dos contenedores para ser revisadas no tienen que ser del mismo tipo de contenedor
(aunque pueden ser), pero s tiene que mantener el mismo tipo de artculos. Este
requisito se expresa a travs de una combinacin de restricciones de tipo y donde
clusulas:

func allItemsMatch<

C1: Container, C2: Container

where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>

(someContainer: C1, anotherContainer: C2) -> Bool {

// Comprobar que ambos recipientes contienen el mismo


nmero de artculos

if someContainer.count != anotherContainer.count {

return false

// Comprobar cada par de artculos para ver si son


equivalentes

for i in 0..<someContainer.count {

if someContainer[i] != anotherContainer[i] {

return false

// Todos los artculos coinciden, por lo devuelven true

return true

263

}
Esta funcin toma dos argumentos
llamados someContainer y anotherContainer . El someContainer argume
nto es de tipo C1 , y el anotherContainer argumento es de
tipo C2 . Tanto C1 y C2 son parmetros de tipo de marcador de posicin para dos tipos
de contenedores que se determinarn cuando se invoca la funcin.
Lista de parmetros de tipo de la funcin coloca los siguientes requisitos en los dos
parmetros de tipo:
C1 debe ser conforme a la Container protocolo (escrito como C1:
Contenedor ).
C2 tambin debe ajustarse a la Container protocolo (escrito como C2:
Contenedor ).
El ItemType para C1 debe ser el mismo que el ItemType para C2 (escrito
como C1.ItemType == C2.ItemType).
El ItemType para C1 debe ser conforme a la equatable protocolo (escrito
como C1.ItemType: equatable ).
La tercera y cuarta requisitos se definen como parte de una clusula en donde, y se
escriben despus de laque la palabra clave como parte de la lista de parmetros de tipo
de la funcin.
Estos requisitos se refiere a:
someContainer es un contenedor de tipo C1 .
anotherContainer es un contenedor de tipo C2 .
someContainer y anotherContainer contienen el mismo tipo de artculos.
Los artculos en someContainer se puede comprobar con el operador no igual
( ! = ) para ver si son diferentes unos de otros.
La tercera y cuarta requisitos combinan el sentido de que los artculos
en anotherContainer pueden tambinser revisados con el ! = operador, porque
son exactamente del mismo tipo que los elementos desomeContainer .
Estos requisitos permiten la allItemsMatch funcin para comparar los dos
contenedores, incluso si son de un tipo de contenedor diferente.
El allItemsMatch funcin inicia mediante la comprobacin de que ambos
recipientes contienen el mismo nmero de elementos. Si contienen un nmero diferente
de elementos, no hay manera de que puedan coincidir, y la funcin devuelve falso .
Despus de hacer esta comprobacin, las iteraciones de la funcin ms de todos los
artculos ensomeContainer con un para - en bucle y el operador de rango medio
abierta ( .. < ). Para cada elemento, la funcin comprueba si el elemento
de someContainer no es igual a la partida correspondiente
enanotherContainer . Si los dos artculos no son iguales, entonces los dos
contenedores no coinciden, y la funcin devuelve false .
Si el bucle termina sin encontrar una falta de coincidencia, los dos contenedores
coinciden, y la funcin devuelve verdadero .
He aqu cmo la allItemsMatch funcin se ve en accin:

stackOfStrings.push("uno")

stackOfStrings.push("dos")

stackOfStrings.push("tres")
264

var arrayOfStrings = ["uno", "dos", "tres"]

if allItemsMatch(stackOfStrings, arrayOfStrings) {

println("All items match.")

} else {

println("Not all items match.")

// imprime "Todos los artculos coinciden".


El ejemplo anterior crea una pila instancia para almacenar de Cuerda valores, y
empuja tres cadenas en la pila. El ejemplo tambin crea una matriz instancia
inicializada con un literal de matriz que contiene los mismos tres cadenas como la
pila. A pesar de que la pila y la matriz son de un tipo diferente, ambos se ajustan a
la Container protocolo, y ambos contienen el mismo tipo de valores. Por tanto,
puede llamar a laallItemsMatch funcin con estos dos recipientes como sus
argumentos. En el ejemplo anterior, elallItemsMatch funcin informa
correctamente que todos los elementos de los dos contenedores coinciden.


Control de Acceso
Control de acceso restringe el acceso a las partes de su cdigo de cdigo en otros
archivos de origen y mdulos. Esta funcin le permite ocultar los detalles de
implementacin de su cdigo, y para especificar una interfaz preferida a travs del cual
se puede acceder a ese cdigo y utiliza.
Puede asignar niveles especficos de acceso a los distintos tipos (clases, estructuras,
enumeraciones y), as como a las propiedades, mtodos, inicializadores y subndices
que pertenecen a esos tipos. Los protocolos pueden ser restringidas a un determinado
contexto, como puede globales constantes, variables y funciones.
Adems de ofrecer varios niveles de control de acceso, Swift reduce la necesidad de
especificar los niveles de control de acceso explcitas al proporcionar niveles de acceso
por defecto para los escenarios tpicos. De hecho, si usted est escribiendo una
aplicacin de un solo objetivo, es posible que no tenga que especificar los niveles de
control de acceso explcitas en absoluto.
NOTA
Los diversos aspectos de su cdigo que pueden tener el control de acceso que se les
aplican (propiedades, tipos, funciones, y as sucesivamente) se denominan "entidades"
en las siguientes secciones, por razones de brevedad.
Los mdulos y archivos de origen
Modelo de control de acceso de Swift se basa en el concepto de mdulos y archivos de
origen.

265

Un mdulo es una unidad de cdigo de distribucin-un marco o aplicacin que se crea y


se envan como una sola entidad y que pueden ser importados por otro mdulo con
Swift importacin palabra clave.
Cada tipo de generacin (por ejemplo, un paquete de aplicacin o marco) en Xcode se
trata como un mdulo separado en Swift. Si se agrupan los aspectos del cdigo de su
aplicacin como una continuacin-aplicaciones todo autnomo marco-tal vez para
encapsular y reutilizar ese cdigo a travs de mltiples definir dentro de ese marco ser
parte de un mdulo separado cuando se importa y se utiliza dentro de una aplicacin , o
cuando se utiliza dentro de otro marco.
Un archivo de cdigo fuente es un solo archivo Swift cdigo fuente dentro de un
mdulo (en efecto, un solo archivo dentro de una aplicacin o marco). Aunque es
comn para definir los distintos tipos de archivos de origen independientes, un solo
archivo fuente puede contener definiciones para varios tipos, funciones, y as
sucesivamente.
Niveles de acceso
Swift ofrece tres diferentes niveles de acceso para las entidades dentro de su
cdigo. Estos niveles de acceso son en relacin con el archivo de origen en el que se
define una entidad, y tambin en relacin con el mdulo que pertenece al archivo
fuente.
El acceso pblico permite a las entidades a utilizar dentro de cualquier archivo de
origen de su mdulo que defina, y tambin en un archivo de origen de otro mdulo
que importa el mdulo que defina.Normalmente se utiliza el acceso del pblico al
especificar la interfaz pblica de un marco.
El acceso interno permite a las entidades que deben utilizarse dentro de cualquier
archivo de origen de su mdulo que defina, pero no en cualquier archivo fuente
externa de ese mdulo. Normalmente se utiliza el acceso interno al definir una
aplicacin o de la estructura interna de un marco.
Acceso privado restringe el uso de una entidad para su propio archivo de origen que
define. Utilice el acceso privado a ocultar los detalles de implementacin de una
parte especfica de la funcionalidad.
El acceso del pblico es el ms alto nivel de acceso (menos restrictivo) y acceso privado
es el ms bajo (o ms restrictivo) el nivel de acceso.
Principio Rector de Niveles de Acceso
Los niveles de acceso en Swift siguen un principio rector general: Ninguna entidad
puede ser definido en trminos de otra entidad que tenga un (ms restrictiva) nivel de
acceso inferior.
Por ejemplo:
Una variable pblica no puede ser definido como tener un tipo interno o privado,
porque el tipo puede no estar disponible en todas partes que se utiliza la variable
pblica.
Una funcin no puede tener un nivel de acceso ms alto que sus tipos de parmetros
y el tipo de retorno, porque la funcin podra ser utilizada en situaciones en las que
sus tipos de constituyentes no estn disponibles para el cdigo circundante.

266

Las implicaciones concretas de este principio rector para diferentes aspectos de la


lengua estn cubiertos en detalle a continuacin.
Los niveles de acceso predeterminados
Todas las entidades en su cdigo (con algunas excepciones especficas, como se
describe ms adelante en este captulo) tienen un nivel de acceso predeterminado de
interior si no se especifica un nivel de acceso explcito a ti mismo. Como resultado, en
muchos casos no es necesario especificar un nivel de acceso explcita en el cdigo.
Niveles de acceso para aplicaciones individuales-objetivo
Cuando se escribe una sencilla aplicacin a un solo objetivo, el cdigo en su aplicacin
suele ser auto-contenida dentro de la aplicacin y no necesita ser hecho disponible fuera
de mdulo de la aplicacin. El nivel de acceso predeterminado de interior ya coincide
con este requisito. Por lo tanto, no es necesario especificar un nivel de acceso
personalizado. Es posible, sin embargo, querer marcar algunas partes de su cdigo como
privado, a fin de ocultar sus detalles de implementacin de otro cdigo dentro del
mdulo de la aplicacin.
Niveles de acceso para los Marcos
Al desarrollar un marco, marque la interfaz de cara al pblico para ese marco lo pblico,
por lo que se puede ver y acceder a otros mdulos, como por ejemplo una aplicacin
que importa el marco. Esta interfaz pblica-frente es la interfaz de programacin de
aplicaciones (o API) para el marco.
NOTA
Cualquier detalle de implementacin internos de su marco pueden seguir utilizando el
nivel de acceso por defecto de internos, o pueden ser marcados como privados si desea
ocultar los de otras partes del cdigo interno del marco. Es necesario para marcar una
entidad como pblico slo si desea que se convierta en parte de la API de su marco.
Sintaxis de Control de Acceso
Defina el nivel de acceso de una entidad mediante la colocacin de uno de
los pblicos , internos o privadosmodificadores antes introductor de la
entidad:

public class SomePublicClass {}

internal class SomeInternalClass {}

private class SomePrivateClass {}

public var somePublicVariable = 0

internal let someInternalConstant = 0

private func somePrivateFunction() {}


A menos que se especifique lo contrario, el nivel de acceso por defecto es interna, como
se describe en los niveles de acceso predeterminados . Esto significa
que SomeInternalClass y someInternalConstant pueden ser escrito sin un
modificador de nivel de acceso explcita, y seguirn teniendo un nivel de acceso de
interior:

267

class SomeInternalClass {} // implicitly internal

var someInternalConstant = 0 // implicitly internal


Tipos personalizados
Si desea especificar un nivel de acceso explcito a un tipo personalizado, que lo hagan
en el punto que defina el tipo. El nuevo tipo puede ser utilizada siempre que sea sus
permisos de nivel de acceso. Por ejemplo, si se define una clase privada, esa clase slo
se puede utilizar como el tipo de una propiedad, o como un parmetro de funcin o tipo
de retorno, en el archivo de origen en el que se define la clase privada.
El nivel de control de acceso de un tipo tambin afecta el nivel de acceso
predeterminado del tipo de que los miembros (sus propiedades, mtodos inicializadores
y subndices). Si se define el nivel de acceso de un tipo como privado, el nivel de acceso
por defecto de sus miembros tambin ser privado. Si se define el nivel de acceso de un
tipo como interna o pblica (o utiliza el nivel de acceso por defecto de internos sin
especificar un nivel de acceso de forma explcita), el nivel de acceso predeterminado de
los miembros del tipo ser interna.
NOTA
Como se mencion anteriormente, un tipo por defecto pblicos a tener miembros
internos, no miembros pblicos. Si quieres un miembro de tipo de ser pblica, debe
marcar explcitamente como tal. Este requisito garantiza que la API de cara al pblico
para un tipo es algo que se opta en la publicacin, y evita la presentacin de los trabajos
internos de un tipo como API pblica por error.

public class SomePublicClass { // explicitly public class

public var somePublicProperty = 0 // explicitly public class member

var someInternalProperty = 0 // implicitly internal class member

private func somePrivateMethod() {} // explicitly private class member

class SomeInternalClass { // implicitly internal class

var someInternalProperty = 0 // implicitly internal class member

private func somePrivateMethod() {} // explicitly private class member

private class SomePrivateClass { // explicitly private class

var somePrivateProperty = 0 // implicitly private class member

func somePrivateMethod() {} // implicitly private class member

Tipos Tuple
El nivel de acceso de un tipo tupla es el nivel de acceso ms restrictivo de los tipos
utilizados en esa tupla.Por ejemplo, si el usuario crea una tupla de dos tipos diferentes,

268

uno con acceso interno y otro con acceso privado, el nivel de acceso para ese tipo tupla
compuesto ser privada.
NOTA
Tipos de tupla no tienen una definicin independiente de la forma en que las clases,
estructuras, enumeraciones y funciones hacen. Nivel de acceso de un tipo tupla se
deduce automticamente cuando se utiliza el tipo de tupla, y no se puede especificar de
forma explcita.
Tipos de funciones
El nivel de acceso para un tipo de funcin se calcula como el nivel de acceso ms
restrictivo de tipos de parmetros de la funcin y el tipo de retorno. Debe especificar el
nivel de acceso de forma explcita como parte de la definicin de la funcin, si el nivel
de acceso de la funcin calculada no coincide con el valor por defecto contextual.
El ejemplo siguiente define una funcin global llamada algunaFuncion , sin
proporcionar un modificador especfico nivel de acceso para la funcin en s. Se podra
esperar que esta funcin tiene el nivel de acceso predeterminado de "interno", pero este
no es el caso. De hecho, algunaFuncion no recogera como est escrito a
continuacin:

func someFunction() -> (SomeInternalClass, SomePrivateClass) {

// Implementacin de la funcin va aqu

}
Tipo de retorno de la funcin es un tipo tupla compuesta a partir de dos de las clases
personalizadas definidas anteriormente en Tipos personalizados . Una de estas clases se
defini como "interno", y el otro se defini como "privado". Por lo tanto, el nivel de
acceso general de la tupla tipo compuesto es (el nivel de acceso mnimo de tipos de
constituyentes de la tupla) "privado".
Debido a que el tipo de retorno de la funcin es privada, debe marcar el nivel de acceso
general de la funcin con el privado modificador para la declaracin de la funcin de
ser vlida:

private func someFunction() -> (SomeInternalClass, SomePrivateClass) {

// Implementacin de la funcin va aqu

}
No es vlido para marcar la definicin de algunaFuncion con
los pblicos o internos modificadores, o para utilizar la configuracin por
defecto de internos, ya que los usuarios pblicos o internos de la funcin podra no tener
acceso adecuado a la clase privada usada en el tipo de retorno de la funcin.
Tipos de enumeracin
Los casos individuales de una enumeracin automticamente reciben el mismo nivel de
acceso como la enumeracin que pertenecen. No se puede especificar un nivel de acceso
diferente para casos de enumeracin individuales.
En el siguiente ejemplo, el CompassPoint enumeracin tiene un nivel de acceso
explcita de "pblico". Los casos de enumeracin del
Norte , Sur , Este y Oeste , por tanto, tambin tienen un nivel de acceso de
"pblico":

269

public enum CompassPoint {

case North

case South

case East

case West

}
Valores primas y valores asociados
Los tipos utilizados para cualquier valor primas o valores asociados en una definicin
de enumeracin deben tener un nivel de acceso por lo menos tan alto como nivel de
acceso de la enumeracin. No puede utilizar unprivado tipo que el tipo de valor en
bruto de una enumeracin con un interno de nivel de acceso, por ejemplo.
Tipos anidados
Tipos anidados definidos dentro de un tipo privado tienen un nivel de acceso automtico
de los privados.Tipos anidados definidos dentro de un tipo de pblico o un tipo interno
tienen un nivel de acceso automtico de los internos. Si quieres un tipo anidado dentro
de un tipo de pblico que est disponible pblicamente, debe declarar explcitamente el
tipo anidado como pblico.
Subclassing
Usted puede crear una subclase de cualquier clase que se puede acceder en el contexto
de acceso actual.Una subclase no puede tener un nivel de acceso ms alto que su
ejemplo superclase-para, usted no puede escribir una subclase de una superclase pblica
interna.
Adems, puede invalidar cualquier miembro de la clase (mtodo, propiedad,
inicializador, o subndice) que es visible en un contexto de acceso seguro.
Una anulacin puede hacer un miembro de la clase heredada ms accesible que su
versin de la superclase.En el siguiente ejemplo, la clase A es una clase pblica con un
mtodo privado llamado someMethod. Clase Bes una subclase de A , con un nivel de
acceso reducido de "interno". Sin embargo, la clase B proporciona una anulacin
de someMethod con un nivel de acceso de "interno", que es ms alta que la
implementacin original de someMethod:

public class A {

private func someMethod() {}

internal class B: A {

override internal func someMethod() {}

}
Incluso es vlido para un miembro de la subclase llamar a un miembro de la superclase
que tiene permisos de acceso ms bajos que el miembro de la subclase, siempre y

270

cuando la llamada a miembro de la superclase tiene lugar dentro de un contexto de nivel


de acceso permitido (es decir, dentro del mismo archivo de origen como la superclase
para una llamada de miembro privado, o dentro del mismo mdulo que la superclase
para una llamada miembro interno):

public class A {

private func someMethod() {}

internal class B: A {

override internal func someMethod() {

super.someMethod()

}
Debido superclase A y subclase B se definen en el mismo archivo fuente, es vlido para
el B implementacin de someMethod llamar super.someMethod () .
Constantes, variables, propiedades, y subndices
Una constante, variable o la propiedad no puede ser ms pblico que su tipo. No es
vlido para escribir una propiedad pblica con un tipo privado, por ejemplo. Del mismo
modo, un subndice no puede ser ms pblico que sea su tipo de ndice o tipo de
retorno.
Si una constante, variable, propiedad, o subndice hace uso de un tipo privado, la
constante, variable, propiedad, o subndice debe tambin ser marcado como privado :

private var privateInstance = SomePrivateClass()

Captadores y definidores
Getters y setters para las constantes, variables, propiedades y subndices
automticamente reciben el mismo nivel de acceso como la constante, variable,
propiedad, o subndice que pertenecen.
Usted puede dar un setter un menor nivel de acceso de su correspondiente captador,
para restringir el alcance de lectura-escritura de esa variable, propiedad o subndice. Se
asigna un nivel de acceso ms bajo escribiendo privado (set) o interna
(set) antes de la var o subndice introductor.
NOTA
Esta regla se aplica a las propiedades almacenados, as como propiedades calculadas. A
pesar de que usted no escribe un captador explcito y setter para una propiedad
almacenada, Swift todava sintetiza un captador implcita y setter para que usted
proporcione el acceso al almacenamiento de respaldo de la propiedad
almacenada. Utilice privado (set) y interior (set) para cambiar el nivel de
acceso de este organismo sintetiza exactamente de la misma manera que para un setter
explcita en una propiedad calculada.
El ejemplo siguiente define una estructura llamada TrackedString , que mantiene
un registro del nmero de veces que una propiedad de cadena se modifica:

271

struct TrackedString {

private(set) var numberOfEdits = 0

var value: String = "" {

didSet {

numberOfEdits++

}
El TrackedString estructura define una propiedad de cadena almacenado
llamado valor , con un valor inicial de "" (una cadena vaca). La estructura tambin
define una propiedad de entero almacenado llamadonumberOfEdits , que se utiliza
para realizar el seguimiento del nmero de veces que el valor se modifica. Este
seguimiento modificacin se lleva a cabo con un didSet observador propiedad en
el valor de la propiedad, que se incrementa numberOfEdits cada vez que
el valor de la propiedad se establece en un nuevo valor.
El TrackedString estructura y el valor de la propiedad no proporcionan un
modificador explcito nivel de acceso, por lo que ambos reciben el nivel de acceso por
defecto de internos. Sin embargo, el nivel de acceso para
el numberOfEdits propiedad est marcada con un (juego)
privado modificador para indicar que la propiedad debe ser ajustable slo desde
dentro del mismo archivo fuente que la TrackedString definicin de
estructura. Getter de la propiedad todava tiene el nivel de acceso por defecto de
internos, pero su organismo es ahora privado a la fuente en la que TrackedString se
define. Esto permite TrackedString modificar elnumberOfEdits propiedad
internamente, sino para presentar la propiedad como una propiedad de slo lectura
cuando es utilizado por otros archivos de cdigo fuente en el mismo mdulo.
Si crea una TrackedString instancia y modificar su valor de cadena un par de
veces, se puede ver elnumberOfEdits actualizacin valor de la propiedad para que
coincida con el nmero de modificaciones:

var stringToEdit = TrackedString()

stringToEdit.value = "This string will be tracked."

stringToEdit.value += " This edit will increment numberOfEdits."

stringToEdit.value += " So will this one."

println("The number of edits is \(stringToEdit.numberOfEdits)")

// imprime "El nmero de ediciones es de 3"


Aunque se puede consultar el valor actual de la numberOfEdits propiedad desde
otro archivo de origen, no se puede modificar la propiedad de otro archivo de
origen. Esta restriccin protege los detalles de implementacin de
la TrackedString funcionalidad de edicin de seguimiento, sin dejar de ofrecer
acceso conveniente a un aspecto de esa funcionalidad.
Tenga en cuenta que puede asignar un nivel de acceso explcito a la vez un getter y un
setter si es necesario.El siguiente ejemplo muestra una versin de

272

la TrackedString estructura en la que la estructura se define con un nivel de acceso


explcita de pblico. Los miembros de la estructura (incluyendo
la numberOfEditspropiedad), por tanto, tienen un nivel de acceso interno por
defecto. Usted puede hacer de la estructuranumberOfEdits pblica getter de la
propiedad, y su setter propiedad privada, mediante la combinacin de
lospblicos y privados (juego) modificadores de nivel de acceso:

public struct TrackedString {

public private(set) var numberOfEdits = 0

public var value: String = "" {

didSet {

numberOfEdits++

public init() {}

Inicializadores
Inicializadores personalizados se pueden asignar un nivel de acceso inferior o igual al
tipo que inicializar. La nica excepcin es para los inicializadores requeridos (segn se
define en Inicializadores requeridos ). Un inicializador requerido debe tener el mismo
nivel de acceso como la clase a la que pertenece.
Al igual que con los parmetros de funcin y de mtodo, los tipos de los parmetros de
un inicializador no pueden ser ms privado que el propio nivel de acceso del
inicializador.
Inicializadores defecto
Swift proporciona un inicializador por defecto sin ningn argumento para cualquier
estructura o base clase que proporciona valores predeterminados para todas sus
propiedades y no proporciona al menos un inicializador de s mismo. Este inicializador
por defecto se describe en Inicializadores predeterminados . El inicializador por defecto
tiene el mismo nivel de acceso como el tipo se inicializa.
NOTA
Para un tipo que se define como pblica , el inicializador por defecto se considera
interna. Si desea un tipo pblico sea initializable con un inicializador sin argumentos
cuando se usa en otro mdulo, debe proporcionar a un pblico sin argumentos
inicializador ti mismo como parte de la definicin del tipo.
Por defecto miembro por miembro Inicializadores de Estructura Tipos
El inicializador de miembro por miembro predeterminado para un tipo de estructura se
considera privada si alguna de las propiedades almacenados de la estructura son
privados. De lo contrario, el inicializador tiene un nivel de acceso de interior.
Al igual que con el inicializador por defecto de arriba, si quieres un tipo de estructura
pblica sea initializable con un inicializador de miembro por miembro cuando se usa en

273

otro mdulo, debe proporcionar un miembro por miembro pblica inicializador a s


mismo como parte de la definicin del tipo.
Protocolos
Si desea asignar un nivel de acceso explcito a un tipo de protocolo, que lo hagan en el
punto que defina el protocolo. Esto le permite crear protocolos que slo pueden ser
adoptadas dentro de un contexto de acceso seguro.
El nivel de acceso de cada requisito dentro de una definicin de protocolo se establece
automticamente en el mismo nivel de acceso como el protocolo. No se puede
establecer un requisito de protocolo a un nivel de acceso diferente que el protocolo que
soporta. Esto asegura que todos los requisitos del protocolo sern visibles en cualquier
tipo que adopta el protocolo.
NOTA
Si define un protocolo pblico, los requisitos del protocolo requieren un nivel de acceso
pblico a dichos requisitos cuando se implementan. Este comportamiento es diferente
de otros tipos, en una definicin de tipo pblico implica un nivel de acceso del interno
para los miembros del tipo.
Protocolo de Herencia
Si define un nuevo protocolo que se hereda de un protocolo existente, el nuevo
protocolo puede tener como mximo el mismo nivel de acceso como el protocolo
hereda de. No se puede escribir un protocolo pblico que hereda de un protocolo
interno, por ejemplo.
Protocolo de Conformidad
Un tipo puede ajustarse a un protocolo con un nivel de acceso ms bajo que el propio
tipo. Por ejemplo, puede definir un tipo de pblico que puede ser utilizado en otros
mdulos, pero cuya conformidad con un protocolo interno slo se puede utilizar dentro
de la definicin de mdulo del protocolo interno.
El contexto en el que un tipo se ajusta a un protocolo en particular es el mnimo de nivel
de acceso del tipo y el nivel de acceso del protocolo. Si un tipo es pblica, sino un
protocolo que se ajusta a es interno, la conformidad del tipo a que el protocolo tambin
es interna.
Cuando se escribe o ampliar un tipo de ajustarse a un protocolo, debe asegurarse de que
la aplicacin del tipo de cada requisito protocolo tiene como mnimo el mismo nivel de
acceso como la conformidad del tipo con ese protocolo. Por ejemplo, si un tipo de
pblico se ajusta a un protocolo interno, la aplicacin del tipo de cada requisito de
protocolo debe ser por lo menos "interna".
NOTA
En Swift, como en Objective-C, de conformidad protocolo es global-no es posible para
un tipo de ajustarse a un protocolo de dos maneras diferentes dentro del mismo
programa.
Extensiones
Puede ampliar una clase, estructura o enumeracin en cualquier contexto en el que el
acceso a la clase, estructura o enumeracin disponible. Cualquier tipo de miembros

274

agregaron en una extensin tiene el mismo nivel de acceso predeterminado como


miembros de tipo declarados en el modelo original est extendiendo.Por ejemplo, si
ampla un tipo de pblico, los nuevos miembros de tipo que agregue tendrn un nivel de
acceso predeterminado de interior.
Alternativamente, usted puede marcar una extensin con un modificador explcito nivel
de acceso (por ejemplo, extensin privada ) para establecer un nuevo nivel de
acceso por defecto para todos los miembros definidos dentro de la extensin. Este
nuevo valor predeterminado an se puede anular dentro de la extensin para miembros
individuales.
Adicin de Protocolo de conformidad con una extensin
No se puede proporcionar un modificador explcito nivel de acceso para una extensin
si est usando esa extensin para agregar conformidad protocolo. En cambio, el propio
nivel de acceso del protocolo se utiliza para proporcionar el nivel de acceso
predeterminado para cada aplicacin el requisito de protocolo dentro de la extensin.
Genricos
El nivel de acceso de un tipo genrico o funcin genrica es el mnimo del nivel de
acceso del tipo genrico o de la funcin en s y el nivel de acceso de las restricciones de
tipo de sus parmetros de tipo.
Tipo de los nombres
Cualquier alias de tipo que defina se consideran como tipos distintos a efectos de
control de acceso. Un alias de tipo puede tener un nivel de acceso de menos de o igual
al nivel de acceso del tipo que alias. Por ejemplo, un tipo de alias privado puede crear
un alias para un tipo privado, interno o pblico, sino un tipo de alias pblico no puede
crear un alias para un tipo interno o privado.
NOTA
Esta regla tambin se aplica a escribir alias para tipos asociados que se utilizan para
satisfacer las conformidades de protocolo.

Operadores avanzados
Adems de los operadores descritos en operadores bsicos , Swift proporciona varios
operadores avanzados que realizan la manipulacin valor ms complejo. Estos incluyen
todos los operadores de bits y bits cambiando usted estar familiarizado con de C y
Objective-C.
A diferencia de los operadores aritmticos en C, los operadores aritmticos en Swift no
hacen desbordamiento por defecto. Comportamiento de desbordamiento es atrapado y
se expresa como un error.Para optar a desbordarse comportamiento, utilice el segundo
conjunto de operadores aritmticos de Swift que se desbordan por defecto, como el
operador de suma desbordamiento ( y + ). Todos estos operadores desbordamiento
comienzan con un signo ( y ).
Al definir sus propias estructuras, clases y enumeraciones, que puede ser til para
proporcionar sus propias implementaciones de los operadores Swift estndar para este

275

tipo de encargo. Swift hace que sea fcil para proporcionar implementaciones a medida
de estos operadores y para determinar exactamente lo que su comportamiento debe ser
para cada tipo que cree.
Usted no est limitado a los operadores predefinidos. Swift le da la libertad para definir
sus propios operadores infijo costumbre, prefijos, Postfix, y de asignacin, con valores
de precedencia y asociatividad personalizado. Estos operadores se pueden utilizar y
adoptaron en su cdigo como cualquiera de los operadores predefinidos, e incluso se
puede extender los tipos existentes para apoyar a los operadores de encargo que usted
defina.
Operadores a nivel de bit
Operadores bit a bit le permiten manipular los bits de datos en bruto individuales dentro
de una estructura de datos. A menudo se utilizan en la programacin de bajo nivel, tales
como la programacin de grficos y la creacin de controlador de
dispositivo. Operadores bit a bit tambin pueden ser tiles cuando se trabaja con datos
en bruto procedentes de fuentes externas, como los datos de codificacin y
decodificacin de la comunicacin a travs de un protocolo personalizado.
Swift es compatible con todos los operadores de bits que se encuentran en C, tal como
se describe a continuacin.
A nivel de bit del operador NO
El nivel de bit NO operador ( ~ ) invierte todos los bits en un nmero:


El nivel de bit NO es un operador prefijo, y aparece inmediatamente antes del valor que
opera en, sin ningn espacio en blanco:

let initialBits: UInt8 = 0b00001111

let invertedBits = ~initialBits // equals 11110000


Uint8 enteros tienen ocho bits y puede almacenar cualquier valor entre 0 y 255 . Este
ejemplo inicializa unaUint8 entero con el valor binario 00001111 , que tiene sus
primeros cuatro bits puestos a 0 , y sus segundos cuatro bits se establece en 1 . Esto es
equivalente a un valor decimal de 15 .
El bit a bit NO operador se utiliza a continuacin para crear una nueva constante
llamada invertedBits , que es igual a initialBits , pero con todos los bits
invertidos. Ceros conviertan, y los convierten en ceros. El valor
de invertedBits es 11110000 , que es igual a un valor decimal sin signo de 240 .
Operador AND
El operador AND ( Y ) combina los bits de dos nmeros. Devuelve un nuevo nmero
cuyos bits se establecen en 1 slo si los bits son iguales a 1 en ambos nmeros de
entrada:

276


En el siguiente ejemplo, los valores de firstSixBits y lastSixBits ambos
tienen cuatro bits medias iguales a 1. El operador AND los combina para hacer el
nmero 00111100 , que es igual a un valor decimal sin signo de60 :

let firstSixBits: UInt8 = 0b11111100

let lastSixBits: UInt8 = 0b00111111

let middleFourBits = firstSixBits & lastSixBits // equals 00111100

Operador binario OR
El operador binario OR ( | ) compara los bits de dos nmeros. El operador devuelve un
nuevo nmero cuyos bits se ponen a 1 si los bits son iguales a 1 , en tanto el nmero de
entrada:


En el siguiente ejemplo, los valores de someBits y moreBits tienen diferentes bits
puestos a 1 . El operador binario OR los combina para hacer el nmero 11111110 , lo
que equivale a un decimal sin signo de 254 :

let someBits: UInt8 = 0b10110010

let moreBits: UInt8 = 0b01011110

let combinedbits = someBits | moreBits // equals 11111110

XOR Operador
El operador XOR bit a bit , o "operador O exclusivo" ( ^ ), compara los bits de dos
nmeros. El operador devuelve un nuevo nmero cuyos bits se ponen a 1 , donde los

277

bits de entrada son diferentes y estn ajustados a 0 , donde los bits de entrada son los
mismos:


En el siguiente ejemplo, los valores de firstBits y otherBits tienen cada uno un
conjunto de bits a 1 en un lugar que el otro no. El operador XOR bit a bit establece
estos dos bits a 1 en su valor de salida. Todos los otros bits
en firstBits y otherBits partido y se ponen a 0 en el valor de salida:

let firstBits: UInt8 = 0b00010100

let otherBits: UInt8 = 0b00000101

let outputBits = firstBits ^ otherBits // equals 00010001

Izquierda en modo bit y Operadores de desplazamiento a la derecha


La izquierda en modo bit operador de desplazamiento ( << ) y en modo bit operador de
desplazamiento a la derecha ( >> ) se mueven todos los bits de un nmero a la
izquierda o la derecha por un nmero determinado de plazas, de acuerdo con las reglas
definidas a continuacin.
Bit a bit a la izquierda y desplazamientos a la derecha tener el efecto de multiplicar o
dividir un nmero entero en un factor de dos. Cambiando los bits de un entero a la
izquierda por una posicin duplica su valor, mientras que el cambio hacia la derecha por
una posicin mitades su valor.
El cambio de comportamiento para Unsigned enteros
El comportamiento de desplazamiento de bits de enteros sin signo es la siguiente:
1. Los bits existentes se desplazan hacia la izquierda o hacia la derecha por el nmero
solicitado de lugares.
2. Todos los bits que se mueven ms all de los lmites de almacenamiento del nmero
entero se descartan.
3. Los ceros se insertan en los espacios que quedan despus de los bits originales se
mueven a la izquierda oa la derecha.
Este enfoque es conocido como un desplazamiento lgico .
La siguiente ilustracin muestra los resultados de 11111111 << 1 (que
es 11111111 movido a la izquierda por 1lugar), y 11111111 >> 1 (que
es 11111111 desplaza a la derecha por 1 lugar). Nmeros azules se desplazan,
nmeros grises se descartan, y se insertan ceros naranja:

278


As es como se ve poco cambio en el cdigo Swift:

let shiftBits: UInt8 = 4 // 00000100 in binary

shiftBits << 1 // 00001000

shiftBits << 2 // 00010000

shiftBits << 5 // 10000000

shiftBits << 6 // 00000000

shiftBits >> 2 // 00000001


Usted puede utilizar el desplazamiento de bits para codificar y decodificar los valores
dentro de otros tipos de datos:

let pink: UInt32 = 0xCC6699

let redComponent = (pink & 0xFF0000) >> 16 // redComponent is 0xCC, or 204

let greenComponent = (pink & 0x00FF00) >> 8 // greenComponent is 0x66, or 102

let blueComponent = pink & 0x0000FF // blueComponent is 0x99, or 153


Este ejemplo utiliza un UInt32 constante llamada rosa para almacenar un valor de
color Hojas de estilo en cascada para el color rosa. El color CSS valor # CC6699 se
escribe como 0xCC6699 en representacin nmero hexadecimal de Swift. Este color
se descompone luego en su color rojo ( CC ), verde ( 66 ), y azul ( 99 ) componentes
por el operador AND ( Y ) y el operador de desplazamiento a la derecha en modo bit
( >> ).
El componente rojo se obtiene mediante la realizacin de un AND bit a bit entre los
nmeros 0xCC6699 y0xff0000 . Los ceros en 0xFF0000 efectivamente "mscara"
el segundo y tercer bytes de 0xCC6699 , haciendo que el 6699 para ser ignorados y
dejando 0xCC0000 como el resultado.
Este nmero es entonces desplazado 16 lugares a la derecha ( >> 16 ). Cada par de
caracteres en un nmero hexadecimal utiliza 8 bits, por lo que un movimiento de 16
lugares a la derecha convertir 0xCC0000 en0x0000CC . Este es el mismo
que 0xCC , que tiene un valor decimal de 204 .
Del mismo modo, el componente verde se obtiene mediante la realizacin de un AND
bit a bit entre los nmeros 0xCC6699 y 0x00FF00 , lo que da un valor de salida
de 0x006600 . Este valor de salida es entonces desplazado ocho lugares a la derecha,
dando un valor de 0x66 , que tiene un valor decimal de 102 .
Finalmente, el componente azul se obtiene mediante la realizacin de un AND bit a bit
entre los nmeros0xCC6699 y 0x0000FF , lo que da un valor de salida
de 0x000099 . No hay necesidad de cambiar esto a la derecha, como 0x000099 ya
es igual a 0x99 , que tiene un valor decimal de 153 .

279

El cambio de comportamiento para los enteros con signo


El comportamiento de desplazamiento es ms complejo para enteros con signo que para
los enteros sin signo, debido a la forma enteros con signo se representan en
binario. (Los ejemplos siguientes se basan en 8 bits enteros con signo de simplicidad,
pero los mismos principios se aplican para los enteros con signo de cualquier tamao.)
Los enteros con signo utilizan su primer bit (conocido como el bit de signo ) para
indicar si el entero es positivo o negativo. Un bit de signo de 0 significa positivo, y un
bit de signo de 1 significa negativo.
Los bits restantes (conocidos como los bits de valor ) almacenan el valor real. Los
nmeros positivos se almacenan exactamente de la misma manera que para enteros sin
signo, contando hacia arriba desde 0 . He aqu cmo los bits dentro de un INT8 buscan
el nmero 4 :


El bit de signo es 0 (lo que significa "positivo"), y los siete bits de valor son slo el
nmero 4 , escrito en notacin binaria.
Los nmeros negativos, sin embargo, se almacenan de manera diferente. Se almacenan
restando su valor absoluto de 2 a la potencia de n , donde n es el nmero de bits de
valor. Un nmero de ocho bits tiene siete bits de valor, por lo que esto significa 2 a la
potencia de 7 , o 128 .
He aqu cmo los bits dentro de un INT8 buscan el nmero -4 :


Esta vez, el bit de signo es 1 (que significa "negativo"), y los siete bits de valor tiene un
valor binario de 124(que es 128-4 ):


La codificacin para los nmeros negativos se conoce como un complemento a dos
de la representacin.Puede parecer una manera inusual para representar nmeros
negativos, pero tiene varias ventajas.
En primer lugar, puede agregar -1 a -4 , basta con realizar una suma binaria estndar
de todos los ocho bits (incluyendo el bit de signo), y descartar cualquier cosa que no
encaja en los ocho bits, una vez que haya terminado:

280


En segundo lugar, la representacin de los dos se complementan tambin le permite
desplazar los bits de los nmeros negativos a la izquierda y la derecha como nmeros
positivos, y an as terminar duplicando ellos por cada turno que realice a la izquierda, o
reducir a la mitad de ellos por cada turno que realice a la derecha . Para lograr esto, se
utiliza una regla adicional cuando enteros con signo se desplazan a la derecha:
Cuando usted cambia enteros con signo a la derecha, se aplican las mismas reglas
que para los enteros sin signo, pero llenar cualquier pedacito vaco de la izquierda
con el bit de signo , en lugar de con un cero.


Esta accin asegura que los nmeros enteros con signo tienen el mismo signo despus
de que se desplazan a la derecha, y se conoce como un desplazamiento aritmtico .
Debido a la forma especial que los nmeros positivos y negativos se almacenan,
cambiando cualquiera de ellos a la derecha los mueve ms cerca de cero. Mantener el
signo mordi la misma durante este cambio significa que los enteros negativos siguen
siendo negativas ya que su valor se acerca a cero.
Operadores de desbordamiento
Si intenta insertar un nmero en una constante entera o variable que no puede contener
ese valor, por defecto Swift informa de un error en lugar de permitir un valor no vlido
que se crear. Este comportamiento da mayor seguridad cuando se trabaja con nmeros
que son demasiado grandes o demasiado pequeas.
Por ejemplo, la Int16 tipo entero puede contener cualquier nmero entero con signo
entre -32768 y 32767 .Tratar de establecer una Int16 constante o variable a un
nmero fuera de este rango produce un error:

var potentialOverflow = Int16.max

// potentialOverflow equals 32767, which is the largest value an Int16 can hold

potentialOverflow += 1

// Esto provoca un error


281

Manipulacin cuando los valores se ponen demasiado grande o demasiado pequeo


error Siempre que da mucha ms flexibilidad a la hora de codificacin para las
condiciones de contorno.
Sin embargo, cuando usted desea especficamente una condicin de desbordamiento
para truncar el nmero de bits disponibles, usted puede optar por este comportamiento
en lugar de desencadenar un error. Swift proporciona cinco aritmticos operadores de
desbordamiento que opten por el comportamiento de desbordamiento para los clculos
de enteros. Estos operadores comienzan con un signo ( Y ):
Adems Overflow ( y + )
Sustraccin de desbordamiento ( y - )
Multiplicacin de desbordamiento ( & * )
Divisin de desbordamiento ( y / )
Resto de desbordamiento ( &% )
Desbordamiento del valor
He aqu un ejemplo de lo que sucede cuando se permite un valor sin signo de
desbordarse, utilizando el operador de suma desbordamiento ( y + ):

var willOverflow = UInt8.max

// WillOverflow es igual a 255, que es el valor ms grande


puede contener un Uint8

willOverflow = willOverflow &+ 1

// WillOverflow es ahora igual a 0


La variable willOverflow se inicializa con el valor ms grande de un Uint8 puede
contener ( 255 , o 11111111 en binario). A continuacin, se incrementa en 1 usando
el operador de suma de desbordamiento ( y + ). Esto empuja a su representacin
binaria poco ms el tamao que un Uint8 puede sostener, provocando que se desborde
ms all de sus lmites, como se muestra en el siguiente diagrama. El valor que se
mantiene dentro de los lmites de la Uint8 despus de la adicin de desbordamiento
es 00000000 , o cero:


Valor Underflow
Los nmeros tambin pueden llegar a ser demasiado pequeo como para caber dentro
de los lmites mximos de su tipo. He aqu un ejemplo.
El menor valor que un Uint8 puede contener es 0 (que es 00 millones en forma
binaria de ocho bits). Si se resta 1 de 00 millones mediante el operador de
sustraccin de desbordamiento, el nmero se desbordar hacia atrs y vuelta
a 11111111 , o 255 en decimal:

282


As es como que se ve en el cdigo Swift:

// willUnderflow equals 0, which is the smallest value a UInt8 can hold

willUnderflow = willUnderflow &- 1

// willUnderflow is now equal to 255


Un desbordamiento similar ocurre para los enteros con signo. Toda la resta de enteros
con signo se realiza como la resta binaria directa, con el bit de signo incluye como parte
de los nmeros que se sustrae, como se describe en la izquierda en modo bit y
Operadores de desplazamiento a la derecha . El nmero ms pequeo que
un INT8 puede sostener es -128 , que es 10000000 en binario. Restando 1 de este
nmero binario con el operador de desbordamiento da un valor binario de 01111111 ,
que alterna el bit de signo y da positivo 127 , el valor positivo ms grande que
un INT8 puede contener:


Aqu est lo mismo en cdigo Swift:

var signedUnderflow = Int8.min

// SignedUnderflow es igual a -128, que es el valor ms


pequeo puede contener un INT8

signedUnderflow = signedUnderflow &- 1

// SignedUnderflow es ahora igual a 127


El resultado final del comportamiento de extracto y refinado descrito anteriormente es
que tanto para los nmeros enteros con y sin signo, desbordamiento siempre da la vuelta
del mayor valor entero vlido de nuevo a la ms pequea, y la corriente de fondo
siempre se envuelve alrededor del valor ms pequeo al ms grande.

283

La divisin por cero


Al dividir un nmero por cero ( i / 0 ), o tratar de calcular resto por cero ( i% 0 ),
provoca un error:

let x = 1

let y = x / 0
Sin embargo, las versiones de desbordamiento de estos operadores ( y / y &% )
devuelven un valor de cero si se divide por cero:

let x = 1

let y = x &/ 0

// Y es igual a 0

Precedencia y asociatividad
Operador precedencia da algunos operadores de mayor prioridad que otras; estos
operadores se aplican primero.
Operador asociatividad define cmo se agrupan los operadores de la misma precedencia
juntos (o asociados) -bien agrupan desde la izquierda, o agrupados por la
derecha. Piense en ello en el sentido de "que asocian con la expresin a su izquierda", o
"que se asocian con la expresin de su derecho."
Es importante tener en cuenta la precedencia y asociatividad de cada operador cuando
se trabaja con el orden en el que se calcula una expresin compuesta. He aqu un
ejemplo. Por qu la siguiente expresin es igual a 4 ?

2 + 3 * 4 % 5

// Esto es igual a 4
Tomado estrictamente de izquierda a derecha, es de esperar que esto se lea como sigue:
2 ms 3 igual a 5;
5 veces 4 es igual a 20;
20 resto 5 es igual a 0
Sin embargo, la respuesta real es 4 , no 0 . Operadores de mayor precedencia se evalan
antes que las de menor precedencia. En Swift, como en C, el operador de multiplicacin
( * ) y el operador de resto ( % ) tienen una mayor precedencia que el operador de suma
( + ). Como resultado, ambos son evaluados antes se considera la adicin.
Sin embargo, la multiplicacin y el resto tienen la misma precedencia que s. Para
calcular el orden de evaluacin exacta de usar, tambin es necesario tener en cuenta su
asociatividad. La multiplicacin y la resta tanto asociado con la expresin a su
izquierda. Piense en esto como la adicin de parntesis implcitos alrededor de estas
partes de la expresin, a partir de su izquierda:
2 + (( 3 * 4 )% 5 )
(3 * 4) es 12 , as que esto es equivalente a:

2 + ( 12 % 5 )
(12% 5) es 2 , as que esto es equivalente a:

2 + 2
Este clculo se obtiene la respuesta final de 4 .

284

Para obtener una lista completa de precedencias operador Swift y reglas de


asociatividad, vea Expresiones .
NOTA
Precedencias operador de Swift y reglas de asociatividad son ms simples y ms
predecible que las que se encuentran en C y Objective-C. Sin embargo, esto significa
que no son los mismos que en lenguajes basados-C. Tenga cuidado para asegurar que
las interacciones del operador an se comportan de la manera que usted piensa cuando
al portar el cdigo existente para Swift.
Funciones del operador
Clases y estructuras pueden proporcionar sus propias implementaciones de los
operadores existentes. Esto se conoce como la sobrecarga de los operadores existentes.
El siguiente ejemplo muestra cmo implementar el operador de suma aritmtica ( + )
para una estructura personalizada. El operador de suma aritmtica es un operador
binario , ya que funciona con dos objetivos y se dice que es infijo porque aparece entre
esos dos objetivos.
El ejemplo define un Vector2D estructura para un vector bidimensional posicin (x,
y) , seguido de una definicin de una funcin de operador para aadir juntos instancias
de la Vector2D estructura:

struct Vector2D {

var x = 0.0, y = 0.0

func + (left: Vector2D, right: Vector2D) -> Vector2D {

return Vector2D(x: left.x + right.x, y: left.y + right.y)

}
La funcin de operador se define como una funcin global con un nombre de funcin
que coincide con el operador para ser sobrecargado ( + ). Debido a que el operador de
suma aritmtica es un operador binario, esta funcin operador toma dos parmetros de
entrada de tipo Vector2D y devuelve un nico valor de salida, tambin de
tipo Vector2D .
En esta aplicacin, los parmetros de entrada se
denominan izquierda y derecha para representar losVector2D instancias que
estarn en el lado izquierdo y el lado derecho de la + operador. La funcin devuelve una
nueva Vector2D ejemplo, cuya x y Y. propiedades se inicializan con la suma de
la x y Y las propiedades de los dos Vector2D casos que se agregan juntos.
La funcin se define a nivel mundial, en lugar de como un mtodo en
el Vector2D estructura, de modo que pueda ser utilizado como un operador infijo
entre existentes Vector2D casos:

let vector = Vector2D(x: 3.0, y: 1.0)

let anotherVector = Vector2D(x: 2.0, y: 4.0)

let combinedVector = vector + anotherVector

// CombinedVector es una instancia de Vector2D con valores


de (5.0, 5.0)

285

Este ejemplo suma los vectores (3.0, 1.0) y (2.0, 4.0) para hacer que el
vector (5.0, 5.0) , como se ilustra a continuacin.


Prefijo y Operadores de Postfix
El ejemplo anterior demuestra una implementacin personalizada de un operador infijo
binario. Clases y estructuras tambin pueden proporcionar implementaciones de los
estndares operadores unarios . Los operadores unarios operan en un solo
objetivo. Son prefijo cuando fueren anteriores a su destino (por ejemplo : una )
y postfix operadores si siguen su destino (como i ++ ).
Implementa un prefijo o Postfix operador unitario escribiendo el prefijo o de
sufijo modificador antes de lafunc palabra clave cuando se declara la funcin de
operador:

prefix func - (vector: Vector2D) -> Vector2D {

return Vector2D(x: -vector.x, y: -vector.y)

}
El ejemplo anterior implementa el operador menos unario ( -a )
para Vector2D casos. El operador menos unario es un operador prefijo, por lo que
esta funcin tiene que ser calificado con el prefijo modificador.
Para los valores numricos simples, el operador menos unario convierte nmeros
positivos en su negativa versa equivalente y el vicio. La aplicacin correspondiente
para Vector2D casos realiza esta operacin tanto en la x y Y propiedades:

let positive = Vector2D(x: 3.0, y: 4.0)

let negative = -positive

// Negativo es una instancia de Vector2D con valores de (3,0, -4,0)


286

let alsoPositive = -negative

// AlsoPositive es una instancia de Vector2D con valores de


(3.0, 4.0)


Operadores de Asignacin Compuesto
Operadores de asignacin compuestos combinan asignacin ( = ) con otra
operacin. Por ejemplo, el operador de asignacin de suma ( + = ) combina la adicin y
la asignacin en una sola operacin. Usted marca parmetro de entrada izquierda una
asignacin del operador compuesto como inout , porque el valor del parmetro ser
modificado directamente desde dentro de la funcin de operador.
El siguiente ejemplo implementa una funcin de operador de asignacin de suma
para Vector2D casos:

func += (inout left: Vector2D, right: Vector2D) {

left = left + right

}
Debido a que un operador de suma se defini anteriormente, no es necesario volver a
implementar el proceso de adicin aqu. En lugar de ello, la funcin de operador de
asignacin Adems se aprovecha de la funcin de operador de suma existente, y la
utiliza para establecer el valor de izquierda a ser el valor ms el valor izquierda derecha:

var original = Vector2D(x: 1.0, y: 2.0)

let vectorToAdd = Vector2D(x: 3.0, y: 4.0)

original += vectorToAdd

// Original, ahora muestra los valores de (4.0, 6.0)


Puede combinar la asignacin, ya sea con el prefijo o de sufijo modificador,
como en esta implementacin del operador de incremento prefijo ( ++ una )
para Vector2D casos:

prefix func ++ (inout vector: Vector2D) -> Vector2D {

vector += Vector2D(x: 1.0, y: 1.0)

return vector

}
La funcin de operador de incremento prefijo anteriormente se aprovecha de que el
operador de asignacin de suma definida anteriormente. Se aade
un Vector2D con x y Y los valores de 1,0 a la Vector2D en la que se le llama, y
devuelve el resultado:

var toIncrement = Vector2D(x: 3.0, y: 4.0)

let afterIncrement = ++toIncrement

// ToIncrement ahora tiene valores de (4.0, 5.0)

// AfterIncrement tambin tiene valores de (4.0, 5.0)


NOTA

287

No es posible sobrecargar el operador de asignacin por defecto ( = ). Slo los


operadores de asignacin compuestos se pueden sobrecargar. Del mismo modo, el
operador condicional ternario ( a b:? c ) no puede ser sobrecargado.
Operadores de equivalencia
Clases y estructuras personalizadas no reciben una implementacin por defecto de
los operadores de equivalencia , conocida como la "igual a" operador ( == ) y "no es
igual a" operador ( ! = ). No es posible que Swift adivinar lo calificara como "igual"
para sus propios tipos personalizados, ya que el significado de "igual" depende de las
funciones que desempean esos tipos en el cdigo.
Para utilizar los operadores de equivalencia para comprobar la equivalencia de su propio
tipo personalizado, proporcionar una implementacin de los operadores de la misma
forma que para otros operadores infijos:

func == (left: Vector2D, right: Vector2D) -> Bool {

return (left.x == right.x) && (left.y == right.y)

func != (left: Vector2D, right: Vector2D) -> Bool {

return !(left == right)

}
El ejemplo anterior implementa un "igual a" operador ( == ) para comprobar si
dos Vector2D casos tienen valores equivalentes. En el contexto de Vector2D , tiene
sentido considerar "igual" en el sentido de "ambas instancias tienen los
mismos x valores y Y valores ", y por lo que esta es la lgica utilizada por la aplicacin
del operador. El ejemplo tambin implementa el "no es igual a" operador ( ! = ), que
simplemente devuelve el inverso del resultado de la "igual a" operador.
Ahora puede utilizar estos operadores para comprobar si dos Vector2D casos son
equivalentes:

let twoThree = Vector2D(x: 2.0, y: 3.0)

let anotherTwoThree = Vector2D(x: 2.0, y: 3.0)

if twoThree == anotherTwoThree {

println("These two vectors are equivalent.")

// imprime "Estos dos vectores son equivalentes."



Operadores personalizados
Puede declarar e implementar sus propios operadores personalizados adems de los
operadores estndar proporcionados por Swift. Para obtener una lista de caracteres que
se pueden utilizar para definir operadores personalizados, consulte Operadores .
Los nuevos operadores se declaran a nivel global mediante el operador de la
palabra clave, y estn marcados con los prefix,infix or postfix modificadores:

prefix operator +++ {}


El ejemplo anterior define un nuevo operador de prefijo de llamada +++ . Este operador
no tiene un significado existente en Swift, y por lo que se le da su propio significado

288

personalizado debajo en el contexto especfico de trabajar con Vector2D casos. Para


los fines de este ejemplo, +++ se trata como un nuevo operador "prefijo duplicar
incrementador". Dobla las x y Y valores de una Vector2D ejemplo, aadiendo que el
vector propio con el operador de asignacin de suma definido anteriormente:

prefix func +++ (inout vector: Vector2D) -> Vector2D {

vector += vector

return vector

}
Esta implementacin de +++ es muy similar a la aplicacin de ++ para Vector2D ,
excepto que esta funcin de operador aade el vector a s mismo, en lugar de
aadir Vector2D (1.0, 1.0) :

var toBeDoubled = Vector2D(x: 1.0, y: 4.0)

let afterDoubling = +++toBeDoubled

// ToBeDoubled ahora muestra los valores de (2.0, 8.0)

// AfterDoubling tambin tiene valores de (2.0, 8.0)



Precedencia y asociatividad de operadores infijos personalizados
Custom infix operadores tambin pueden especificar una prioridad y
una asociatividad . Ver Precedencia y asociatividad para una explicacin de cmo estas
dos caractersticas afectan a la interaccin de un operador infijo con otros operadores
infijos.
Los valores posibles para la asociatividad se dejaron , derecha ,
y ninguno . Operadores asociativos por la izquierda asociado a la izquierda si se
escribe junto a otros operadores asociativos por la izquierda de la misma
precedencia. Operadores de la misma manera, asociativo por la derecha asociada a la
derecha si escrito junto a otros operadores de la derecha asociativas de la misma
precedencia. Los operadores no asociativos no se pueden escribir junto a otros
operadores con la misma precedencia.
Los asociatividad valor predeterminado es ninguno si no se
especifica. Los precedencia valor por defecto es100 , si no se especifica.
El ejemplo siguiente define una nueva costumbre infijo operador de llamada + - ,
con izquierdaasociatividad y precedencia de 140 :

infix operator +- { associativity left precedence 140 }

func +- (left: Vector2D, right: Vector2D) -> Vector2D {

return Vector2D(x: left.x + right.x, y: left.y - right.y)

let firstVector = Vector2D(x: 1.0, y: 2.0)

let secondVector = Vector2D(x: 3.0, y: 4.0)

let plusMinusVector = firstVector +- secondVector

// PlusMinusVector es una instancia de Vector2D con valores


de (4,0, -2,0)

289

Este operador suma los x valores de dos vectores, y resta el y valor de la segunda vector
desde el primero.Debido a que es en esencia un operador "aditivo", se ha dado a los
mismos valores de asociatividad y precedencia ( izquierda y 140 ) como
operadores infijos aditivo defecto como + y - . Para obtener una lista completa de los
ajustes de precedencia y asociatividad de operadores Swift predeterminados,
veaExpresiones .
NOTA
No se especifica una prioridad en la definicin de un operador de prefijo o de sufijo. Sin
embargo, si usted solicita un prefijo y un operador de sufijo al mismo operando, el
operador de sufijo se aplica primero.





















290


Acerca de la Referencia del lenguaje
Esta parte del libro describe la gramtica formal del lenguaje de programacin Swift. La
gramtica se describe aqu est destinado a ayudar a entender el idioma con ms detalle,
en lugar de que le permite implementar directamente un analizador o compilador.
El lenguaje Swift es relativamente pequeo, debido a que muchos comunes tipos,
funciones y operadores que aparecen prcticamente en todas partes en el cdigo Swift
estn definidos en la librera estndar de Swift. Aunque estos tipos, funciones y
operadores que no forman parte de la propia lengua Swift, que se utilizan ampliamente
en las discusiones y ejemplos de cdigo en esta parte del libro.
Cmo leer la Gramtica
La notacin utilizada para describir la gramtica formal del lenguaje de programacin
Swift sigue una serie de convenciones:
Una flecha () se utiliza para marcar las producciones de la gramtica y se puede
leer como "puede consistir en."
Categoras sintcticas se indican mediante cursiva texto y aparecen en ambos lados
de una regla de produccin gramtica.
Palabras literales y puntuacion se indican con negrita anchura
constante texto y slo aparecen en el lado derecho de una regla de gramtica de
produccin.
Producciones gramaticales alternativos estn separados por barras verticales
(|). Cuando producciones alternativas son demasiado tiempo para leer con facilidad,
que se dividen en varias reglas de la gramtica de produccin en nuevas lneas.
En unos pocos casos, el texto fuente normal se utiliza para describir el lado derecho
de una regla de gramtica de produccin.
Categoras y literales sintcticas opcionales estn marcadas por un subndice de
arrastre, optan .
Como ejemplo, la gramtica de un bloque getter-setter se define como sigue:
GRAMTICA DE UN BLOQUE GETTER-SETTER
getter-setter-block {getter-clausesetter-clauseopt} {setter-clausegetter-clause}
Esta definicin indica que un bloque getter-setter puede consistir en una clusula getter
seguida de una clusula facultativa setter, entre llaves, o una clusula setter seguido por
una clusula getter, entre llaves. La produccin de la gramtica anterior es equivalente a
las siguientes dos producciones, donde las alternativas se extraen explcitamente:
GRAMTICA DE UN BLOQUE GETTER-SETTER
getter-setter-block {getter-clausesetter-clauseopt} {setter-clausegetter-clause}



291

Estructura lxica
En esta pgina
La estructura lxica de Swift describe qu secuencia de caracteres forman smbolos
vlidos de la lengua.Estos tokens vlidos forman los bloques de construccin de ms
bajo nivel de la lengua y se utilizan para describir el resto de la lengua en los captulos
siguientes. Un smbolo consiste en un identificador, palabra clave, puntuacion, literal, o
el operador.
En la mayora de los casos, las fichas se generan a partir de los caracteres de un archivo
de origen Swift considerando la ms larga subcadena posible del texto de entrada,
dentro de las restricciones de la gramtica que se especifican a continuacin. Este
comportamiento se conoce como partido ms largo o munch mxima.
Los espacios en blanco y comentarios
El espacio en blanco tiene dos usos: para separar tokens en el archivo de origen y para
ayudar a determinar si un operador es un prefijo o de sufijo (ver Operadores ), pero se
ignora lo contrario. Los siguientes caracteres se consideran espacios en blanco: espacio
(U + 0020), avance de lnea (U + 000A), retorno de carro (U + 000D), tabulador
horizontal (U + 0009), pestaa vertical (U + 000B), la forma de alimentacin (U +
000C) y nulo (U + 0000).
Los comentarios son tratados como espacios en blanco por el compilador. Una sola
lnea Los comentarios comienzan con // y continuar hasta que un retorno de carro (U +
000D) o avance de lnea (U + 000A).Comentarios multilnea empiezan con / * y
terminan con * / . Anidacin comentarios multilnea est permitido, pero los
marcadores de comentario debe ser equilibrado.
Identificadores
Identificadores comienzan con una letra mayscula o minscula de la A a la Z, un guin
bajo ( _ ), un carcter alfanumrico noncombining Unicode en el plano multilinge
bsico, o un personaje fuera del plano multilinge bsico que no est en un rea de uso
privado. Despus del primer carcter, tambin se permite la combinacin de dgitos y
caracteres Unicode.
Para utilizar una palabra reservada como identificador, poner un acento grave ( ` ) antes
y despus de ella.Por ejemplo, la clase no es un identificador vlido,
pero `class` es vlida. Los acentos abiertos no se consideran parte del
identificador; `x` y x tienen el mismo significado.
Dentro de un cierre sin nombres explcitos de los parmetros, los parmetros se
denominan implcitamente $ 0 , $ 1 , $ 2 , y as sucesivamente. Estos nombres son
identificadores vlidos dentro del mbito de aplicacin del cierre.
GRAMTICA DE UN IDENTIFICADOR
identifier identifier-headidentifier-charactersopt
identifier `identifier-headidentifier-charactersopt`
identifier implicit-parameter-name
identifier-list identifier identifier,identifier-list
identifier-head Upper- or lowercase letter A through Z
identifier-head _
identifier-head U+00A8, U+00AA, U+00AD, U+00AF, U+00B2U+00B5, or
U+00B7U+00BA

292

identifier-head U+00BCU+00BE, U+00C0U+00D6, U+00D8U+00F6, or


U+00F8U+00FF
identifier-head U+0100U+02FF, U+0370U+167F, U+1681U+180D, or
U+180FU+1DBF
identifier-head U+1E00U+1FFF
identifier-head U+200BU+200D, U+202AU+202E, U+203FU+2040, U+2054,
or U+2060U+206F
identifier-head U+2070U+20CF, U+2100U+218F, U+2460U+24FF, or U+2776
U+2793
identifier-head U+2C00U+2DFF or U+2E80U+2FFF
identifier-head U+3004U+3007, U+3021U+302F, U+3031U+303F, or U+3040
U+D7FF
identifier-head U+F900U+FD3D, U+FD40U+FDCF, U+FDF0U+FE1F, or
U+FE30U+FE44
identifier-head U+FE47U+FFFD
identifier-head U+10000U+1FFFD, U+20000U+2FFFD, U+30000U+3FFFD, or
U+40000U+4FFFD
identifier-head U+50000U+5FFFD, U+60000U+6FFFD, U+70000U+7FFFD, or
U+80000U+8FFFD
identifier-head U+90000U+9FFFD, U+A0000U+AFFFD, U+B0000U+BFFFD,
or U+C0000U+CFFFD
identifier-head U+D0000U+DFFFD or U+E0000U+EFFFD
identifier-character Digit 0 through 9
identifier-character U+0300U+036F, U+1DC0U+1DFF, U+20D0U+20FF, or
U+FE20U+FE2F
identifier-character identifier-head
identifier-characters identifier-characteridentifier-charactersopt
implicit-parameter-name $decimal-digits
Palabras clave y Puntuacion
Los siguientes palabras clave estn reservados y no se pueden usar como
identificadores, a menos que estn escaparon con acentos abiertos, como se describe
anteriormente en Identificadores .
Keywords used in
declarations: class, deinit, enum, extension, func, import, init, internal, let, opera
tor,private, protocol, public, static, struct, subscript, typealias, and var.
Keywords used in
statements: break, case, continue, default, do, else, fallthrough, for, if, in, return,
switch, where, and while.
Keywords used in expressions and
types: as, dynamicType, false, is, nil, self, Self, super, true,__COLUMN__, __FI
LE__, __FUNCTION__, and __LINE__.
Keywords reserved in particular
contexts: associativity, convenience, dynamic, didSet, final, get, infix,inout, lazy
, left, mutating, none, nonmutating, optional, override, postfix, precedence, prefi

293

x, Protocol,required, right, set, Type, unowned, weak, and willSet. Palabras


clave reservadas, en particular, y willSet . Fuera del contexto en el que
aparecen en la gramtica, que pueden utilizarse como identificadores.
Las siguientes fichas estn reservados como puntuacion y no pueden ser utilizados
como operadores personalizados: ( , ) , { , } , [ , ] , . , , , : , ; , = , @ , # , y (como
operador de prefijo) , -> , ` , ? , y ! (como un operador de sufijo).
Literales
Un literal es la representacin cdigo fuente de un valor de un tipo, tal como un nmero
o una cadena.
Los siguientes son ejemplos de literales:

42 // Integer literal

3.14159 // Floating-point literal

"Hello, world!" // String literal

true // Boolean literal


Un literal no tiene un tipo por s solo. En su lugar, un literal se analiza como tener una
precisin infinita y la inferencia de tipos de Swift intentos de inferir un tipo de lo
literal. Por ejemplo, en la declaracin sea x: INT8 = 42 , Swift utiliza el tipo de
anotacin explcita ( : INT8 ) para inferir que el tipo del entero literal 42 es INT8 . Si
no hay informacin de tipo adecuado disponible, Swift infiere que el tipo del literal es
uno de los tipos literales defecto definidos en la librera estndar de Swift. Los tipos por
defecto son Int para literales enteros, doblepara los literales de punto
flotante, Cadena de literales de cadena, y Bool para los literales booleanos. Por
ejemplo, en la declaracin deje cadena = "Hola, mundo" , el tipo inferido por
defecto de la cadena literal "Hola, mundo" es de cuerda .
Al especificar la anotacin de tipo por un valor literal, el tipo de la anotacin debe ser
un tipo que se pueden crear instancias de ese valor literal. Es decir, el tipo debe ajustarse
a uno de los siguientes protocolos de la biblioteca estndar
Swift: IntegerLiteralConvertible para literales
enteros, FloatingPointLiteralConvertiblepara literales de punto
flotante, StringLiteralConvertible para los literales de cadena,
yBooleanLiteralConvertible para los literales booleanos. Por
ejemplo, INT8 se ajusta a laIntegerLiteralConvertible protocolo, y por lo
tanto puede ser utilizado en la anotacin de tipo para el nmero entero literal 42 en la
declaracin sea x: INT8 = 42 .
GRAMTICA DE UN LITERAL
literal integer-literal floating-point-literal string-literal
literal true false nil
Enteros literales
Literales enteros representan valores enteros de precisin sin especificar. Por defecto,
los literales enteros se expresan en decimal; puede especificar una base alternativo

294

usando un prefijo. Literales binarios comienzan con 0b , literales octales comienzan


con 0 , y los literales hexadecimales comienzan con 0x .
Literales decimales contienen los dgitos 0 a travs de 9 . Literales binarios
contienen 0 y 1 , literales octales contienen 0 a travs de 7 y literales hexadecimales
contienen 0 a travs de 9 , as como A travs de F en maysculas o en minsculas.
Literales enteros negativos se expresan anteponiendo un signo menos ( - ) en un entero
literal, como en -42 .
Guiones bajos ( _ ) se permite entre los dgitos para facilitar la lectura, pero se ignoran y
por lo tanto no afectan el valor del literal. Literales enteros pueden comenzar con ceros
a la izquierda ( 0 ), pero son igualmente ignorado y no afectar a la base o el valor del
literal.
A menos que se especifique lo contrario, el tipo inferido por defecto de un entero literal
es el tipo de biblioteca estndar Swift Int . La biblioteca estndar Swift tambin define
los tipos para diferentes tamaos de los enteros con y sin signo, como se describe en los
nmeros enteros .
GRAMTICA DE UN LITERAL ENTERO
integer-literal binary-literal
integer-literal octal-literal
integer-literal decimal-literal
integer-literal hexadecimal-literal
binary-literal 0bbinary-digitbinary-literal-charactersopt
binary-digit Digit 0 or 1
binary-literal-character binary-digit _
binary-literal-characters binary-literal-characterbinary-literal-charactersopt
octal-literal 0ooctal-digitoctal-literal-charactersopt
octal-digit Digit 0 through 7
octal-literal-character octal-digit _
octal-literal-characters octal-literal-characteroctal-literal-charactersopt
decimal-literal decimal-digitdecimal-literal-charactersopt
decimal-digit Digit 0 through 9
decimal-digits decimal-digitdecimal-digitsopt
decimal-literal-character decimal-digit _
decimal-literal-characters decimal-literal-characterdecimal-literal-charactersopt
hexadecimal-literal 0xhexadecimal-digithexadecimal-literal-charactersopt
hexadecimal-digit Digit 0 through 9, a through f, or A through F
hexadecimal-literal-character hexadecimal-digit _
hexadecimal-literal-characters hexadecimal-literal-characterhexadecimal-literalcharacters opt
Floating-Point literales
Literales de punto flotante representan valores de punto flotante de precisin sin
especificar.
Por defecto, los literales de punto flotante se expresan en decimal (sin prefijo), pero
tambin pueden ser expresados en hexadecimal (con un 0x prefijo).

295

Literales decimales de coma flotante consisten en una secuencia de dgitos decimales


seguidos por cualquiera de una fraccin decimal, un exponente decimal, o ambos. La
fraccin decimal consta de un punto decimal ( . ) seguido de una secuencia de dgitos
decimales. El exponente consiste en un maysculas o minsculas e prefijo seguido por
una secuencia de dgitos decimales que indica qu potencia de 10 del valor anterior a
la e se multiplica por. Por ejemplo, 1.25e2 representa 1.25 10 2 , que evala
a 125,0 . Del mismo modo, 1.25E-2 representa 1,25 x 10 -2 , que evala
a 0,0125 .
Hexadecimales literales de punto flotante consisten en un 0x prefijo, seguido de una
fraccin hexadecimal opcional, seguido de un exponente hexadecimal. La fraccin
hexadecimal consta de un punto decimal seguido por una secuencia de dgitos
hexadecimales. El exponente consiste en un maysculas o minsculasp prefijo seguido
por una secuencia de dgitos decimales que indica qu potencia de 2, el valor anterior a
la pse multiplica por. Por ejemplo, 0xFp2 representa 15 2 2 , que evala a 60 . Del
mismo modo, 0xFp-2representa 15 2 -2 , que evala a 3,75 .
A diferencia de los literales enteros, nmeros de punto flotante negativos se expresan
aplicando el operador menos unario ( - ) a un literal de coma flotante, como en 42,0 . El resultado es una expresin, no un literal de coma flotante.
Guiones bajos ( _ ) se permite entre los dgitos para facilitar la lectura, pero se ignoran y
por lo tanto no afectan el valor del literal. Literales de punto flotante pueden comenzar
con ceros a la izquierda ( 0 ), pero estn igualmente ignorado y no afectar a la base o el
valor del literal.
A menos que se especifique lo contrario, el tipo inferido por defecto de un literal de
coma flotante es el tipo de biblioteca estndar Swift doble , lo que representa un
nmero de punto flotante de 64 bits. La biblioteca estndar Swift tambin define
un flotador tipo, lo que representa un nmero de punto flotante de 32 bits.
GRAMTICA DE UN LITERAL DE COMA FLOTANTE
floating-point-literal decimal-literaldecimal-fractionoptdecimal-exponentopt
floating-point-literal hexadecimal-literalhexadecimal-fractionopthexadecimalexponent
decimal-fraction .decimal-literal
decimal-exponent floating-point-esignoptdecimal-literal
hexadecimal-fraction .hexadecimal-digithexadecimal-literal-charactersopt
hexadecimal-exponent floating-point-psignoptdecimal-literal
floating-point-e e E
floating-point-p p P
sign + Literales de cadena
Un literal de cadena es una secuencia de caracteres entre comillas, por, con el siguiente
formulario:

" characters "


Los literales de cadena no puede contener un doble cita no literal ( " ), una barra
invertida sin escape ( \ ), un retorno de carro o un salto de lnea.

296

Los caracteres especiales pueden ser incluidos en los literales de cadena utilizando las
siguientes secuencias de escape:
Carcter nulo ( \ 0 )
Barra invertida ( \\ )
Horizontal Tab ( \ t )
Avance de lnea ( \ n )
Retorno de carro ( \ r )
Doble Cita ( \ " )
Las comillas sencillas ( \ ' )
Unicode escalar ( \ u { n } ), donde n es entre uno y ocho dgitos hexadecimales
El valor de una expresin se puede insertar en una cadena literal mediante la colocacin
de la expresin entre parntesis despus de una barra invertida ( \ ). La expresin
interpolado no debe contener un doble cita no literal ( " ), una barra invertida sin escape
( \ ), un retorno de carro o un salto de lnea. La expresin debe evaluarse como un valor
de un tipo que la Cadena de clase tiene un inicializador de.
Por ejemplo, todos los siguientes literales de cadena tienen el mismo valor:

"1 2 3"

"1 2 \ ( 3 ) "

"1 2 \ ( 1 + 2 ) "

dejar que x = 3 ; "1 2 \ ( x ) "


El tipo inferido por defecto de un literal de cadena es de cuerda . El tipo inferido por
defecto de los caracteres que componen una cadena es de caracteres . Para
obtener ms informacin acerca de las cuerdas y de Carcter tipos, vea Cadenas
y caracteres .
GRAMTICA DE UNA CADENA LITERAL
string-literal "quoted-textopt"
quoted-text quoted-text-itemquoted-textopt
quoted-text-item escaped-character
quoted-text-item \(expression)
quoted-text-item Any Unicode extended grapheme cluster except ", \, U+000A, or
U+000D
escaped-character \0 \\ \t \n \r \" \'
escaped-character \u{unicode-scalar-digits}
unicode-scalar-digits Between one and eight hexadecimal digits
Operadores
La biblioteca estndar Swift define una serie de operadores para su uso, muchas de las
cuales se describenOperadores bsicos y Operadores avanzados . La presente seccin
describe qu caracteres se pueden usar para definir operadores personalizados.
Operadores personalizados pueden comenzar con uno de los caracteres ASCII / , = , , + , ! , * , % , < , > , y ,| , ^ , o ~ , o uno de los caracteres Unicode definido en la
gramtica de abajo. Despus del primer carcter, tambin se permite la combinacin de

297

caracteres Unicode. Tambin puede definir operadores personalizados como una


secuencia de dos o ms puntos (por ejemplo, .... ).
NOTA
Los tokens = , -> , // , / * , * / , . , y el operador de prefijo y se reservan. Estas
fichas no se pueden sobrecargar, ni pueden ser utilizados como operadores
personalizados.
El espacio en blanco alrededor de un operador se utiliza para determinar si un operador
se utiliza como un operador de prefijo, un operador de sufijo, o un operador
binario. Este comportamiento se resume en las siguientes reglas:
Si un operador ha de espacio en blanco alrededor de ambos lados o alrededor de
ninguna de las partes, se trata como un operador binario. A modo de ejemplo,
el + operador en un + b y a + b es tratado como un operador binario.
Si el operador tiene espacios en blanco slo en el lado izquierdo, se trata como un
operador unario prefijo. Como un ejemplo, el ++ operador en un ++ b se trata
como un operador unario prefijo.
Si el operador tiene espacios en blanco slo en el lado derecho, se trata como un
operador unario postfix. A modo de ejemplo, el ++ operador en un ++ b es
tratado como un operador unario postfix.
Si un operador no tiene espacios en blanco a la izquierda, pero es seguida
inmediatamente por un punto ( . ), se trata como un operador unario postfix. Como
un ejemplo, el ++ operador en un ++. B se trata como un operador unario postfix
( a ++ .b en lugar de un ++ .b ).
Para los efectos de este reglamento, los personajes ( , [ , y { antes de un operador, de
los personajes ) , ] y} despus de un operador, y los personajes , , , , y : tambin se
consideran espacios en blanco.
Hay una advertencia a las reglas anteriores. Si el ! o ? operador predefinido no tiene
espacios en blanco a la izquierda, se trata como un operador de sufijo,
independientemente de si se tiene un espacio en blanco a la derecha. Para utilizar
el ? como el operador opcional en cadena, que no debe tener espacios en blanco a la
izquierda. Para usarlo en el ternario condicional ( ? : ) operador, debe tener un espacio
en blanco alrededor de ambos lados.
En ciertas construcciones, los operadores con un lder < o > se pueden dividir en dos o
ms fichas. El resto es tratado de la misma manera y se puede dividir de nuevo. Como
resultado, no hay necesidad de utilizar espacios en blanco para eliminar la ambigedad
entre el cierre > caracteres en constructos como Diccionario <String, Array
<Int >> . En este ejemplo, las de cierre > personajes no son tratados como una sola
seal de que luego pueden ser mal interpretada como un desplazamiento de
bits >> operador.
Para saber cmo definir nuevos operadores personalizados, vea Operadores
personalizados y Declaracin del operador . Para aprender a sobrecargar los operadores
existentes, consulte Funciones del operador .
GRAMTICA DE LOS OPERADORES
operator operator-headoperator-charactersopt
operator dot-operator-headdot-operator-charactersopt
operator-head / = - + ! * % < > & | ^ ~

298

operator-head U+00A1U+00A7
operator-head U+00A9 or U+00AB
operator-head U+00AC or U+00AE
operator-head U+00B0U+00B1, U+00B6, U+00BB, U+00BF, U+00D7, or
U+00F7
operator-head U+2016U+2017 or U+2020U+2027
operator-head U+2030U+203E
operator-head U+2041U+2053
operator-head U+2055U+205E
operator-head U+2190U+23FF
operator-head U+2500U+2775
operator-head U+2794U+2BFF
operator-head U+2E00U+2E7F
operator-head U+3001U+3003
operator-head U+3008U+3030
operator-character operator-head
operator-character U+0300U+036F
operator-character U+1DC0U+1DFF
operator-character U+20D0U+20FF
operator-character U+FE00U+FE0F
operator-character U+FE20U+FE2F
operator-character U+E0100U+E01EF
operator-characters operator-characteroperator-charactersopt
dot-operator-head ..
dot-operator-character . operator-character
dot-operator-characters dot-operator-characterdot-operator-charactersopt
binary-operator operator
prefix-operator operator
postfix-operator operator

Tipos
En Swift, hay dos clases de tipos: tipos con nombre y tipos de compuestos. Un tipo con
nombre es un tipo que se puede dar un nombre en particular cuando se define. Tipos con
nombre incluyen clases, estructuras, enumeraciones y protocolos. Por ejemplo, las
instancias de una clase llamada definidos por el usuario MyClasstienen el
tipo MyClass . Adems de los tipos con nombres definidos por el usuario, la biblioteca
estndar Swift define muchos tipos con nombre de uso comn, incluidos aquellos que
representan arrays, diccionarios, y los valores opcionales.
Tipos de datos que normalmente se consideran bsicos o primitivos en otros idiomascomo los tipos que representan nmeros, caracteres y cadenas-se nombren tipos,
definidos e implementados en la biblioteca estndar Swift utilizando estructuras. Debido
a que se nombran los tipos, puede extender su comportamiento para adaptarse a las
necesidades de su programa, usando una ampliacin de declaracin, se discuti
enExtensiones y ampliacin de declaracin .

299

Un tipo de compuesto es un tipo sin nombre, que se define en el propio idioma


Swift. Hay dos tipos de compuestos: tipos de funciones y tipos de tupla. Un tipo de
compuesto puede contener tipos con nombre y otros tipos compuestos. Por ejemplo, el
tipo tupla (Int, (Int, Int)) contiene dos elementos: el primero es el tipo
llamado Int , y el segundo es otro tipo compuesto (Int, Int) .
Este captulo trata de los tipos definidos en el propio idioma Swift y describe el
comportamiento inferencia tipo de Swift.
GRAMTICA DE UN TIPO
type array-type dictionary-type function-type type-identifier tuple-type optionaltype implicitly-unwrapped-optional-type protocol-composition-type metatype-type
Tipo de anotacin
Una anotacin de tipo especifica explcitamente el tipo de una variable o
expresin. Tipo anotaciones empiezan con dos puntos ( : ) y terminan con un tipo,
como muestran los siguientes ejemplos:

let someTuple: (Double, Double) = (3.14159, 2.71828)

func someFunction(a: Int) { /* ... */ }


En el primer ejemplo, la expresin someTuple Se especifica que el tipo de
tupla (Doble, doble) . En el segundo ejemplo, el parmetro de una funcin a
la algunaFuncion Se especifica que el tipo int .
Tipo anotaciones pueden contener una lista opcional de atributos de tipo antes de que el
tipo.
GRAMTICA DE UNA ANOTACIN DE TIPO
type-annotation :attributesopttype
Identificador de Tipo
Un identificador de tipo hace referencia a un tipo con nombre o un alias de tipo de un
tipo con nombre o compuesto.
La mayora del tiempo, un identificador de tipo se refiere directamente a un tipo
llamado con el mismo nombre que el identificador. Por ejemplo, int es un
identificador de tipo que se refiera directamente al tipo llamado Int, y el identificador
de tipo Dictionary <String, int> se refiere directamente al tipo
llamado Diccionario <String, int> .
Hay dos casos en los que un identificador de tipo no se refiere a un tipo con el mismo
nombre. En el primer caso, un identificador de tipo se refiere a un alias de tipo de un
tipo llamado o compuesto. Por ejemplo, en el siguiente ejemplo, el uso de punto en la
anotacin de tipo se refiere al tipo tupla (Int, Int) .

typealias Point = (Int, Int)

let origin: Point = (0, 0)


En el segundo caso, un identificador de tipo utiliza punto ( . ) sintaxis para referirse a
tipos con nombre declaradas en otros mdulos o anidados dentro de otros tipos. Por

300

ejemplo, el identificador de tipo en el cdigo siguiente se hace referencia al tipo


llamado MyType que se declara en la ExampleModule mdulo.

var someValue: ExampleModule.MyType

GRAMTICA DE UN IDENTIFICADOR DE TIPO


type-identifier type-namegeneric-argument-clauseopt type-namegeneric-argumentclauseopt.type-identifier
type-name identifier
Tipo Tuple
Un tipo tupla es una lista separada por comas de cero o ms tipos, entre parntesis.
Puede utilizar un tipo tupla como el tipo de retorno de una funcin para activar la
funcin para devolver un solo tupla que contiene varios valores. Tambin puede
nombrar a los elementos de un tipo tupla y utilizar esos nombres para referirse a los
valores de los elementos individuales. Un nombre de elemento consta de un
identificador seguido inmediatamente por dos puntos (:). Para ver un ejemplo que
demuestra tanto de estas funciones, consulte Funciones con mltiples valores de
retorno .
Vaco es un typealias para el tipo de tupla vaca, () . Si slo hay un elemento dentro
de los parntesis, el tipo es simplemente el tipo de ese elemento. Por ejemplo, el tipo
de (Int) es Int , no (Int) . Como resultado, puede nombrar a un elemento de la
tupla slo cuando el tipo de tupla tiene dos o ms elementos.
GRAMTICA DE UN TIPO TUPLA
de tipo tupla ( tupla tipo de cuerpo opt)
tupla de tipo de cuerpo tupla-tipo-elemento-lista ... opt
tupla de tipo de elemento lista tipo tupla de elementos de tipo tupla de
elementos , tupla-tipo-elemento-lista
tupla de tipo de elemento atributos optan inout opt tipo inout opt elementonombre -tipo de anotacin
Tipo de funcin
Un tipo de funcin representa el tipo de una funcin, mtodo, o el cierre y se compone
de un tipo de parmetro y retorno separados por una flecha ( -> ):

tipo de parmetro -> tipo de retorno


Debido a que el tipo de parmetro y el tipo de retorno puede ser un tipo tupla, tipos de
funciones de soporte a las funciones y mtodos que toman mltiples parmetros y
devuelven varios valores.
Puede aplicar el autoclosure atributo a un tipo de funcin que tiene un tipo de
parmetro de () y que devuelve el tipo de una expresin (ver Tipo Atributos ). Una
funcin autoclosure capta un cierre implcito sobre la expresin especificada, en lugar
de la propia expresin. El ejemplo siguiente utiliza la autoclosure atributo en la
definicin de una funcin assert muy simple:

301

func simpleAssert(condition: @autoclosureautoclosure () -> Bool, message:


String) {

if !condition() {

println(message)

let testNumber = 5

simpleAssert(testNumber % 2 == 0, "testNumber isn't an even number.")

// Impresiones "testNumber no es un nmero par."


Un tipo de funcin puede tener un parmetro variadic como el ltimo parmetro en
su tipo de parmetro .Sintcticamente, un parmetro variadic consta de un nombre de
tipo base, seguido inmediatamente por tres puntos ( ... ), como en Int ... . Un
parmetro variadic se trata como una matriz que contiene los elementos del nombre de
tipo de base. Por ejemplo, el parmetro variadic Int ... se trata como [Int] . Para
ver un ejemplo que utiliza un parmetro variadic, consulte Parmetros variadic .
Para especificar un parmetro in-out, prefijar el tipo de parmetro con el inout palabra
clave. No se puede marcar un parmetro variadic o un tipo de retorno con
el inout palabra clave. In-Out parmetros se discuten en Parmetros In-Out .
Los tipos de funcin de una funcin de curry se agrupan de derecha a izquierda. Por
ejemplo, el tipo de funcin Int -> Int -> Int se entiende como Int -> (Int
-> Int) , es decir, una funcin que toma un int y devuelve otra funcin que toma y
devuelve un int . Funcin al curry se describen en Funciones curry .
GRAMTICA DE UN TIPO DE FUNCIN
function-type type->type
Tipo de matriz
El lenguaje Swift proporciona la siguiente manera de expresar el Swift de la biblioteca
estndar de matriz <T>Tipo:
[ type ]
En otras palabras, las dos declaraciones siguientes son equivalentes:

let someArray: [String] = ["Alex", "Brian", "Dave"]

let someArray: Array<String> = ["Alex", "Brian", "Dave"]


En ambos casos, la constante someArray se declara como una matriz de cadenas. Los
elementos de una matriz se puede acceder a travs de subndices especificando un valor
de ndice vlido entre corchetes:someArray [0] se refiere al elemento en el ndice
0, "Alex" .
Puede crear matrices multidimensionales anidando pares de corchetes, donde el nombre
del tipo base de los elementos est contenido en el par ms interno de corchetes. Por
ejemplo, puede crear una matriz tridimensional de nmeros enteros utilizando tres
conjuntos de corchetes:

var array3D: [[[Int]]] = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]

302

Cuando se accede a los elementos en una matriz multidimensional, el ndice ms a la


izquierda subndice se refiere al elemento en ese ndice de la matriz externa. El
siguiente ndice subndice a la derecha se refiere al elemento en ese ndice de la matriz
que est anidado en un nivel. Y as sucesivamente. Esto significa que en el ejemplo
anterior, array3D [0] se refiere a [[1, 2], [3, 4]] , array3D [0]
[1] se refiere a [3, 4] , y array3D [0] [1 ] [1] se refiere al valor 4.
Para una discusin detallada de la librera estndar de Swift matriz tipo,
vea Matrices .
GRAMTICA DE UN TIPO DE MATRIZ
array-type [type]
Diccionario Type
El lenguaje Swift proporciona la siguiente manera de expresar la biblioteca estndar
Swift Dictionary <KeyType, ValueType> Tipo:
[ key type : value type ]
En otras palabras, las dos declaraciones siguientes son equivalentes:

let someDictionary: [String: Int] = ["Alex": 31, "Paul": 39]

let someDictionary: Dictionary<String, Int> = ["Alex": 31, "Paul": 39]


En ambos casos, la constante someDictionary se declara como un diccionario con
cadenas como claves y nmeros enteros como valores.
Los valores de un diccionario se puede acceder a travs de subndices especificando la
clave correspondiente entre corchetes: someDictionary ["Alex"] se refiere al
valor asociado a la clave "Alex" . El subndice devuelve un valor opcional de valor
tipo del diccionario. Si la clave especificada no se encuentra en el diccionario, el
subndice retornos nil .
El tipo de clave de un diccionario debe ser conforme a la biblioteca estndar
Swift Hashable protocolo, como se describe en valores hash para los tipos clave de
diccionario .
Para una discusin detallada de la Swift estndar biblioteca Diccionario tipo,
vea Diccionarios .
GRAMTICA DE UN TIPO DE DICCIONARIO
dictionary-type [type:type]
Tipo Opcional
El lenguaje Swift define el postfix ? como azcar sintctico para el tipo de
llamada opcional <T> , que se define en la biblioteca estndar de Swift. En otras
palabras, las dos declaraciones siguientes son equivalentes:

var optionalInteger: Int?

var optionalInteger: Optional<Int>


En ambos casos, la variable optionalInteger se declararon tener el tipo de un
entero opcional. Tenga en cuenta que no hay espacio en blanco puede aparecer entre el
tipo y el ? .

303

El tipo opcional <T> es una enumeracin con dos casos, Ninguno y Algunos
(T) , que se utilizan para representar valores que pueden o no pueden estar
presentes. Cualquier tipo puede ser declarado explcitamente que ser (o implcitamente
convertido a) un tipo opcional. Si usted no proporciona un valor inicial cuando se
declara una variable o propiedad opcional, su valor cambia automticamente a cero .
Si una instancia de un tipo opcional contiene un valor, se puede acceder a ese valor con
el operador de sufijo! , como se muestra a continuacin:

optionalInteger = 42

optionalInteger! // 42
Usando el ! operador a desenvolver un opcional que tiene un valor de nil resultados
en un error de ejecucin.
Tambin puede utilizar el encadenamiento opcional y de unin opcional para realizar
condicionalmente una operacin en una expresin opcional. Si el valor es cero , no se
realiza ninguna operacin, por lo que no se produce ningn error de ejecucin.
Para obtener ms informacin y ver ejemplos que muestran cmo utilizar los tipos
opcionales, consulteOpcionales .
GRAMTICA DE TIPO OPCIONAL
optional-type type?
Implcitamente Unwrapped Tipo Opcional
El lenguaje Swift define el postfix ! como azcar sintctico para el tipo
llamado ImplicitlyUnwrappedOptional <T> , que se define en la biblioteca
estndar de Swift. En otras palabras, las dos declaraciones siguientes son equivalentes:

var implicitlyUnwrappedString: String!

var implicitlyUnwrappedString: ImplicitlyUnwrappedOptional<String>


En ambos casos, la variable implicitlyUnwrappedString se declararon tener el
tipo de una cadena opcional implcitamente sin envolver. Tenga en cuenta que no hay
espacio en blanco puede aparecer entre el tipo y el! .
Puede utilizar opcionales implcitamente abierto en todos los mismos lugares en su
cdigo que puede utilizar opcionales. Por ejemplo, puede asignar valores de opcionales
implcitamente abierto a variables, constantes y propiedades de opcionales, y viceversa.
Al igual que con los opcionales, si no se proporciona un valor inicial cuando se declara
una variable opcional implcitamente sin envolver o propiedad, su valor cambia
automticamente a cero .
Debido a que el valor de una manera implcita sin envolver opcional es
automticamente sin envolver cuando lo utiliza, no hay necesidad de utilizar
el ! operador desenvuelva. Dicho esto, si intenta utilizar una opcin implcita sin
envolver que tiene un valor de cero , obtendr un error de ejecucin.
Utilice encadenamiento opcional para realizar condicionalmente una operacin en una
expresin opcional implcitamente sin envolver. Si el valor es cero , no se realiza
ninguna operacin, por lo que no se produce ningn error de ejecucin.
Para obtener ms informacin acerca de los tipos opcionales implcitamente abierto,
ver Implcitamente Unwrapped Opcionales .

304

GRAMTICA DE TIPO OPCIONAL IMPLCITAMENTE SIN


ENVOLVER
implicitly-unwrapped-optional-type type!
Protocolo Tipo Composicin
Un tipo de composicin protocolo describe un tipo que se ajusta a cada protocolo en una
lista de protocolos especificados. Protocolo de tipos de composicin se pueden usar en
anotaciones de tipo y en los parmetros genricos.
Tipos de composicin Protocolo tienen el siguiente formulario:

protocol< Protocol 1 , Protocol 2 >


Un tipo de composicin protocolo permite especificar un valor cuyo tipo se ajusta a los
requisitos de mltiples protocolos sin tener que definir explcitamente un nuevo
protocolo llamado que hereda de cada protocolo que desea el tipo de ajustarse a. Por
ejemplo, la especificacin de un protocolo de tipo composicin protocolo
<ProtocolA, ProtocolB, ProtocolC> es efectivamente el mismo que definir
un nuevo protocolo ProtocolD que hereda
de ProtocolA , ProtocolB y ProtocolC , pero sin tener que introducir un nuevo
nombre.
Cada elemento de una lista composicin protocolo debe ser el nombre de protocolo o un
alias de tipo de un tipo de composicin protocolo. Si la lista est vaca, que especifica el
tipo de composicin protocolo vaco, que se ajusta a todos los tipos.
GRAMTICA DE UN TIPO DE COMPOSICIN PROTOCOLO
protocol-composition-type protocol<protocol-identifier-listopt>
protocol-identifier-list protocol-identifier protocol-identifier,protocol-identifier-list
protocol-identifier type-identifier
Metatipo Tipo
Un tipo metatipo se refiere al tipo de cualquier tipo, incluyendo tipos de clase, tipos de
estructura, tipos de enumeracin y tipos de protocolo.
El metatipo de un tipo de clase, estructura o enumeracin es el nombre de ese tipo,
seguido de .Type . El metatipo de un protocolo de tipo-no el tipo de hormign que
cumpla con el protocolo en tiempo de ejecucin-es el nombre de ese protocolo seguido
por .Protocol . Por ejemplo, el metatipo del tipo de
clase AlgunaClasees SomeClass.Type y la metatipo del
protocolo SomeProtocol es SomeProtocol.Protocol .
Usted puede utilizar el postfix auto expresin para acceder a un tipo como un
valor. Por ejemplo,SomeClass.self devuelve AlgunaClase s mismo, no una
instancia
de AlgunaClase . Y SomeProtocol.selfdevuelve SomeProtocol s mismo,
no una instancia de un tipo que se ajusta a SomeProtocol en tiempo de
ejecucin. Puede utilizar un dynamicType expresin con una instancia de un tipo
para acceder tipo en tiempo de ejecucin de esa instancia como un valor, como muestra
el siguiente ejemplo:

305

class SomeBaseClass {

class func printClassName() {

println("SomeBaseClass")

class SomeSubClass: SomeBaseClass {

override class func printClassName() {

println("SomeSubClass")

let someInstance: SomeBaseClass = SomeSubClass()

// SomeInstance es de tipo SomeBaseClass en tiempo de


compilacin, pero

// SomeInstance es de tipo SomeSubClass en tiempo de


ejecucin

someInstance.dynamicType.printClassName()

// Impresiones "SomeSubClass"


GRAMTICA DE UN TIPO METATIPO
metatype-type type.Type type.Protocol
Tipo Herencia Clusula
Una clusula tipo de herencia se utiliza para especificar qu clase de un tipo llamado
hereda y qu protocolos un tipo designado cumple con. Una clusula tipo de herencia
tambin se utiliza para especificar una clase derequisito en un protocolo. Una
clusula tipo de herencia comienza con dos puntos ( : ), seguido por cualquiera de
una clase de requisito, una lista de identificadores de tipo, o ambos.
Tipos de clases pueden heredar de una nica superclase y ajustarse a cualquier nmero
de protocolos.Cuando se define una clase, el nombre de la superclase debe aparecer
primero en la lista de identificadores de tipo, seguido de cualquier nmero de protocolos
de la clase debe cumplir. Si la clase no se hereda de otra clase, la lista puede comenzar
con un protocolo en su lugar. Para una extensa discusin y varios ejemplos de la
herencia de clases, vea Herencia .
Otros tipos con nombre slo pueden heredar de o ajustarse a una lista de
protocolos. Tipos de protocolo pueden heredar de cualquier nmero de otros
protocolos. Cuando un tipo de protocolo hereda de otros protocolos, el conjunto de
requisitos de los otros protocolos son agregados juntos, y de cualquier tipo que hereda
de la actual protocolo debe cumplir con todos esos requisitos. Como se discuti en la
declaracin el Protocolo , puede incluir la clase de palabras clave como el primer
elemento de la clusula de tipo de herencia para marcar una declaracin protocolo con
una clase requisito.

306

Una clusula tipo de herencia en una definicin de enumeracin puede ser una lista de
protocolos, o en el caso de una enumeracin que asigna valores de primas a sus casos,
una sola, el tipo con nombre que especifica el tipo de los valores brutos. Para ver un
ejemplo de una definicin de la enumeracin que utiliza una clusula tipo de herencia
para especificar el tipo de sus valores brutos, consulte Raw Values.
GRAMTICA DE UNA CLUSULA DE HERENCIA DE TIPO
type-inheritance-clause :class-requirement,type-inheritance-list
type-inheritance-clause :class-requirement
type-inheritance-clause :type-inheritance-list
type-inheritance-list type-identifier type-identifier,type-inheritance-list
class-requirement class
-requisito clase
Tipo Inferencia
Swift utiliza la inferencia de tipos ampliamente, lo que le permite omitir el tipo o la
parte del tipo de muchas variables y expresiones en el cdigo. Por ejemplo, en lugar de
escribir var x: int = 0 , se puede escribir var x = 0 , omitiendo el tipo
completamente-el compilador infiere correctamente que x nombres un valor de
tipoint . Del mismo modo, se puede omitir parte de un tipo cuando el tipo completo se
puede deducir por el contexto. Por ejemplo, si escribes dejar dict:
Diccionario = ["A": 1] , el compilador infiere que dict tiene el
tipo Dictionary <String, int> .
En los dos ejemplos anteriores, la informacin de tipo se pasa desde las hojas del rbol
de expresin a su raz. Es decir, el tipo de x en var x: int = 0 se deduce
comprobando primero el tipo de 0 y despus de pasar esta informacin de tipo hasta la
raz (la variable x ).
En Swift, informacin de tipo tambin puede fluir en la direccin opuesta, desde la raz
hasta las hojas. En el ejemplo siguiente, por ejemplo, la anotacin de tipo explcita ( :
flotador ) de la constante de eFloat hace que el literal numrico 2,71828 tener
un tipo inferido de flotador en lugar de doble .

let e = 2.71828 // The type of e is inferred to be Double.

let eFloat: Float = 2.71828 // The type of eFloat is Float.


Tipo de inferencia en Swift opera en el nivel de una sola expresin o declaracin. Esto
significa que toda la informacin necesaria para inferir un tipo omitido o parte de un
tipo en una expresin debe ser accesible desde el tipo de comprobacin de la expresin
o uno de sus subexpresiones.

Expresiones
En esta pgina
En Swift, hay cuatro tipos de expresiones: expresiones de prefijos binarios, expresiones,
expresiones primarias, y las expresiones de sufijo. Evaluacin de una expresin
devuelve un valor, provoca un efecto secundario, o ambos.
Prefijo y expresiones binarias le permiten aplicar los operadores para expresiones ms
pequeas.Expresiones primarias son conceptualmente el tipo ms simple de expresin,
y que proporcionan una forma de acceder a los valores. Expresiones Postfix, como

307

prefijo y expresiones binarias, le permiten construir hasta expresiones ms complejas


utilizando sufijos tales como llamadas a funciones y acceso de los miembros.Cada tipo
de expresin se describe en detalle en las siguientes secciones.
GRAMTICA DE UNA EXPRESIN
expression prefix-expressionbinary-expressionsopt
expression-list expression expression,expression-list
Prefijo Expresiones
Expresiones prefijo combinan un operador prefijo opcional con una
expresin. Operadores de prefijo toman un argumento, la expresin que les sigue.
La biblioteca estndar Swift ofrece los siguientes operadores de prefijo:
++ Increment
-- Decrement
! Logical NOT
~ Bitwise NOT
+ Unary plus
- Unary minus
Para obtener informacin sobre el comportamiento de estos operadores,
consulte Operadores bsicos yOperadores avanzados .
Adems de los operadores de la biblioteca estndar mencionados anteriormente, se
utiliza y de inmediato antes de que el nombre de una variable que est siendo pasado
como un argumento en la salida a una expresin de llamada a la funcin. Para obtener
ms informacin y ver un ejemplo, consulte In-Out Parameters .
GRAMTICA DE UNA EXPRESIN PREFIJO
prefix-expression prefix-operatoroptpostfix-expression
prefix-expression in-out-expression
in-out-expression &identifier
Expresiones binarias
Expresiones binarias combinan un operador infijo binario con la expresin que se toma
como la izquierda y los argumentos de la mano derecha. Tiene la siguiente forma:

left-hand argument operator right-hand argument


La biblioteca estndar Swift proporciona los siguientes operadores binarios:
Exponentiative (No asociatividad, nivel de precedencia 160)
o << izquierda en modo bit turno
o >> bit a bit desplazamiento a la derecha
Multiplicativo (asociativo Izquierda, nivel de precedencia 150)
o * Multiplicar
o / Divide
o % El resto
o & * Multiplicar, desbordamiento ignorando
o Y / Divide, desbordamiento ignorando
o &% El resto, haciendo caso omiso de desbordamiento

308

Y AND bit a bit


Aditivo (asociativo Izquierda, nivel de precedencia 140)
o + Aadir
o - Restar
o Y + Aadir a desbordamiento
o Y - Resta con rebosadero
o | OR bit a bit
o ^ XOR
Range (No asociatividad, nivel de precedencia 135)
o .. < gama semiabierta
o ... gama Cerrado
Reparto (No asociatividad, nivel de precedencia 132)
o es Tipo de verificacin
o como Tipo elenco
Comparado (No asociatividad, precedencia nivel 130)
o < menos que
o <= Menor o igual que
o > Mayor que
o > = Mayor o igual
o == Igualdad
o ! = No igual
o === Idntica
o ! == no idnticos
o ~ = Coincidencia de patrn
Conjuntiva (asociativo Izquierda, nivel 120 precedencia)
o && Y lgico
Disyuntivo (asociativo Izquierda, nivel de precedencia 110)
o || OR lgico
Ninguna de coalescencia (asociativo derecho, nivel de precedencia 110)
o ?? Ninguna coalescencia
Ternario condicional (asociativo derecho, nivel de precedencia 100)
o ? : condicional ternario
Asignacin (asociativo derecho, nivel de prioridad 90)
o = Asignar
o * = Multiplicar y asignar
o / = Dividir y asignar
o % = Resto y asignar
o + = Agregar y asignar
o - = Restar y asignar
o << = desplazamiento de bits izquierda y asignar
o >> = desplazamiento de bits derecho y asignar
o & = AND bit a bit y asignar
o ^ = XOR bit a bit y de asignacin
o | = OR bit a bit y de asignacin
o && = Y lgico y asignar
o || = O lgico y asignar
o

309

Para obtener informacin sobre el comportamiento de estos operadores,


consulte Operadores bsicos yOperadores avanzados .
NOTA
En tiempo de anlisis, una expresin formada por operadores binarios se representa
como una lista plana.Esta lista se transforma en un rbol mediante la aplicacin de la
precedencia de operadores. Por ejemplo, la expresin 2 + 3 * 5 se entiende
inicialmente como una lista plana de cinco artculos, 2 , + , 3 , * , y 5 . Este proceso
transforma en el rbol (2 + (3 * 5)).
GRAMTICA DE UNA EXPRESIN BINARIA
binary-expression binary-operatorprefix-expression
binary-expression assignment-operatorprefix-expression
binary-expression conditional-operatorprefix-expression
binary-expression type-casting-operator
binary-expressions binary-expressionbinary-expressionsopt
Operador de asignacin
El operador CESION establece un nuevo valor para una expresin dada. Tiene la
siguiente forma:
expression = value
El valor de la expresin se establece en el valor obtenido mediante la evaluacin
del valor . Si la expresin es una tupla, el valor debe ser una tupla con el mismo nmero
de elementos. (Tuplas anidadas estn permitidos.) Asignacin se realiza desde cada
parte del valor a la parte correspondiente de la expresin . Por ejemplo:

(a, _, (b, c)) = ("test", 9.45, (12, 3))

// a is "test", b is 12, c is 3, and 9.45 is ignored


El operador de asignacin no devuelve ningn valor.
GRAMTICA DE UN OPERADOR DE ASIGNACIN
asignacin-operador =
Operador condicional ternario
El operador condicional ternario evala como uno de los dos valores dados en funcin
del valor de una condicin. Tiene la siguiente forma:

condition ? expression used if true : expression used if false


Si la condicin se evala como verdadera , el operador condicional evala la
primera expresin y devuelve su valor. De lo contrario, se evala la segunda expresin y
devuelve su valor. La expresin no utilizada no se evala.
Para ver un ejemplo que utiliza el operador condicional ternario, ver ternario operador
condicional .

310

GRAMTICA DE UN OPERADOR CONDICIONAL


assignment-operator =
Operadores encasillamiento
Hay tres operadores de tipo de fundicin a presin, el is el operador, el as? operador,
y el as operador.Tienen el siguiente formulario:

expression is type

expression as? type

expression as type
Las is check de operador en tiempo de ejecucin si la expresin puede ser abatido a la
especificadatipo . Devuelve verdadero si la expresin puede ser abatido a la
especificada tipo ; de lo contrario, devuelvefalse . Si vas a vaciar a la
especificada tipo est garantizado para tener xito o fracasar, se eleva un error en
tiempo de compilacin. Por ejemplo, 10 es Int y 10 es de cadena tanto elevar
los errores en tiempo de compilacin.
El as operador realiza un elenco condicional de la expresin a la
especificada tipo . El as operador devuelve un opcional de la especificada tipo . En
tiempo de ejecucin, si la conversin se realiza correctamente, el valor de la
expresin se envuelve en una opcional y regres; de lo contrario, el valor devuelto
es nulo . Si vas a vaciar a la especificada tipo est garantizada a fallar, se eleva un
error en tiempo de compilacin. Por ejemplo, la conversin a un tipo que no es ni una
subclase o superclase del tipo de laexpresin es un error.
El as operador realiza una conversin forzada de la expresin a la
especificada tipo . El as operador devuelve un valor de la especificada tipo , no un tipo
opcional. Si la conversin falla, se produce un error de ejecucin. El comportamiento
de x as T es el mismo que el comportamiento de (x como? T)! .
Para obtener ms informacin acerca de la conversin de tipos y para ver ejemplos que
utilizan los operadores de tipo de fundicin a presin, ver la conversin de tipos .
GRAMTICA DE UN OPERADOR DE TIPO CASTING
type-casting-operator istype
type-casting-operator astype
type-casting-operator as?type
Expresiones primarias
Expresiones primarias son el tipo ms bsico de expresin. Pueden ser utilizados como
expresiones de su propia, y se pueden combinar con otras fichas para hacer expresiones
de prefijos binarios, expresiones y expresiones de sufijo.
GRAMTICA DE UNA EXPRESIN PRIMARIA
primary-expression identifiergeneric-argument-clauseopt
primary-expression literal-expression
primary-expression self-expression
primary-expression superclass-expression
primary-expression closure-expression

311

primary-expression parenthesized-expression
primary-expression implicit-member-expression
primary-expression wildcard-expression
Expresin Literal
Una expresin literal consiste ya sea de un literal ordinario (tal como una cadena o un
nmero), una matriz o diccionario literal, o uno de los siguientes literales especiales:
Literal

Tipo

Valor

__FILE__

Cadena

El nombre del archivo en el que aparece.

__LINE__

Int

En la que aparece el nmero de lnea.

__COLUMN__

Int

El nmero de columna en el que comienza.

__FUNCTION__

Cadena

El nombre de la declaracin en la que aparece.

Dentro de una funcin, el valor de __FUNCTION__ es el nombre de esa funcin,


dentro de un mtodo que es el nombre de ese mtodo, dentro de un captador de
propiedad o Setter es el nombre de esa propiedad, dentro de los miembros especiales
como init o subndice es el nombre de esa palabra clave, y en el nivel superior de
un archivo es el nombre del mdulo actual.
Un literal de matriz es una coleccin ordenada de valores. Tiene la siguiente forma:
[ value 1 , value 2 , ... ]
La ltima expresin en la matriz puede ser seguida por una coma opcional. El valor de
un literal de matriz tiene tipo [T] , donde T es el tipo de las expresiones en su
interior. Si hay expresiones de varios tipos, T es su supertipo comn ms
cercano. Literales de matriz vacos se escriben utilizando un par vaco de corchetes y se
pueden utilizar para crear una matriz vaca de un tipo especificado.

var emptyArray: [Double] = []


Un literal diccionario es una coleccin desordenada de pares clave-valor. Tiene la
siguiente forma:
[ key 1 : value 1 , key 2 : value 2 , ... ]
La ltima expresin en el diccionario puede ser seguida por una coma opcional. El valor
de un literal diccionario tiene el tipo [KeyType: ValueType] ,
donde KeyType es el tipo de sus expresiones clave y ValueTypees el tipo de sus
expresiones de valor. Si hay expresiones de varios tipos, KeyType y ValueType son
el supertipo comn ms cercano por sus respectivos valores. Un diccionario vaco literal
se escribe como dos puntos dentro de un par de corchetes ( [:] ) para distinguirlo de un
array vaco literal. Puede utilizar un diccionario vaco literal para crear un diccionario
vaco literal de tipos de clave y valor especificados.

var emptyDictionary : [ Cadena : Doble ] = [:]


GRAMTICA DE UNA EXPRESIN LITERAL
literal-expression literal
literal-expression array-literal dictionary-literal

312

literal-expression __FILE__ __LINE__ __COLUMN__ __FUNCTION__


array-literal [array-literal-itemsopt]
array-literal-items array-literal-item,opt array-literal-item,array-literal-items
array-literal-item expression
dictionary-literal [dictionary-literal-items] [:]
dictionary-literal-items dictionary-literal-item,opt dictionary-literal-item,dictionaryliteral-items
dictionary-literal-item expression:expression
Auto Expresin
La auto expresin es una referencia explcita al tipo actual o instancia del tipo en el
que se produce. Tiene las siguientes formas:

self

self. member name

self[ subscript index ]

self( initializer arguments )

self.init( initializer arguments )


En un inicializador, subndice, o mtodo de instancia, s hace referencia a la instancia
actual del tipo en el que se produce. En un mtodo esttico o de clase, s se refiere al
tipo actual en el que se produce.
La auto expresin se utiliza para especificar el alcance cuando se accede a los
miembros, proporcionando desambiguacin cuando hay otra variable del mismo
nombre en su alcance, como por ejemplo un parmetro de la funcin. Por ejemplo:

class SomeClass {

var greeting: String

init(greeting: String) {

self.greeting = greeting

}
En un procedimiento de mutacin de un tipo de valor, se puede asignar una nueva
instancia de ese tipo de valor para uno mismo . Por ejemplo:

struct Point {

var x = 0.0, y = 0.0

mutating func moveByX(deltaX: Double, y deltaY: Double) {

self = Point(x: x + deltaX, y: y + deltaY)

313

GRAMTICA DE LA LIBRE EXPRESIN


self-expression self
self-expression self.identifier
self-expression self[expression]
self-expression self.init
Expresin Superclase
Una expresin superclase permite un interactan clase con su superclase. Cuenta con
una de las siguientes formas:

super. member name

super[ subscript index ]

super.init( initializer arguments )


La primera forma se utiliza para acceder a un miembro de la superclase. La segunda
forma se utiliza para acceder a la aplicacin subndice de la superclase. La tercera forma
se utiliza para acceder a un inicializador de la superclase.
Las subclases pueden utilizar una expresin superclase en la aplicacin de los
miembros, subndices y inicializadores para hacer uso de la aplicacin en su superclase.
GRAMTICA DE UNA EXPRESIN SUPERCLASE
superclass-expression superclass-method-expression superclass-subscriptexpression superclass-initializer-expression
superclass-method-expression super.identifier
superclass-subscript-expression super[expression]
superclass-initializer-expression super.init
Expresin Clausura
Una expresin de cierre crea un cierre, tambin conocido como una lambda o
una funcin annima en otros lenguajes de programacin. Al igual que las declaraciones
de funcin, los cierres contienen declaraciones que abonan, y capturan los valores de su
mbito circundante. Tiene la siguiente forma:

{ ( parameters ) -> return type in


statements

}
Los parmetros tienen la misma forma que los parmetros en una declaracin de la
funcin, tal como se describe en la declaracin de la funcin .
Hay varias formas especiales que permiten a los cierres que se escriben de manera ms
concisa:
Un cierre puede omitir los tipos de sus parmetros, el tipo de retorno, o ambos. Si
omite los nombres de los parmetros y de ambos tipos, omita el de palabra clave
antes de las sentencias. Si los tipos omitidos no se pueden deducir, se eleva un error
en tiempo de compilacin.

314

Un cierre puede omitir los nombres de sus parmetros. Sus parmetros son entonces
implcitamente nombrado $ seguidos de su posicin: $ 0 , $ 1 , $ 2 , y as
sucesivamente.
Un cierre que consta de slo una nica expresin se entiende para devolver el valor
de esa expresin.El contenido de esta expresin tambin se consideran cuando se
realiza la inferencia de tipos en la expresin de los alrededores.
Las siguientes expresiones de cierre son equivalentes:

myFunction {

(x: Int, y: Int) -> Int in

return x + y

myFunction {

(x, y) in

return x + y

myFunction { return $0 + $1 }

myFunction { $0 + $1 }
Para obtener informacin acerca de pasar un cierre como argumento a una funcin,
consulte Funcin de llamada Expresin .
Una expresin de cierre puede especificar explcitamente los valores que retrata tanto en
el mbito circundante utilizando una lista de captura . Una lista de captura est escrita
como una lista separada por comas entre corchetes, antes de que la lista de
parmetros. Si utiliza una lista de captura, tambin debe usar el de palabra clave,
incluso si se omite los nombres de parmetros, tipos de parmetros y el tipo de retorno.
Cada entrada en la lista de captura puede ser marcado como dbil o sin
dueo para capturar una referencia dbil o sin dueo al valor.

myFunction { print(self.title) } // captura fuerte

myFunction { [weak self] in print(self!.title) } // captura debil

myFunction { [unowned self] in print(self.title) } // captura sin dueo


Tambin puede enlazar una expresin arbitraria a un valor con nombre en la lista de
captura. Se evala la expresin cuando se forma el cierre, y captur con la resistencia
especificada. Por ejemplo:

// Dbil captura de "self.parent" como "padre"


myFunction { [weak parent = self.parent] in print(parent!.title) }
Para obtener ms informacin y ejemplos de expresiones de cierre,
consulte Expresiones de cierre .

315

GRAMTICA DE UNA EXPRESIN DE CIERRE


closure-expression {closure-signatureoptstatements}
closure-signature parameter-clausefunction-resultoptin
closure-signature identifier-listfunction-resultoptin
closure-signature capture-listparameter-clausefunction-resultoptin
closure-signature capture-listidentifier-listfunction-resultoptin
closure-signature capture-listin
capture-list [capture-specifierexpression]
capture-specifier dbil sin dueo sin dueo (seguro) sin
dueo (no seguro)
Implcita Expresin miembros
Un miembro de la expresin implcita es una forma abreviada para acceder a un
miembro de un tipo, tal como un caso de enumeracin o un mtodo de clase, en un
contexto en la inferencia de tipos puede determinar el tipo implcito. Tiene la siguiente
forma:
. member name
Por ejemplo:

var x = MyEnumeration.SomeValue

x = .AnotherValue

GRAMTICA DE UN MIEMBRO DE LA EXPRESIN IMPLCITA


implcita-miembro de la expresin . identificador
Expresin entre parntesis
Una expresin entre parntesis consiste en una lista separada por comas de expresiones
rodeadas por parntesis. Cada expresin puede tener un identificador opcional ante s,
separados por dos puntos ( : ).Tiene la siguiente forma:

( identifier 1 : expression 1 , identifier 2 : expression 2 , ... )


Utilice expresiones entre parntesis para crear tuplas y para pasar argumentos a una
llamada de funcin. Si slo hay un valor dentro de la expresin entre parntesis, el tipo
de la expresin entre parntesis es el tipo de ese valor. Por ejemplo, el tipo de la
expresin entre parntesis (1) es Int , no (Int) .
GRAMTICA DE UNA EXPRESIN CON PARNTESIS
parenthesized-expression (expression-element-listopt)
expression-element-list expression-element expression-element,expression-elementlist
expression-element expression identifier:expression

316

Expresin Comodn
Una expresin comodn se utiliza para ignorar explcitamente un valor durante una
asignacin. Por ejemplo, en la siguiente asignacin de 10 se asigna a x y 20 se ignora:

(x, _) = (10, 20)

// x is 10, 20 is ignored
GRAMTICA DE UNA EXPRESIN COMODN
wildcard-expresin _
Postfix Expresiones
Expresiones Postfix se forman mediante la aplicacin de un operador de sufijo u otra
sintaxis postfix a una expresin. Sintcticamente, cada expresin primaria es tambin
una expresin postfix.
La biblioteca estndar Swift ofrece los siguientes operadores de sufijo:
++ Incremento
- Disminuir
Para obtener informacin sobre el comportamiento de estos operadores,
consulte Operadores bsicos yOperadores avanzados .
GRAMTICA DE UNA EXPRESIN POSTFIX
postfix-expression primary-expression
postfix-expression postfix-expressionpostfix-operator
postfix-expression function-call-expression
postfix-expression initializer-expression
postfix-expression explicit-member-expression
postfix-expression postfix-self-expression
postfix-expression dynamic-type-expression
postfix-expression subscript-expression
postfix-expression forced-value-expression
postfix-expression optional-chaining-expression
Funcin Expresin Call
Una expresin de llamada a la funcin consiste en un nombre de la funcin seguido de
una lista separada por comas de los argumentos de la funcin entre
parntesis. Expresiones de llamada de funcin tiene la siguiente forma:

function name ( argument value 1 , argument value 2 )


El nombre de la funcin puede ser cualquier expresin cuyo valor es de un tipo de
funcin.
Si la definicin de funcin incluye nombres de sus parmetros, la llamada de funcin
tiene que incluir los nombres antes de sus valores de argumentos separados por dos
puntos ( : ). Este tipo de expresin llamada de funcin tiene la siguiente forma:

function name ( argument name 1 : argument value 1 , argument name 2 : argument


value 2 )
Una expresin de llamada a la funcin puede incluir un cierre posterior en forma de una
expresin de cierre inmediatamente despus del parntesis de cierre. El cierre posterior

317

se entiende como un argumento a la funcin, agregado despus del ltimo argumento


entre parntesis. Las siguientes llamadas a funciones son equivalentes:
// AlgunaFuncion toma un entero y un cierre como sus
argumentos

someFunction(x, {$0 == 13})

someFunction(x) {$0 == 13}


Si el cierre de salida es slo el argumento de la funcin, los parntesis pueden omitirse.
// AlgunaFuncion toma un cierre como nico argumento

myData.someMethod() {$0 == 13}

myData.someMethod {$0 == 13}

GRAMTICA DE UNA EXPRESIN DE LLAMADA A LA


FUNCIN
function-call-expression postfix-expressionparenthesized-expression
function-call-expression postfix-expressionparenthesized-expressionopttrailingclosure
trailing-closure closure-expression
Inicializador Expresin
Una expresin de inicializador proporciona acceso a inicializador de un tipo. Tiene la
siguiente forma:
expression .init( initializer arguments )
Se utiliza la expresin de inicializacin en una expresin de llamada a una funcin para
inicializar una nueva instancia de un tipo. A diferencia de las funciones, un inicializador
no puede ser utilizado como un valor. Por ejemplo:

var x = SomeClass.someClassFunction // ok

var y = SomeClass.init // error


Tambin puede utilizar una expresin de inicializador delegar en el inicializador de una
superclase.

class SomeSubClass: SomeSuperClass {

init() {

// Inicializacin subclase va aqu

super.init()

318

GRAMTICA DE UNA EXPRESIN DE INICIALIZADOR


initializer-expression postfix-expression.init
Explcita Expresin miembros
Un miembro de la expresin explcita permite el acceso a los miembros de un tipo
llamado, una tupla, o un mdulo. Se compone de un punto ( . ) entre el elemento y el
identificador de su miembro.
expresin . nombre de miembro
Los miembros de un tipo con nombre se nombran como parte de la declaracin o
ampliacin del tipo. Por ejemplo:

class SomeClass {

var someProperty = 42

let c = SomeClass()

let y = c.someProperty // Member access


Los miembros de una tupla se nombran de forma implcita mediante nmeros enteros en
el orden en que aparecen, a partir de cero. Por ejemplo:

var t = (10, 20, 30)

t.0 = t.1

// Ahora t es (20, 20, 30)


Los miembros de un mdulo de acceso a las declaraciones de alto nivel de ese mdulo.
GRAMTICA DE UNA EXPRESIN EXPLCITA MIEMBRO
explicit-member-expression postfix-expression.decimal-digits
explicit-member-expression postfix-expression.identifiergeneric-argument-clauseopt
Postfix Auto Expresin
Un sufijo auto expresin consiste de una expresin o el nombre de un tipo, seguido
inmediatamente por .self. Tiene las siguientes formas:

expression .self

type .self
La primera forma se evala como el valor de la expresin . Por
ejemplo, x.self evala como x .
La segunda forma se evala al valor del tipo . Utilice este formulario para acceder a un
tipo como un valor.Por ejemplo, porque SomeClass.self evala
al AlgunaClase mismo tipo, puede pasar a una funcin o mtodo que acepta un
argumento de nivel de tipo.

319

GRAMTICA DE LA LIBRE EXPRESIN


postfix-self-expression postfix-expression.self
Tipo Dinmico Expresin
A dynamicType expresin consiste en una expresin, seguida inmediatamente
por .dynamicType . Tiene la siguiente forma:
expression .dynamicType
La expresin no puede ser el nombre de un tipo. Todo el dynamicType expresin se
evala como el valor del tipo de tiempo de ejecucin de la expresin , como muestra el
siguiente ejemplo:

class SomeBaseClass {

class func printClassName() {

println("SomeBaseClass")

class SomeSubClass: SomeBaseClass {

override class func printClassName() {

println("SomeSubClass")

let someInstance: SomeBaseClass = SomeSubClass()

// SomeInstance es de tipo SomeBaseClass en tiempo de


compilacin, pero

// SomeInstance es de tipo SomeSubClass en tiempo de


ejecucin

someInstance.dynamicType.printClassName()

// Impresiones "SomeSubClass"


GRAMTICA DE UN TIPO DE EXPRESIN DINMICA
dynamic-type-expression postfix-expression.dynamicType
Expresin Subndice
Una expresin subndice proporciona acceso subndice usando el get y set de la
declaracin subndice correspondiente. Tiene la siguiente forma:

expresin [ expresiones de ndice ]


Para evaluar el valor de una expresin de subndice, el captador subndice para
la expresin de tipo 's se denomina con las expresiones de ndice pasados como los
parmetros subndice. Para establecer su valor, el setter subndice se llama de la misma
manera.

320

Para obtener informacin sobre las declaraciones de subndice, consulte Protocolo


Declaracin Subndice .
GRAMTICA DE UNA EXPRESIN SUBNDICE
subscript-expression postfix-expression[expression-list]
-Valor forzado Expresin
Una expresin-valor forzado desenvuelve un valor opcional que est seguro de que no
es nula . Tiene la siguiente forma:
expresin !
Si el valor de la expresin no es nula , el valor opcional es desenvuelto y volvi con el
tipo no opcional correspondiente. De lo contrario, se produce un error de ejecucin.
El valor de envolver de una expresin-valor forzado puede ser modificado, ya sea por
mutacin del valor en s, o mediante la asignacin a uno de los miembros del valor. Por
ejemplo:

var x: Int? = 0

x!++

// x is now 1

var someDictionary = ["a": [1, 2, 3], "b": [10, 20]]

someDictionary["a"]![0] = 100

// SomeDictionary es ahora ["a": [100, 2, 3], "b": [10,


20]]


GRAMTICA DE UNA EXPRESIN-VALOR FORZADO
forced-value-expression postfix-expression!
Opcional-encadenamiento Expresin
Una expresin opcional encadenamiento proporciona una sintaxis simplificada para el
uso de los valores opcionales en las expresiones de sufijo. Tiene la siguiente forma:

expression ?
Por su parte, el postfix ? operador simplemente devuelve el valor de su argumento
como un opcional.
Postfix expresiones que contienen una expresin opcional de encadenamiento se
evalan de una manera especial. Si la expresin-opcional encadenamiento es nulo ,
todas las otras operaciones en la expresin postfix son ignorados y toda la expresin
postfix evala como nula . Si la expresin-opcional encadenamiento no es nula , el
valor de la expresin-opcional encadenamiento se desenvuelve y se utiliza para evaluar
el resto de la expresin postfix. En cualquier caso, el valor de la expresin postfix sigue
siendo de un tipo opcional.
Si una expresin postfix que contiene una expresin opcional en cadena est anidado
dentro de otras expresiones de sufijo, slo la expresin ms externa devuelve un tipo

321

opcional. En el ejemplo siguiente, cuando c no es nula , su valor es sin envolver y se


utiliza para evaluar tanto .property y .performAction () , y toda la
expresin c? .property.performAction () tiene un valor de un tipo
opcional.

var c: SomeClass?

var result: Bool? = c?.property.performAction()


El siguiente ejemplo muestra el comportamiento del ejemplo anterior sin usar el
encadenamiento opcional.

if let unwrappedC = c {

result = unwrappedC.property.performAction()

}
El valor de envolver de una expresin opcional de encadenamiento puede ser
modificado, ya sea por mutacin del valor en s, o mediante la asignacin a uno de los
miembros del valor. Si el valor de la expresin-opcional encadenamiento es nula , no
se evala la expresin en el lado derecho del operador de asignacin. Por ejemplo:

func someFunctionWithSideEffects() -> Int {

return 42

var someDictionary = ["a": [1, 2, 3], "b": [10, 20]]

someDictionary["not here"]?[0] = someFunctionWithSideEffects()

// someFunctionWithSideEffects no se evala

// SomeDictionary sigue siendo ["a": [1, 2, 3], "b": [10,


20]]

someDictionary["a"]?[0] = someFunctionWithSideEffects()
()

// someFunctionWithSideEffects se evala

// SomeDictionary es ahora ["a": [100, 2, 3], "b": [10,


20]]


GRAMTICA DE UNA EXPRESIN-OPCIONAL
ENCADENAMIENTO
optional-chaining-expression postfix-expression?

Declaraciones
En Swift, hay dos tipos de declaraciones: declaraciones simples y estados de flujo de
control. Declaraciones simples son los ms comunes y consisten tanto en una expresin
o una declaracin. Estados de flujos de control se utilizan para controlar el flujo de

322

ejecucin de un programa. Hay tres tipos de sentencias de control de flujo en Swift:


sentencias de bucle, declaraciones de sucursales, y las declaraciones de transferencia de
control.
Las sentencias de bucle permiten que un bloque de cdigo que se ejecuta repetidamente,
declaraciones sucursales permiten un determinado bloque de cdigo que se ejecutar
slo cuando se cumplan ciertas condiciones, y las declaraciones de transferencia de
control proporcionan una forma de alterar el orden en el que se ejecuta el cdigo. Cada
tipo de declaracin de flujo de control se describe en detalle a continuacin.
Un punto y coma ( ; ) opcionalmente puede aparecer despus de cualquier declaracin
y se utiliza para separar varias declaraciones si aparecen en la misma lnea.
GRAMTICA DE UNA DECLARACIN
statement expression;opt
statement declaration;opt
statement loop-statement;opt
statement branch-statement;opt
statement labeled-statement;opt
statement control-transfer-statement;opt
statements statementstatementsopt
Declaraciones Loop
Sentencias de bucle permiten un bloque de cdigo que se ejecuta repetidamente,
dependiendo de las condiciones especificadas en el bucle. Swift tiene cuatro sentencias
de bucle: una para la declaracin, unapara - en la declaracin,
una mientras declaracin, y un do - mientras comunicado.
El flujo de control en un comunicado de bucle se puede cambiar por una ruptura y
una declaracin continuardeclaracin y se discute en sentencia break y Continuar
Declaracin de abajo.
GRAMTICA DE UNA SENTENCIA DE BUCLE
loop-statement for-statement
loop-statement for-in-statement
loop-statement while-statement
loop-statement do-while-statement
Para Declaracin
Una de declaracin permite un bloque de cdigo que se ejecuta repetidamente mientras
incrementando un contador, siempre y cuando una condicin sigue siendo cierto.
Una de instruccin tiene la siguiente forma:

for initialization ; condition ; increment {


statements

}
Los punto y coma entre la inicializacin , condicin , y la subasta se requieren. Los
apoyos en torno a lasdeclaraciones tambin son necesarios en el cuerpo del bucle.
Una de sentencia se ejecuta de la siguiente manera:

323

1. La inicializacin se evala slo una vez. Normalmente se utiliza para declarar e


inicializar las variables que se necesitan para el resto del ciclo.
2. La condicin se evala la expresin.
Si cierto , el programa ejecuta las declaraciones , y la ejecucin contina al paso
3 Si falso , el programa no se ejecuta las declaraciones o el incremento de la
expresin, y el programa ha terminado de ejecutar el de declaracin.
3. El incremento se evala la expresin, y la ejecucin vuelve al paso 2.
Las variables definidas dentro de la inicializacin slo son vlidos en el mbito de
la de declaracin en s.
El valor de la condicin de expresin debe tener un tipo que se ajusta a
la BooleanType protocolo.
GRAMTICA DE UNA SENTENCIA FOR
for-statement forfor-initopt;expressionopt;expressionoptcode-block
for-statement for(for-initopt;expressionopt;expressionopt)code-block
for-init variable-declaration expression-list
Para-In Declaracin
Una de - en la declaracin permite un bloque de cdigo que se ejecuta una vez para
cada elemento de una coleccin (o de cualquier tipo) que se ajusta a
la SequenceType protocolo.
Una de - en la declaracin tiene la siguiente forma:

for item in collection {


statements

}
El generar mtodo se llama en la coleccin de expresin para obtener un valor de un
tipo que es generador, un tipo que se ajusta a la GeneratorType protocolo. El
programa comienza la ejecucin de un bucle mediante una llamada
al siguiente mtodo en la secuencia. Si el valor devuelto no es Ninguno , se le
asigna a la partidapatrn, el programa ejecuta las declaraciones , y luego contina la
ejecucin en el principio del bucle. De lo contrario, el programa no realiza cesin o
ejecutar las sentencias , y que se haya ejecutado la para - encomunicado.
GRAMTICA DE UNA DECLARACIN FOR-IN
for-in-statement forpatterninexpressioncode-block
Mientras Declaracin
Un mientras declaracin permite un bloque de cdigo que se ejecuta repetidamente,
siempre y cuando una condicin sigue siendo cierto.
A mientras que la declaracin tiene la siguiente forma:

while condition {
statements

324

}
A mientras sentencia se ejecuta de la siguiente manera:
1. La condicin es evaluada.
Si cierto , la ejecucin contina con el paso 2 Si falso , el programa ha
terminado de ejecutar elmientras comunicado.
2. El programa ejecuta las declaraciones , y la ejecucin vuelve al paso 1.
Debido a que el valor de la condicin es evaluada antes de que las declaraciones se
ejecutan, lasdeclaraciones en una mientras que la declaracin se pueden ejecutar
cero o ms veces.
El valor de la condicin debe tener un tipo que se ajusta a
la BooleanType protocolo. La condicin tambin puede ser una declaracin de unin
opcional, como se discute en Opcional Binding .
GRAMTICA DE UNA SENTENCIA WHILE
while-statement whilewhile-conditioncode-block
while-condition expression declaration
Hgalo hasta instruccin (Do-While)
A do while sentencia permite un bloque de cdigo que se ejecutar una o varias
veces, siempre y cuando una condicin se mantiene fiel.
A do while declaracin tiene la siguiente forma:

do {
statements

} while condition
A do while sentencia se ejecuta de la siguiente manera:
1. El programa ejecuta las declaraciones , y la ejecucin contina con el paso 2.
2. La condicin es evaluada.
Si cierto , la ejecucin vuelve al paso 1 Si falso , el programa ha terminado de
ejecutar el do - mientrascomunicado.
Debido a que el valor de la condicin se evala despus de las declaraciones se
ejecutan, las declaracionesen un do - , mientras que la declaracin se ejecutan al
menos una vez.
El valor de la condicin debe tener un tipo que se ajusta a
la BooleanType protocolo. La condicin tambin puede ser una declaracin de unin
opcional, como se discute en Opcional Binding .
GRAMTICA DE UNA DECLARACIN DO-WHILE
do-while-statement docode-blockwhilewhile-condition
Declaraciones Branch
Declaraciones Branch permiten al programa para ejecutar ciertas partes de cdigo en
funcin del valor de una o ms condiciones. Los valores de las condiciones
especificadas en un comunicado rama controlan la forma, por lo tanto, lo que el bloque

325

de cdigo se ejecuta el programa se bifurca y,. Swift tiene dos declaraciones sucursal:
un si declaracin y un interruptor comunicado.
El flujo de control en un interruptor de declaracin puede ser modificada por
una ruptura declaracin y se discute en sentencia break abajo.
GRAMTICA DE UNA DECLARACIN DE LA RAMA
branch-statement if-statement
branch-statement switch-statement
Si Declaracin
Un if de declaracin se utiliza para ejecutar cdigo basado en la evaluacin de una o
ms condiciones.
Hay dos formas bsicas de un if declaracin. En cada formulario, se requiere que las
llaves de apertura y cierre.
La primera forma permite que el cdigo se ejecuta slo cuando una condicin es
verdadera y tiene la siguiente forma:

if condition {
statements

}
La segunda forma de un si declaracin proporciona un adicional clusula
else (introducido por la otra palabra clave) y se utiliza para ejecutar una parte de
cdigo cuando la condicin es verdadera y otra parte del cdigo cuando la misma
condicin es falsa. Cuando una sola clusula ms est presente, un caso
de declaracin tiene la siguiente forma:

if condition {
statements to execute if condition is true

} else {
statements to execute if condition is false

}
La clusula else de un caso de declaracin puede contener otro si la declaracin
para poner a prueba ms de una condicin. Un caso de declaracin encadenado
juntos de esta manera tiene la siguiente forma:

if condition 1 {
statements to execute if condition 1 is true

} else if condition 2 {
statements to execute if condition 2 is true

} else {
statements to execute if both conditions are false

326

}
El valor de cualquier condicin en un caso de declaracin debe tener un tipo que se
ajusta a la BooleanTypeprotocolo. La condicin tambin puede ser una declaracin
de unin opcional, como se discute en Opcional Binding .
GRAMTICA DE UNA SENTENCIA IF
if-statement ifif-conditioncode-blockelse-clauseopt
if-condition expression declaration
else-clause elsecode-block elseif-statement
Sentencia switch
Un switch de declaracin permite que ciertos bloques de cdigo a ejecutar en
funcin del valor de una expresin de control.
Una sentencia switch tiene la siguiente forma:

switch control expression {

case pattern 1 :

statements

case pattern 2 where condition :


statements

case pattern 3 where condition ,

pattern 4 where condition :


statements

default:
statements

}
La expresin de control del switch de declaracin se evala y se compara entonces
con los patrones especificados en cada caso. Si se encuentra una coincidencia, el
programa ejecuta las declaraciones que figuran en el marco de ese caso. El alcance de
cada caso no puede estar vaco. Como resultado, debe incluir al menos una declaracin
despus de los dos puntos ( : ) de cada etiqueta de la caja. Use un solo break
declaracin si usted no tiene intencin de ejecutar cualquier cdigo en el cuerpo de un
caso compatible.
Los valores de las expresiones de su cdigo puede ramificar en son muy flexibles. Por
ejemplo, adems de los valores de los tipos escalares, como enteros y caracteres, su
cdigo puede ramificarse en los valores de cualquier tipo, incluidos los nmeros de
punto flotante, cadenas, tuplas, las instancias de clases personalizadas, y opcionales. El
valor de la expresin de control incluso puede ser igualada al valor de un caso en una
enumeracin y se comprueba para su inclusin en un rango especificado de

327

valores. Para obtener ejemplos de cmo utilizar estos diversos tipos de valores en los
switch declaraciones, consulte Switch en el control de flujo captulo.
Un switch de caso puede contener opcionalmente una expresin guardia despus de
cada patrn. Unprotector de expresin se introduce por la palabra clave , where
seguido por una expresin, y se utiliza para proporcionar una condicin adicional antes
de un patrn en un caso se considera adaptado a la expresin de control . Si una
expresin guardia est presente, las declaraciones en el caso pertinente slo se ejecutan
si el valor de la expresin de control coincide con uno de los patrones del caso y la
expresin guardia evala comoverdadera . Por ejemplo, una expresin de
control coincide con el caso en el ejemplo siguiente slo si es una tupla que contiene
dos elementos del mismo valor, tales como (1, 1) .

case let (x, y) where x == y:


Como muestra el ejemplo de arriba muestra, los patrones en un caso tambin se pueden
unir constantes utilizando la palabra clave let (tambin pueden unirse variables
utilizando la palabra clave var ). Estas constantes (o variables) a continuacin, se
puede hacer referencia en una expresin de guardia correspondiente y durante todo el
resto del cdigo dentro del alcance de la caja. Dicho esto, si el caso contiene varios
patrones que coinciden con la expresin de control, ninguno de esos patrones puede
contener enlaces constantes o variables.
Un switch de declaracin tambin puede incluir un caso default, introducido por la
palabra clave default. El cdigo dentro de un caso por defecto slo se ejecuta si no
hay otros casos coinciden con la expresin de control. Un switch de declaracin
puede incluir slo un caso por defecto, que debe aparecer al final del switch
comunicado.
Aunque el orden de ejecucin real de las operaciones de bsqueda de patrones, y, en
particular, el orden de evaluacin de los patrones de los casos, no se especifica,
bsqueda de patrones en un interruptordeclaracin se comporta como si la
evaluacin se realiza con el fin-esa fuente es, el orden en el que aparecer en el cdigo
fuente. Como resultado, si hay varios casos contienen patrones que dan como resultado
el mismo valor, y por lo tanto puede coincidir con el valor de la expresin de control, el
programa ejecuta slo el cdigo en el primer caso a juego con el fin de origen.
Declaraciones interruptor debe ser exhaustiva
En Swift, cada posible valor de tipo de control de la expresin debe coincidir con el
valor de al menos un patrn de un caso. Cuando esto simplemente no es viable (por
ejemplo, cuando el tipo de la expresin de control es Int ), puede incluir un caso por
defecto para satisfacer el requisito.
La ejecucin no se caiga a travs de casos Implcitamente
Despus de que el cdigo dentro de un caso emparejado ha terminado de ejecutarse, el
programa sale delinterruptor comunicado. La ejecucin del programa no contina
o "caer a travs de" al siguiente caso o caso por defecto. Dicho esto, si quieres continuar
la ejecucin de un caso a otro, explcitamente incluye unfallthrough declaracin,
que consiste simplemente en la palabra clave fallthrough , en el caso de la que
desea que contine la ejecucin. Para obtener ms informacin acerca de
la fallthrough declaracin, veaDeclaracin fallthrough continuacin.

328

GRAMTICA DE UNA SENTENCIA SWITCH


switch-statement switchexpression{switch-casesopt}
switch-cases switch-caseswitch-casesopt
switch-case case-labelstatements default-labelstatements
switch-case case-label; default-label;
case-label casecase-item-list:
case-item-list patternguard-clauseopt patternguard-clauseopt,case-item-list
default-label default:
guard-clause whereguard-expression
guard-expression expression
Declaracin Etiquetada
Usted puede prefijar una sentencia de bucle o un switch declaracin con una etiqueta
de declaracin , que consiste en el nombre de la etiqueta seguido inmediatamente por
dos puntos (:). Utilice las etiquetas de sentencia con break y continue
declaraciones al ser explcito acerca de cmo desea cambiar el flujo de control en un
comunicado de bucle o un switch de declaracin, como se explica en la sentencia
break yContinuar Declaracin de abajo.
El alcance de una sentencia etiquetada es toda la instruccin que sigue a la etiqueta
comunicado. Puede anidar declaraciones etiquetado, pero el nombre de cada etiqueta de
declaracin debe ser nico.
Para obtener ms informacin y ver ejemplos de cmo utilizar las etiquetas de
sentencia, consulteDeclaraciones Etiquetada en el control de flujo captulo.
GRAMTICA DE UNA SENTENCIA ETIQUETADA
control-transfer-statement break-statement
control-transfer-statement continue-statement
control-transfer-statement fallthrough-statement
control-transfer-statement return-statement
Declaraciones de transferencia de control
Enunciados de transferencia de control puede cambiar el orden en el que el cdigo de su
programa es ejecutado por incondicionalmente transferir el control del programa a partir
de una sola pieza de cdigo a otro. Swift tiene cuatro enunciados de transferencia de
control: una ruptura , una declaracin continuardeclaracin,
un fallthrough declaracin, y un retorno de los estados.
GRAMTICA DE UNA DECLARACIN DE TRANSFERENCIA DE
CONTROL
control-transfer-statement break-statement
control-transfer-statement continue-statement
control-transfer-statement fallthrough-statement
control-transfer-statement return-statement

329

Sentencia break
Un break declaracin termina la ejecucin del programa de un bucle o un switch
de declaracin. Una break comunicado puede consistir en slo la palabra
clave break, o puede consistir en la palabra clave break seguido del nombre de una
etiqueta de declaracin, como se muestra a continuacin.

break

break label name


Cuando una break declaracin es seguida por el nombre de una etiqueta de
declaracin, termina la ejecucin del programa del bucle o switch sentencia indicada
por esa etiqueta.
Cuando una break declaracin no es seguido por el nombre de una etiqueta de
declaracin, termina la ejecucin del programa del switch de declaracin o la
sentencia de bucle ms interno en el que se produce.
En ambos casos, el control del programa se transfiere entonces a la primera lnea de
cdigo siguiente que encierra el bucle o switch de declaracin, si los hubiere.
Para obtener ejemplos de cmo utilizar un break declaracin,
ver Receso y etiquetadas declaraciones en el control de flujo captulo.
GRAMTICA DE UNA SENTENCIA BREAK
break-statement breaklabel-nameopt
Continuar Declaracin
A continue declaracin termina la ejecucin del programa de la iteracin actual de
una sentencia de bucle, pero no detiene la ejecucin de la sentencia de
bucle. A seguir comunicado puede consistir en slo la palabra clave continue , o
puede consistir en la palabra clave siguen seguido del nombre de una etiqueta de
declaracin, como se muestra a continuacin.

continue

continue label name


Cuando un continue declaracin es seguida por el nombre de una etiqueta de
declaracin, termina la ejecucin del programa de la iteracin actual de la sentencia de
bucle llamado por esa etiqueta.
Cuando un continue declaracin no es seguido por el nombre de una etiqueta de
declaracin, termina la ejecucin del programa de la iteracin actual de la sentencia de
bucle ms interno en el que se produce.
En ambos casos, el control del programa se transfiere entonces a la condicin de la
sentencia de bucle encierra.
En una for declaracin, la expresin de incremento todava se evala despus de
la continue se ejecuta declaracin, debido a que la expresin de incremento se
evala despus de la ejecucin del cuerpo del bucle.
Para ver ejemplos de cmo usar un continue declaracin,
vase Continuar y Etiquetada declaraciones en elcontrol de flujo captulo.

330

GRAMTICA DE UNA SENTENCIA CONTINUE


continue-statement continuelabel-nameopt
Declaracin fallthrough
A fallthrough declaracin consiste en la fallthrough palabra clave y slo se
produce en un bloque caso de un switch comunicado. A fallthrough causas de
los estados de ejecucin del programa para continuar de un caso en un switch
declaracin al siguiente caso. La ejecucin del programa contina con el siguiente caso,
incluso si los patrones de la etiqueta de la caja no coinciden con el valor del switch
decontrol de la expresin de la declaracin.
Un fallthrough declaracin puede aparecer en cualquier lugar dentro de
un switch de declaracin, no slo como la ltima instruccin de un bloque caso,
pero no puede ser utilizado en el caso de bloque final.Tambin no puede transferir el
control en un bloque caso cuyo patrn contiene patrones de enlace de valor.
Para ver un ejemplo de cmo utilizar un fallthrough declaracin en
un interruptor de declaracin, verdeclaraciones de transferencia de control en
el control de flujo captulo.
GRAMTICA DE UNA DECLARACIN FALLTHROUGH
fallthrough-statement fallthrough
Declaracin de retorno
Un retorno declaracin se produce slo en el cuerpo de una ejecucin del programa
funcin o mtodo definicin y las causas para volver a la funcin de llamada o
mtodo. La ejecucin del programa contina en el punto inmediatamente despus de la
llamada a una funcin o mtodo.
Un retorno comunicado puede consistir en slo la palabra clave de retorno , o
puede consistir en la palabra clave de retorno seguida de una expresin, como se
muestra a continuacin.

return

return expression
Cuando un return declaracin es seguida por una expresin, el valor de la expresin
se devuelve a la funcin de llamada o mtodo. Si el valor de la expresin no coincide
con el valor del tipo de retorno declarado en la declaracin de la funcin o mtodo, el
valor de la expresin se convierte en el tipo de retorno antes de que se devuelve a la
funcin de llamada o mtodo.
Cuando un return declaracin no es seguido por una expresin, que puede ser
utilizado slo para volver de una funcin o mtodo que no devuelve un valor (es decir,
cuando el tipo de retorno de la funcin o mtodo esvaco o () ).
GRAMTICA DE UNA SENTENCIA RETURN
return-statement returnexpressionopt

331


Declaraciones
Una declaracin introduce un nuevo nombre o construir en su programa. Por ejemplo,
utiliza las declaraciones de introducir funciones y mtodos, variables y constantes, y
para definir nuevos tipos de enumeracin, estructura, clase, y de protocolo, con
nombre. Tambin puede utilizar una declaracin para extender el comportamiento de un
tipo con nombre existente e importar smbolos en el programa que se declar en otro
lugar.
En Swift, la mayora de las declaraciones son tambin las definiciones en el sentido de
que se implementan o inicializadas a la vez que se declaran. Dicho esto, ya que los
protocolos no implementan sus miembros, la mayora de los miembros de protocolo son
slo declaraciones. Por comodidad y porque la distincin no es tan importante en el
Swift, el plazo de declaracin abarca tanto las declaraciones y definiciones.
GRAMTICA DE UNA DECLARACIN
declaration import-declaration
declaration constant-declaration
declaration variable-declaration
declaration typealias-declaration
declaration function-declaration
declaration enum-declaration
declaration struct-declaration
declaration class-declaration
declaration protocol-declaration
declaration initializer-declaration
declaration deinitializer-declaration
declaration extension-declaration
declaration subscript-declaration
declaration operator-declaration
declarations declarationdeclarationsopt
De nivel superior Cdigo
El cdigo de nivel superior en un archivo fuente Swift consiste en cero o ms
declaraciones, declaraciones y expresiones. Por defecto, las variables, constantes, y
otras declaraciones con nombre que se declar en el nivel superior de un archivo de
origen se puede acceder al cdigo en cada archivo de origen que es parte del mismo
mdulo. Puede anular este comportamiento predeterminado marcando la declaracin
con un modificador de nivel de acceso, como se describe en los niveles de control de
acceso .
GRAMTICA DE UNA DECLARACIN DE ALTO NIVEL
top-level-declaration statementsopt

332

Bloques de Cdigo
Un bloque de cdigo es utilizado por una variedad de declaraciones y las estructuras de
control de los estados agrupar. Tiene la siguiente forma:

{
statements

}
Las declaraciones dentro de un bloque de cdigo incluyen declaraciones, expresiones y
otros tipos de sentencias y se ejecutan en el orden en que aparecen en el cdigo fuente.
GRAMTICA DE UN BLOQUE DE CDIGO
code-block {statementsopt}
Declaracin de Importacin
Una declaracin de importacin le permite acceder a los smbolos que se declaran fuera
del archivo actual.La forma bsica importa todo el mdulo; que consiste en
la importacin de palabra clave seguida de un nombre de mdulo:

import module
Proporcionar ms lmites que se detalle smbolos importan-puede especificar un
submdulo especfico o una declaracin especfica dentro de un grupo o
mdulo. Cuando se utiliza esta forma detallada, slo el smbolo importado (y no el
mdulo que lo declara) se pone a disposicin en el mbito actual.

import import kind module . symbol name

import module . submodule

GRAMTICA DE UNA DECLARACIN DE IMPORTACIN


import-declaration attributesoptimportimport-kindoptimport-path
import-kind typealias struct class enum protocol var func
import-path import-path-identifier import-path-identifier.import-path
import-path-identifier identifier operator
Declaracin Constant
Una declaracin de constante introduce un valor constante con nombre en su
programa. Declaraciones de constantes se declaran utilizando la palabra clave dejar y
tienen la siguiente forma:

let constant name : type = expression


Una declaracin define una constante de unin entre el inmutable nombre de la
constante y el valor del inicializador de expresin ; despus de que el valor de una
constante se establece, no se puede cambiar.Dicho esto, si una constante se inicializa
con un objeto de clase, el objeto en s mismo puede cambiar, pero la unin entre el
nombre de la constante y el objeto que se refiere a que no puede.

333

Cuando se declara una constante en el mbito global, se debe inicializar con un


valor. Cuando una declaracin de constante se produce en el contexto de una
declaracin de clase o estructura, se considera una propiedad constante . Declaraciones
constantes no estn computados propiedades y por lo tanto no tienen getters o setters.
Si el nombre de constante de una declaracin constante es un patrn de tupla, el nombre
de cada elemento de la tupla est destinada a el valor correspondiente en el
inicializador expresin .

let (firstNumber, secondNumber) = (10, 42)

En este ejemplo, primerNumero es una constante con nombre para el valor 10 ,


y secondNumber es una constante llamada para el valor 42 . Ambas constantes ahora
se pueden utilizar independientemente:

// imprime "El primer nmero es 10"

println("The first number is \(firstNumber).")


println("The second number is \(secondNumber).")

// imprime "El segundo nmero es 42"


La anotacin de tipo ( : tipo ) es opcional en una declaracin de constante cuando el
tipo del nombre de la constante se puede deducir, como se describe en Tipo de
inferencia .
Para declarar una propiedad constante esttica, marque la declaracin con
la esttica modificador declaracin. Las propiedades estticas se discuten en Tipo
de Propiedades .
Para obtener ms informacin acerca de las constantes y de orientacin sobre cundo
usarlos, veaConstantes y Variables y propiedades almacenadas .
GRAMTICA DE UNA DECLARACIN DE CONSTANTE
constant-declaration attributesoptdeclaration-modifiersoptletpattern-initializer-list
pattern-initializer-list pattern-initializer pattern-initializer,pattern-initializer-list
pattern-initializer patterninitializeropt
initializer =expression
Declaracin de variables
Una declaracin de variable introduce un valor con nombre variable en su programa y
se declara mediante la palabra clave var .
Las declaraciones de variables tienen varias formas que declaran diferentes tipos de
llamados, valores mutables, incluyendo variables almacenadas y calculadas y
propiedades, variable almacenada y observadores de propiedad y propiedades de las
variables estticas. La forma apropiada de usar depende del mbito en el que se declara
la variable y el tipo de variable que se va a declarar.
NOTA
Tambin puede declarar propiedades en el contexto de una declaracin de protocolo, tal
como se describe en el Protocolo de Declaracin de bienes .

334

Puede anular una propiedad en una subclase marcando declaracin de propiedad de la


subclase con laanulacin modificador de declaracin, como se describe
en Overriding .
Propiedades de variables almacenados Variables y almacenados
El siguiente formulario declara una propiedad almacenada variable o almacenada:

var variable name : type = expression


Usted define esta forma de una declaracin de variable en el mbito global, el alcance
local de una funcin, o en el contexto de una declaracin de clase o estructura. Cuando
una declaracin de variable de esta forma se declara en el mbito global o del mbito
local de una funcin, que se conoce como una variable almacenada .Cuando se declara
en el contexto de una declaracin de clase o estructura, que se conoce como
unapropiedad de variable almacenada .
El inicializador de expresin no puede estar presente en una declaracin de protocolo,
pero en todos los dems contextos, el inicializador de expresin es opcional. Dicho esto,
si no inicializador expresin est presente, la declaracin de variables debe incluir una
anotacin de tipo explcita ( : tipo ).
Al igual que con declaraciones de constantes, si el nombre de la variable es un patrn
de tupla, el nombre de cada elemento de la tupla est destinada a el valor
correspondiente en el inicializador expresin .
Como su nombre indica, el valor de una variable almacenada o guardada propiedad
variable se almacena en la memoria.
Las variables calculadas y Propiedades calculadas
El siguiente formulario declara una propiedad calculada variable o computarizada:

var variable name : type {

get {
statements

set( setter name ) {


statements

}
Usted define esta forma de una declaracin de variable en el mbito global, el alcance
local de una funcin, o en el contexto de una estructura, enumeracin o ampliacin de
declaracin de clase. Cuando una declaracin de variable de esta forma se declara en el
mbito global o del mbito local de una funcin, que se conoce como la variable
calculada . Cuando se declara en el contexto de una estructura o ampliacin de
declaracin de clase, que se conoce como una propiedad calculada .
El captador se utiliza para leer el valor, y el colocador se utiliza para escribir el
valor. La clusula setter es opcional, y cuando slo se necesita un captador, puede
omitir ambas clusulas y devuelva el valor solicitado directamente, como se describe

335

en slo lectura computarizada Propiedades . Pero si usted proporciona una clusula


setter, tambin debe proporcionar una clusula getter.
El nombre del organismo y los parntesis que encierran es opcional. Si proporciona un
nombre de setter, que se utiliza como el nombre del parmetro al setter. Si no se
proporciona un nombre de setter, el nombre del parmetro por defecto para el setter
es nuevoValor , como se describe en taquigrafa Declaracin Setter .
A diferencia de propiedades de las variables almacenadas valores con nombre y
almacenados, el valor de un valor con nombre computarizada o una propiedad calculada
no se almacena en la memoria.
Para obtener ms informacin y ver ejemplos de propiedades calculadas,
vea Propiedades calculadas .
Observadores variable almacenada y observadores de Propiedad
Tambin puede declarar una variable almacenada o propiedad
con willSet y didSet observadores. Una variable o propiedad almacenada
declarado con observadores tiene la siguiente forma:

var variable name : type = expression {

willSet( setter name ) {


statements

didSet( setter name ) {


statements

}
Usted define esta forma de una declaracin de variable en el mbito global, el alcance
local de una funcin, o en el contexto de una declaracin de clase o estructura. Cuando
una declaracin de variable de esta forma se declara en el mbito global o del mbito
local de una funcin, los observadores se refieren comoobservadores variables
almacenadas . Cuando se declara en el contexto de una declaracin de clase o
estructura, los observadores se les conoce como los observadores de propiedad .
Puede agregar observadores de propiedad a cualquier propiedad almacenado. Tambin
puede agregar los observadores de propiedad a cualquier propiedad heredada (si
almacena o calcula) por razones imperiosas de la propiedad dentro de una subclase,
como se describe en observadores Overriding propiedad .
El inicializador de expresin es opcional en el contexto de una declaracin de clase o
estructura, pero requerido en otro lugar. Se requiere que la anotacin de tipo en todas las
declaraciones de variables que incluyen observadores, sin importar el contexto en el que
se declaran.
Los willSet y didSet observadores proporcionan una manera de observar (y para
responder adecuadamente) cuando se est estableciendo el valor de una variable o
propiedad. Los observadores no se les llama cuando la variable o propiedad se inicializa

336

por primera vez. En su lugar, se les llama slo cuando el valor se establece fuera de un
contexto de inicializacin.
A willSet observador se llama justo antes de que se fije el valor de la variable o
propiedad. El nuevo valor se pasa a la willSet observador como una constante, y por
lo tanto no se puede cambiar en la aplicacin de
lawillSet clusula. El didSet observador se llama inmediatamente despus de que
el nuevo valor se establece.En contraste con la willSet observador, el antiguo valor
de la variable o la propiedad se pasa al didSetobservador en caso de que todava
necesita el acceso a la misma. Dicho esto, si se asigna un valor a una variable o
propiedad dentro de su propio didSet clusula observador, ese nuevo valor que asigne
sustituir a la que se acaba de establecer y pasa al willSet observador.
El nombre del organismo y que encierran entre parntesis en
las willSet y didSet clusulas son opcionales.Si usted proporciona nombres setter,
que se utilizan como los nombres de los parmetros a
los willSet ydidSet observadores. Si usted no proporciona nombres setter, el
nombre del parmetro por defecto para elwillSet observador es nuevoValor y el
nombre del parmetro por defecto para el didSet observador esoldValue .
El didSet clusula es opcional cuando se proporciona un willSet clusula. Del
mismo modo, la willSetclusula es opcional cuando se proporciona
un didSet clusula.
Para obtener ms informacin y para ver un ejemplo de cmo utilizar los observadores
de propiedades, consulte Observadores propiedad .
Clase y propiedades de variables estticas
Para declarar una clase computarizada propiedad, marque la declaracin con
la clase modificador declaracin. Para declarar una propiedad esttica variables,
marque la declaracin con la estticamodificador declaracin. Las propiedades de
clase y estticas se discuten en Tipo de Propiedades .
GRAMTICA DE UNA DECLARACIN DE VARIABLE
variable-declaration variable-declaration-headpattern-initializer-list
variable-declaration variable-declaration-headvariable-nametype-annotationcodeblock
variable-declaration variable-declaration-headvariable-nametype-annotationgettersetter-block
variable-declaration variable-declaration-headvariable-nametype-annotationgettersetter-keyword-block
variable-declaration variable-declaration-headvariable-nametype-annotationinitializeroptwillSet-didSet-block
variable-declaration-head attributesoptdeclaration-modifiersoptvar
variable-name identifier
getter-setter-block {getter-clausesetter-clauseopt}
getter-setter-block {setter-clausegetter-clause}
getter-clause attributesoptgetcode-block
setter-clause attributesoptsetsetter-nameoptcode-block

337

setter-name (identifier)
getter-setter-keyword-block {getter-keyword-clausesetter-keyword-clauseopt}
getter-setter-keyword-block {setter-keyword-clausegetter-keyword-clause}
getter-keyword-clause attributesoptget
setter-keyword-clause attributesoptset
willSet-didSet-block {willSet-clausedidSet-clauseopt}
willSet-didSet-block {didSet-clausewillSet-clause}
willSet-clause attributesoptwillSetsetter-nameoptcode-block
didSet-clause attributesoptdidSetsetter-nameoptcode-block
Escriba Declaracin Alias
Una declaracin de tipo alias introduce un alias llamado de un tipo existente en su
programa. Tipo declaraciones de alias se declaran utilizando la palabra
clave typealias y tienen la siguiente forma:

typealias name = existing type


Despus de que se declare un alias tipo, el alias nombre se puede utilizar en lugar
del tipo existente en todas partes en su programa. El tipo existente puede ser un tipo con
nombre o un tipo compuesto. Tipo alias no crean nuevos tipos; simplemente permiten
un nombre para referirse a un tipo existente.
Consulte tambin Protocolo Asociadas Declaracin Tipo .
GRAMTICA DE UNA DECLARACIN TYPEALIAS
typealias-declaration typealias-headtypealias-assignment
typealias-head attributesoptaccess-level-modifieropttypealiastypealias-name
typealias-name identifier
typealias-assignment =type
Declaracin de funciones
Una declaracin de la funcin introduce una funcin o un mtodo en su programa. Una
funcin declarada en el contexto de la clase, estructura, enumeracin, o protocolo se
conoce como un mtodo . Las declaraciones de funciones se declaran usando la palabra
clave func y tienen la siguiente forma:

func function name ( parameters ) -> return type {


statements

}
If the function has a return type of Void, the return type can be omitted as follows:

func function name ( parameters ) {


statements

}
El tipo de cada parmetro debe ser incluido-no se puede inferir. Aunque los parmetros
a una funcin son constantes por defecto, usted puede escribir dej delante del nombre

338

de un parmetro para enfatizar este comportamiento. Escribir var delante del nombre
de un parmetro para que sea una variable, la determinacin del alcance cualquier
cambio realizado en la variable slo para el cuerpo de la funcin, o escribir inout para
hacer esos cambios se aplican tambin al argumento de que fue aprobada en el alcance
de la persona que llama. Para un anlisis de los parmetros de salida, consulte InParmetros que .
Las funciones pueden devolver varios valores con un tipo tupla como el tipo de retorno
de la funcin.
Una definicin de funcin puede aparecer dentro de otra declaracin de la funcin. Este
tipo de funcin se conoce como una funcin anidada . Para un anlisis de las funciones
anidadas, consulte Funciones anidadas.
Nombres de parmetros
Parmetros de la funcin son una lista separada por comas donde cada parmetro tiene
una de varias formas. El orden de argumentos en una llamada a la funcin debe
coincidir con el orden de los parmetros en la declaracin de la funcin. La entrada ms
simple en una lista de parmetros tiene la siguiente forma:
parameter name : parameter type
Para los parmetros de funcin, el nombre del parmetro se utiliza en el cuerpo de la
funcin, pero no se utiliza cuando se llama a la funcin. Para los parmetros del
mtodo, el nombre del parmetro se utiliza como dentro del cuerpo de la funcin, y
tambin se utiliza como una etiqueta para el argumento al llamar al mtodo.El nombre
del primer parmetro de un mtodo slo se utiliza dentro del cuerpo de la funcin, como
el parmetro de una funcin. Por ejemplo:

func f(x: Int, y: String) -> String {

return y + String(x)

f(7, "hello") // x and y have no name

class C {

func f(x: Int, y: String) -> String {

return y + String(x)

let c = C()

c.f(7, y: "hello") // x has no name, y has a name


Puede reemplazar el comportamiento predeterminado de cmo los nombres de
parmetro se utiliza con una de las siguientes formas:

external parameter name local parameter name : parameter type

# parameter name : parameter type


339

_ local parameter name : parameter type


Un segundo nombre antes el nombre de parmetro local da el parmetro de un nombre
externo, que puede ser diferente del nombre de parmetro local. El nombre del
parmetro externo debe utilizar cuando se invoca la funcin. El argumento
correspondiente debe tener el nombre externo en los mtodos o funciones llamadas.
Un smbolo de almohadilla ( # ) delante de un nombre de parmetro indica que el
nombre debe ser utilizado como un nombre de un parmetro local, externa e. Tiene el
mismo significado que escribir el nombre de parmetro local dos veces. El argumento
correspondiente debe tener este nombre en los mtodos o funciones llamadas.
Un guin bajo ( _ ) delante del nombre parmetro local da ese parmetro sin nombre
que se utilizar en las llamadas a funciones. El argumento correspondiente debe tener
ningn nombre en los mtodos o funciones llamadas.
Tipos especiales de Parmetros
Los parmetros pueden ser ignoradas, toman un nmero variable de valores, y
proporcionan valores por defecto usando las siguientes formas:

_ : parameter type

parameter name : parameter type ...

parameter name : parameter type = default argument value

Un parmetro con nombre con un guin bajo ( _ ) se ignora de forma explcita y no se


puede acceder dentro del cuerpo de la funcin.
Un parmetro con un nombre del tipo de base seguida inmediatamente por tres puntos
( ... ) se entiende como un parmetro variadic. Una funcin puede tener como
mximo un parmetro variadic, que debe ser el ltimo parmetro. Un parmetro variadic
se trata como una matriz que contiene los elementos del nombre de tipo de base. Por
ejemplo, el parmetro variadic Int ... se trata como [Int] . Para ver un ejemplo
que utiliza un parmetro variadic, consulte Parmetros variadic .
Un parmetro con un signo igual ( = ) y una expresin despus de su tipo se entiende
que tienen un valor por defecto de la expresin dada. Si el parmetro se omite cuando se
llama a la funcin, el valor predeterminado se utiliza en su lugar. Si el parmetro no se
omite, debe tener su nombre en la llamada a la funcin. Por ejemplo, f () y f (x,
7) son las dos llamadas vlidas a una funcin con un solo parmetro predeterminado
denominado x , pero f (7) no es vlido, ya que proporciona un valor sin un nombre.
Tipos especiales de Mtodos
Mtodos de una enumeracin o una estructura que modifican self deben estar
marcados con el mutating modificador declaracin.
Los mtodos que anulen un mtodo de superclase deben estar marcados con
la override modificador declaracin. Es un error en tiempo de compilacin para
anular un mtodo sin la override modificador o utilizar el override modificador
en un mtodo que no define un mtodo de superclase.
Mtodos asociados con un tipo en lugar de una instancia de un tipo deben estar
marcados con la estatic modificador de declaracin de enumeraciones y estructuras
o la clase de modificador de declaracin para las clases.

340

Funciones Curried
Puede volver a escribir una funcin que toma varios parmetros como una funcin
equivalente que toma un solo parmetro y devuelve una funcin. La funcin devuelto
tiene el siguiente parmetro y devuelve otra funcin. Esto contina hasta que no hay
parmetros restantes, momento en el que la ltima funcin devuelve el valor de retorno
de la funcin de mltiples parmetros originales. La funcin reescrito se conoce como
unafuncin de curry . Por ejemplo, se puede reescribir la addTwoInts funcionan
como el equivalenteaddTwoIntsCurried funcin:

addTwoInts(a: Int, b: Int) -> Int {

return a + b

func addTwoIntsCurried(a: Int) -> (Int -> Int) {

func addTheOtherInt(b: Int) -> Int {

return a + b

return addTheOtherInt

}
El addTwoInts funcin toma dos enteros y devuelve el resultado de
sumarlos. El addTwoIntsCurried funcin toma un solo entero, y devuelve otra
funcin que toma el segundo entero y lo aade a la primera. (La funcin anidada captura
el valor del primer argumento nmero entero de la funcin envolvente.)
En Swift, puede escribir una funcin al curry ms concisa con la siguiente sintaxis:
func function name ( parameter )( parameter ) -> return type {

statements

}
Por ejemplo, las dos declaraciones siguientes son equivalentes:

func addTwoIntsCurried(a: Int)(b: Int) -> Int {

return a + b

func addTwoIntsCurried(a: Int) -> (Int -> Int) {

func addTheOtherInt(b: Int) -> Int {

return a + b

return addTheOtherInt

}
Para utilizar el addTwoIntsCurried funcionan de la misma manera que el
noncurried addTwoInts funcin, debe llamar a la addTwoIntsCurried funcin
con el primer argumento entero y luego llamar a su funcin vuelto con el segundo
argumento entero:

341

// Devuelve un valor de 9

let plusOne = addTwoIntsCurried(1)

// PlusOne es una funcin del tipo Int -> Int


Debido PlusOne refiere a la addTwoIntsCurried funcin con su argumento
enlaza con el valor 1 , llamandoPlusOne con un argumento entero simplemente
aade 1 al argumento.

addTwoIntsCurried(4)(5)

// Devuelve un valor de 9
Aunque usted debe proporcionar los argumentos a una funcin noncurried todos a la vez
en una sola llamada, usted puede utilizar el formulario al curry de una funcin de
proporcionar argumentos en varias llamadas a funciones, una a la vez (incluso en
diferentes lugares en su cdigo). Esto se conoce comoaplicacin de funcin
parcial . Por ejemplo, puede aplicar el addTwoIntsCurried funcin a un
argumento entero1 y asignar el resultado a la constante PlusOne :

addTwoInts(4, 5)

plusOne(10)

// Devuelve un valor de 11

GRAMTICA DE UNA DECLARACIN DE FUNCIN
function-declaration function-headfunction-namegeneric-parameter-clauseoptfunction-signaturefunction-body
function-head attributesoptdeclaration-modifiersoptfunc
function-name identifier operator
function-signature parameter-clausesfunction-resultopt
function-result ->attributesopttype
function-body code-block
parameter-clauses parameter-clauseparameter-clausesopt
parameter-clause () (parameter-list...opt)
parameter-list parameter parameter,parameter-list
parameter inoutoptletopt#optexternal-parameter-nameoptlocal-parameter-nametypeannotationdefault-argument-clauseopt
parameter inoutoptvar#optexternal-parameter-nameoptlocal-parameter-nametypeannotationdefault-argument-clauseopt
parameter attributesopttype
external-parameter-name identifier _
local-parameter-name identifier _
default-argument-clause =expression
Declaracin Enumeracin
Una declaracin de la enumeracin introduce un tipo de enumeracin llamado en su
programa.
Declaraciones de enumeracin tienen dos formas bsicas y se declaran usando la
palabra clave enum . El cuerpo de una enumeracin declarada utilizando formulario

342

contiene los llamados valores cero o ms casos de enumeracin -y cualquier nmero de


declaraciones, incluidas las propiedades calculadas, mtodos de instancia, los mtodos
estticos, inicializadores, alias de tipo, e incluso otra enumeracin, estructura, y las
declaraciones de clase . Declaraciones de enumeracin no pueden contener deinitializer
o protocolo declaraciones.
Tipos de enumeracin pueden adoptar cualquier nmero de protocolos, pero no pueden
heredar de clases, estructuras u otras enumeraciones.
A diferencia de clases y estructuras, tipos de enumeracin no tienen un inicializador por
defecto proporcionado implcitamente; todos los inicializadores deben declararse
explcitamente. Inicializadores pueden delegar a otros inicializadores en la
enumeracin, pero el proceso de inicializacin se ha completado slo despus de un
inicializador asigna uno de los casos de enumeracin a uno mismo .
Al igual que las estructuras, pero a diferencia de las clases, enumeraciones son tipos de
valor; se copian las instancias de una enumeracin cuando se asigna a las variables o
constantes, o cuando se pasa como argumentos de una llamada de funcin. Para obtener
informacin sobre los tipos de valor, vea Estructuras y enumeraciones son tipos de
valor .
Puede extender el comportamiento de un tipo de enumeracin con una ampliacin de
declaracin, como se discuti en la Declaracin de extensin .
Las enumeraciones con casos de Cualquier Tipo
El siguiente formulario declara un tipo de enumeracin que contiene los casos de
enumeracin de cualquier tipo:

enum enumeration name : adopted protocols {

case enumeration case 1

case enumeration case 2 ( associated value types )

}
Enumeraciones declaradas en esta forma a veces se llaman uniones discriminadas en
otros lenguajes de programacin.
En esta forma, cada bloque caso consiste en la palabra clave caso seguido por uno o
ms casos de enumeracin, separados por comas. El nombre de cada caso debe ser
nico. Cada caso tambin puede especificar que almacena los valores de un tipo
determinado. Estos tipos se especifican en el tipo de valor asociado tupla,
inmediatamente despus del nombre del caso. Para obtener ms informacin y ver
ejemplos de casos con tipos de valor asociadas, ver valores asociados .
Las enumeraciones con casos de un tipo de valor crudo
La forma siguiente declara un tipo de enumeracin que contiene los casos de
enumeracin del mismo tipo bsico:

enum enumeration name : raw-value type , adopted protocols {

case enumeration case 1 = raw value 1

case enumeration case 2 = raw value 2

343

En esta forma, cada bloque caso consiste en la palabra clave caso , seguido de uno o
ms casos de enumeracin, separados por comas. A diferencia de los casos en la
primera forma, cada caso tiene un valor subyacente, llamado valor en bruto , del mismo
tipo bsico. El tipo de estos valores se especifica en el tipo de valor crudo y debe
representar un nmero entero, el nmero de punto flotante, cadena, o de un solo
carcter.En particular, el tipo de prima-valor debe ajustarse a la equatable protocolo
y uno de los siguientes protocolos literal
convertibles: IntegerLiteralConvertible para literales
enteros, FloatingPointLiteralConvertible para los literales de punto
flotante, StringLiteralConvertible para los literales de cadena que contienen
cualquier nmero de caracteres,
y ExtendedGraphemeClusterLiteralConvertible para literales de cadena
que contienen slo un nico carcter.
Cada caso debe tener un nombre nico y se le asigna un valor prima nica. Si no se
especifica el tipo de valor crudo como int y no asigna un valor a los casos
explcitamente, se les asigna implcitamente los valores0 , 1 , 2 , y as
sucesivamente. Cada caso sin asignar de tipo Int est implcitamente asigna un valor
en bruto que se incrementa automticamente del valor bruto del caso anterior.

enum ExampleEnum: Int {

case A, B, C = 5, D

}
En el ejemplo anterior, el valor bruto de ExampleEnum.A es 0 y el valor
de ExampleEnum.B es 1 . Y debido a que el valor de ExampleEnum.C se establece
explcitamente en 5 , el valor de ExampleEnum.D se incrementa automticamente a
partir de 5 y por lo tanto es 6 .
El valor en bruto de un caso de enumeracin se puede acceder llamando a
su toRaw mtodo, como enExampleEnum.B.toRaw () . Tambin puede utilizar
un valor crudo para encontrar un caso correspondiente, si es que existe, llamando a
la fromRaw mtodo, que devuelve un caso opcional. Para obtener ms informacin y
ver ejemplos de casos con tipos de valor en bruto, vea Raw Values.
Acceso Casos de enumeracin
Para hacer referencia al caso de un tipo de enumeracin, utilice punto ( . sintaxis),
como enEnumerationType.EnumerationCase . Cuando el tipo de enumeracin
puede inferirse a partir del contexto, puede omitirlo (todava se requiere que el punto),
como se describe en Sintaxis Enumeracin y Implcita Expresin miembros .
Para comprobar los valores de la enumeracin de los casos, utilizar un interruptor
de declaracin, como se muestra en juego valores de enumeracin con una sentencia
switch . El tipo de enumeracin coincide-patrn en contra de los patrones de casos de
enumeracin en los bloques de caso del interruptor de la declaracin, como se
describe en el Modelo de Enumeracin Case .

344

GRAMTICA DE UNA DECLARACIN DE LA ENUMERACIN


enum-declaration attributesoptaccess-level-modifieroptunion-style-enum
enum-declaration attributesoptaccess-level-modifieroptraw-value-style-enum
union-style-enum enumenum-namegeneric-parameter-clauseopttype-inheritanceclauseopt{union-style-enum-membersopt}
union-style-enum-members union-style-enum-memberunion-style-enum-membersopt
union-style-enum-member declaration union-style-enum-case-clause
union-style-enum-case-clause attributesoptcaseunion-style-enum-case-list
union-style-enum-case-list union-style-enum-case union-style-enum-case,unionstyle-enum-case-list
union-style-enum-case enum-case-nametuple-typeopt
enum-name identifier
enum-case-name identifier
raw-value-style-enum enumenum-namegeneric-parameter-clauseopttype-inheritanceclause{raw-value-style-enum-members}
raw-value-style-enum-members raw-value-style-enum-memberraw-value-styleenum-membersopt
raw-value-style-enum-member declaration raw-value-style-enum-case-clause
raw-value-style-enum-case-clause attributesoptcaseraw-value-style-enum-case-list
raw-value-style-enum-case-list raw-value-style-enum-case raw-value-style-enumcase,raw-value-style-enum-case-list
raw-value-style-enum-case enum-case-nameraw-value-assignmentopt
raw-value-assignment =literal
Estructura Declaracin
Una declaracin de la estructura presenta un tipo de estructura llamado en su
programa. Estructura declaraciones se declaran usando la palabra clave struct y
tienen la siguiente forma:

struct structure name : adopted protocols {


declarations

}
El cuerpo de una estructura contiene cero o
ms declaraciones . Estas declaraciones pueden incluir tanto almacenados y calculados
propiedades, propiedades estticas, mtodos de instancia, los mtodos estticos,
inicializadores, subndices, alias de tipo, e incluso otra estructura, clase, y las
declaraciones de enumeracin.Estructura de las declaraciones no pueden contener
deinitializer o protocolo declaraciones. Para una discusin y varios ejemplos de
estructuras que incluyen diversos tipos de declaraciones, vea Clases y Estructuras .
Tipos de estructura puede adoptar cualquier nmero de protocolos, pero no pueden
heredar de clases, enumeraciones, u otras estructuras.
Hay tres formas de crear una instancia de una estructura previamente declarado:
Llame a uno de los inicializadores declarados dentro de la estructura, como se
describe eninicializadores .

345

Si son declarados no inicializadores, llame inicializador miembro por miembro de la


estructura, como se describe en el miembro por miembro Inicializadores de
Estructura Tipos .
Si son declarados no inicializadores, y todas las propiedades de la declaracin de la
estructura se dieron valores iniciales, llame inicializador por defecto de la estructura,
como se describe enInicializadores predeterminados .
El proceso de inicializacin de propiedades declaradas de una estructura se describe en
la inicializacin .
Propiedades de una instancia de estructura se puede acceder mediante punto
( . sintaxis), como se describe en Acceso a las propiedades .
Las estructuras son tipos de valor; se copian las instancias de una estructura cuando se
asigna a las variables o constantes, o cuando se pasa como argumentos de una llamada
de funcin. Para obtener informacin sobre los tipos de valor, vea Estructuras y
enumeraciones son tipos de valor .
Puede extender el comportamiento de un tipo de estructura con una ampliacin de
declaracin, como se discuti en la Declaracin de extensin .

GRAMTICA DE UNA DECLARACIN DE LA ESTRUCTURA


struct-declaration attributesoptaccess-level-modifieroptstructstruct-namegenericparameter-clauseopttype-inheritance-clauseoptstruct-body
struct-name identifier
struct-body {declarationsopt}
Declaracin de Clase
Una declaracin de la clase introduce un tipo de clase nombrada en su
programa. Declaraciones de clase se declaran usando la palabra clave de clase y
tienen la siguiente forma:

class class name : superclass , adopted protocols {


declarations

}
El cuerpo de una clase contiene cero o ms declaraciones . Estas declaraciones pueden
incluir tanto almacenados y calculados propiedades, mtodos de instancia, mtodos de
clase, inicializadores, un solo deinitializer, subndices, alias de tipo, e incluso otra clase,
la estructura, y las declaraciones de enumeracin.Declaraciones de clase no pueden
contener declaraciones de protocolo. Para una discusin y varios ejemplos de clases que
incluyen diversos tipos de declaraciones, vea Clases y Estructuras .
Un tipo de clase puede heredar de una sola clase padre, su superclase , pero puede
adoptar cualquier nmero de protocolos. La superclase aparece por primera vez despus
de que el nombre de la clase y el colon, seguido por cualquier protocolos
adoptados . Clases genricas pueden heredar de otras clases genricas y no genricos,
sino una clase no genrica pueden heredar slo de otras clases no genricos.Cuando se
escribe el nombre de una clase superclase genrica tras los dos puntos, debe incluir el
nombre completo de esa clase genrica, incluida su clusula de parmetro genrico.

346

Como se discuti en la Declaracin Inicializador , las clases pueden han designado y los
inicializadores de conveniencia. El inicializador designado de una clase debe inicializar
todas las propiedades declaradas de la clase y debe hacerlo antes de llamar a cualquiera
de los inicializadores designados de su superclase.
Una clase puede anular las propiedades, los mtodos, los subndices y los
inicializadores de su superclase.Propiedades alteradas temporalmente, los mtodos, los
subndices y inicializadores designados deben estar marcados con
la anulacin modificador declaracin.
Exigir que las subclases implementan inicializador de una superclase, marcan
inicializador de la superclase con el requerido modificador declaracin. La
implementacin de la subclase de que inicializador tambin debe estar marcado con
el requerido modificador declaracin.
Aunque las propiedades y mtodos declarados en la superclase son heredados por la
clase actual, inicializadores designados declarados en la superclase no lo son. Dicho
esto, si la clase actual anula todos los inicializadores designados de la superclase, hereda
inicializadores de conveniencia de la superclase.Clases Swift no heredan de una clase
base universal.
Hay dos maneras de crear una instancia de una clase declarada con anterioridad:
Llame a uno de los inicializadores declarados dentro de la clase, como se describe
en inicializadores .
Si son declarados no inicializadores, y todas las propiedades de la declaracin de
clase se les dio valores iniciales, llame inicializador por defecto de la clase, como se
describe en Inicializadores predeterminados .
Propiedades de acceso de una instancia de la clase con el punto ( . ) sintaxis, como se
describe en Acceso a las propiedades .
Las clases son tipos de referencia; instancias de una clase se denominan, en lugar de
copiar, cuando se asigna a las variables o constantes, o cuando se pasa como
argumentos de una llamada de funcin. Para obtener informacin acerca de los tipos de
referencia, consulte Estructuras y enumeraciones son tipos de valor .
Puede extender el comportamiento de un tipo de clase con una ampliacin de
declaracin, como se discuti en la Declaracin de extensin .
GRAMTICA DE UNA DECLARACIN DE CLASE
class-declaration attributesoptaccess-level-modifieroptclassclass-namegenericparameter-clauseopttype-inheritance-clauseoptclass-body
class-name identifier
class-body {declarationsopt}
Declaracin Protocolo
Una declaracin protocolo introduce un tipo de protocolo llamado en su
programa. Declaraciones de protocolo se declaran usando la palabra clave de
protocolo y tienen la siguiente forma:

protocol protocol name : inherited protocols {


protocol member declarations

347

}
El cuerpo de un protocolo contiene cero o ms declaraciones de miembros de
protocolo , que describen los requisitos de conformidad que cualquier tipo que adoptan
el protocolo debe cumplir. En particular, un protocolo puede declarar que los tipos se
ajusten deben implementar ciertas propiedades, mtodos, inicializadores y
subndices. Los protocolos tambin pueden declarar los tipos especiales de alias de tipo,
llamados tipos asociados , que pueden especificar las relaciones entre las diversas
declaraciones del protocolo. Las declaraciones de miembros protocolo se discuten en
detalle a continuacin.
Tipos de protocolo pueden heredar de cualquier nmero de otros protocolos. Cuando un
tipo de protocolo hereda de otros protocolos, el conjunto de requisitos de los otros
protocolos se agregan, y cualquier tipo que hereda de la actual protocolo debe cumplir
con todos los requisitos. Para ver un ejemplo de cmo utilizar la herencia de protocolo,
vea Herencia Protocolo .
NOTA
Tambin puede agregar los requisitos de conformidad de mltiples protocolos que
utilizan tipos de composicin del protocolo, segn se describe en el Protocolo Tipo
Composicin y Composicin Protocolo .
Usted puede agregar la conformidad de protocolo a un tipo declarado previamente
mediante la adopcin del protocolo en una ampliacin de declaracin de ese tipo. En la
extensin, debe implementar todos los requisitos del protocolo aprobado. Si el tipo ya se
implementa todos los requisitos, se puede dejar el cuerpo de la ampliacin de
declaracin vaca.
De forma predeterminada, los tipos que se ajustan a un protocolo deben implementar
todas las propiedades, mtodos y subndices declaradas en el protocolo. Dicho esto,
puede marcar estas declaraciones de miembros de protocolo con
el opcional modificador de declaracin para especificar que su aplicacin por un tipo
de conformacin es opcional. El opcional modificador slo puede aplicarse a los
protocolos que estn marcados con el objc atributo. Como resultado, slo los tipos de
clase pueden adoptar y cumplir con un protocolo que contiene requisitos miembro
opcionales. Para obtener ms informacin acerca de cmo utilizar
la opcin modificador de declaracin y de orientacin sobre cmo acceder opcional
ejemplo de protocolo miembros-para, cuando no ests seguro de si un tipo de
conformacin implementa ellos-vase Requisitos del Protocolo Facultativo .
Para restringir la adopcin de un protocolo para los tipos de clases solamente, marque el
protocolo con laclase de requerimiento por escrito la clase de palabras clave
como el primer elemento en el protocolos heredados lista despus de los dos
puntos. Por ejemplo, el siguiente protocolo puede ser adoptada slo por los tipos de
clases:

protocol SomeProtocol: class {

/* Protocol members go here */

}
Cualquier protocolo que hereda de un protocolo que est marcado con la clase
de requisito puede igualmente adoped slo por los tipos de clase.
NOTA

348

Si un protocolo est marcado con el objc atributo, la clase de requisito se aplica


implcitamente a ese protocolo; no hay necesidad de marcar el protocolo con la clase
de requisito de forma explcita.
Los protocolos se denominan tipos, y por lo tanto pueden aparecer en todos los mismos
lugares en su cdigo como otros tipos con nombre, como se discute en los Protocolos
como Tipos . Sin embargo, no se puede construir una instancia de un protocolo, ya que
los protocolos en realidad no ofrecen las implementaciones de los requisitos que se
especifican.
Puede usar los protocolos para declarar que los mtodos delegado de una clase o
estructura debe aplicar, como se describe en Delegacin .
GRAMTICA DE UNA DECLARACIN PROTOCOLO
protocol-declaration attributesoptaccess-level-modifieroptprotocolprotocol-nametypeinheritance-clauseoptprotocol-body
protocol-name identifier
protocol-body {protocol-member-declarationsopt}
protocol-member-declaration protocol-property-declaration
protocol-member-declaration protocol-method-declaration
protocol-member-declaration protocol-initializer-declaration
protocol-member-declaration protocol-subscript-declaration
protocol-member-declaration protocol-associated-type-declaration
protocol-member-declarations protocol-member-declarationprotocol-memberdeclarationsopt
Protocolo Declaracin de bienes
Protocolos declaran que los tipos se ajusten deben implementar una propiedad mediante
la inclusin de unadeclaracin de propiedad de protocolo en el cuerpo de la declaracin
de protocolo. Declaraciones de bienes Protocolo tienen una forma especial de una
declaracin de variable:

var property name : type { get set }


Al igual que con otras declaraciones de miembros de protocolo, estas declaraciones de
bienes declaran slo los requisitos get y set para los tipos que cumplen con el
protocolo. Como resultado, no se implementa el getter o setter directamente en el
protocolo en el que se declara.
Los requisitos getter y setter pueden ser satisfechas por un tipo de conformacin en una
variedad de maneras. Si una declaracin de propiedad incluye tanto
los get y set palabras clave, un tipo de conformacin puede implementar con un
almacenada propiedad variable o una propiedad calculada que es a la vez de lectura y
escritura (es decir, una que implementa un getter y un setter). Sin embargo, esa
declaracin de propiedad no se puede implementar como una propiedad constante o una
propiedad calculada de slo lectura. Si una declaracin de propiedad incluye slo
el get de palabras clave, que puede implementarse como cualquier tipo de
propiedad. Para ver ejemplos de tipos que implementan conforme a los requisitos de las
propiedades de un protocolo, vea Requisitos de Propiedad .
Ver tambin declaracin de variables .

349

GRAMTICA DE UNA DECLARACIN DE PROPIEDAD


PROTOCOLO
protocol-property-declaration variable-declaration-headvariable-nametypeannotationgetter-setter-keyword-block
Protocolo Declaracin Mtodo
Protocolos declaran que tipos conformes deben implementar un mtodo mediante la
inclusin de una declaracin de mtodo protocolo en el cuerpo de la declaracin de
protocolo. Declaraciones de mtodos Protocolo tienen la misma forma que las
declaraciones de funciones, con dos excepciones: No se incluyen un cuerpo de la
funcin, y no se puede proporcionar ningn valores de los parmetros por defecto como
parte de la declaracin de la funcin. Para ver ejemplos de tipos que implementan
conforme los requisitos del mtodo de un protocolo, vea Requisitos del mtodo .
Para declarar una clase o requisito mtodo esttico en una declaracin protocolo,
marque la declaracin de mtodo con la clase modificador declaracin. Las clases
que implementan este mtodo tambin declaran el mtodo con la clase
de modificador. Estructuras que lo implementan deben declarar el mtodo con
laesttica modificador de declaracin en su lugar. Si est implementando el mtodo
en una extensin, utilice laclase modificador si est extendiendo una clase y
la esttica modificador si est extendiendo una estructura.
Vase tambin la Declaracin de funciones .
GRAMTICA DE UNA DECLARACIN DE MTODO DE
PROTOCOLO
protocol-method-declaration function-headfunction-namegeneric-parameter-clauseoptfunction-signature
Protocolo Declaracin Inicializador
Protocolos declaran que los tipos se ajusten deben implementar un inicializador al
incluir una declaracin de inicializacin de protocolo en el cuerpo de la declaracin de
protocolo. Declaraciones Protocolo de inicializador tienen la misma forma que las
declaraciones de inicializador, excepto que no incluyen el cuerpo del inicializador.
Cuando una clase implementa un inicializador para satisfacer el requisito de
inicializacin de un protocolo, el inicializador debe estar marcado con el required
modificador de declaracin si la clase no est marcada con el final modificador
declaracin.
Ver tambin Declaracin inicializador .
GRAMTICA DE UNA DECLARACIN INICIALIZADOR
PROTOCOLO
protocol-initializer-declaration initializer-headgeneric-parameter-clauseoptparameter-clause

350

Protocolo Declaracin Subndice


Protocolos declaran que los tipos se ajusten deben implementar un subndice al incluir
una declaracin subndice protocolo en el cuerpo de la declaracin de
protocolo. Declaraciones de bienes Protocolo tienen una forma especial de una
declaracin subndice:

subscript ( parameters ) -> return type { get set }


Declaraciones subndices slo declaran los requisitos mnimos getter y setter de
aplicacin para los tipos que cumplen con el protocolo. Si la declaracin subndice
incluye tanto los get y set palabras clave, un tipo de conformacin debe
implementar tanto un captador y una clusula de setter. Si la declaracin subndice
incluye slo el get palabra clave, un tipo de conformacin debe implementar al
menos una clusula getter y opcionalmente puede aplicar una clusula de setter.
Ver tambin Declaracin Subndice .
GRAMTICA DE UNA DECLARACIN SUBNDICE PROTOCOLO
protocol-subscript-declaration subscript-headsubscript-resultgetter-setter-keywordblock
Protocolo asociado Declaracin Tipo
Protocolos declaran tipos asociados con la palabra clave typealias . Un tipo
asociado proporciona un alias para un tipo que se utiliza como parte de la declaracin de
un protocolo. Tipos asociados son similares a los parmetros de tipo de clusulas de
parmetros genricos, pero estn asociados con self en el protocolo en el que estn
declaradas. En ese contexto, Self refiere al tipo eventual que cumpla con el
protocolo. Para obtener ms informacin y ejemplos, vea Tipos asociados .
Vase tambin el tipo de declaracin Alias .
GRAMTICA DE UNA DECLARACIN DE TIPO DE
PROTOCOLO ASOCIADO
protocol-associated-type-declaration typealias-headtype-inheritance-clauseopttypealias-assignmentopt
Declaracin Inicializador
Una declaracin inicializador introduce un inicializador para una clase, estructura o
enumeracin en su programa. Declaraciones de inicializador se declaran usando la
palabra clave init y tienen dos formas bsicas.
Estructura, enumeracin y tipos de clase pueden tener cualquier nmero de
inicializadores, pero las reglas y el comportamiento asociado para inicializadores de
clase son diferentes. A diferencia de las estructuras y enumeraciones, las clases tienen
dos tipos de inicializadores: inicializadores designados y los inicializadores de
conveniencia, como se describe en la inicializacin .
El siguiente formulario declara inicializadores de estructuras, enumeraciones, y
inicializadores designados de clases:

init( parameters ) {

351

statements

}
Un inicializador designado de una clase inicializa todas las propiedades de la clase
directamente. No se puede llamar a cualquier otro inicializadores de la misma clase, y si
la clase tiene una superclase, debe llamar a uno de los inicializadores designados de la
superclase. Si la clase hereda todas las propiedades de su superclase, uno de
inicializadores designados de la superclase debe ser llamado antes de cualquiera de estas
propiedades pueden ser establecidas o modificadas en la clase actual.
Inicializadores designados pueden ser declarados en el contexto de slo una declaracin
de clase y, por tanto, no se pueden agregar a una clase utilizando una ampliacin de
declaracin.
Inicializadores en estructuras y enumeraciones pueden llamar a otros inicializadores
declarados a delegar parte o la totalidad del proceso de inicializacin.
Declarar inicializadores de conveniencia para una clase, marcar la declaracin
inicializador con la convenience modificador declaracin.

convenience init( parameters ) {


statements

}
Inicializadores de Conveniencia pueden delegar el proceso de inicializacin a otro
inicializador conveniencia o para uno de los inicializadores designados de la
clase. Dicho esto, los procesos de inicializacin deben terminar con una llamada a un
inicializador designado que en ltima instancia se inicializa las propiedades de la
clase. Inicializadores de conveniencia no pueden llamar inicializadores de una
superclase.
Puede marcar designado y los inicializadores de conveniencia con el required
modificador de declaracin para exigir que cada subclase implementar el
inicializador. Aplicacin de una subclase de que inicializador tambin debe estar
marcado con el requirted modificador declaracin.
Por defecto, los inicializadores declarados en una superclase no son heredados por las
subclases. Dicho esto, si una subclase inicializa todas sus propiedades almacenados con
valores por defecto y no define ningn inicializadores de su propia, hereda todos los
inicializadores de la superclase. Si la subclase sobreescribe todos los inicializadores
designados de la superclase, hereda inicializadores de conveniencia de la superclase.
Al igual que con los mtodos, propiedades y subndices, es necesario marcar
inicializadores designados anulados con la override modificador declaracin.
NOTA
Si marca un inicializador con la required modificador de declaracin, no es tambin
marca el inicializador con la override modificador cuando omite el inicializador
requerido en una subclase.
Para ver ejemplos de inicializadores en diversas declaraciones de tipo,
consulte inicializacin .

352

GRAMTICA DE UNA DECLARACIN INICIALIZADOR


initializer-declaration initializer-head generic-parameter-clause opt parameterclause initializer-body
inicializador-cabeza atributos opt declaracin modificadores optan init
inicializador-cuerpo code-block
Declaracin Deinitializer
Una declaracin deinitializer declara un deinitializer para un tipo de
clase. Deinitializers tomar ningn parmetro y tienen la siguiente forma:

deinit {
statements

}
A deinitializer se llama automticamente cuando ya no hay ninguna referencia a un
objeto de clase, justo antes de que se cancela la asignacin del objeto de clase. A
deinitializer se puede declarar slo en el cuerpo de una clase de declaracin-, pero no en
una extensin de una clase y cada clase puede tener como mximo una.
Una subclase hereda deinitializer de su superclase, que se llama implcitamente justo
antes de se desasigna el objeto subclase. El objeto subclase no se cancela la asignacin
hasta que todos deinitializers en su cadena de herencia han terminado de ejecutarse.
Deinitializers no se llaman directamente.
Para ver un ejemplo de cmo utilizar un deinitializer en una declaracin de clase,
vase deinicializacin .
GRAMTICA DE UNA DECLARACIN DEINITIALIZER
deinitializer-declaration attributesoptdeinitcode-block
Declaracin de Extensin
Una ampliacin de declaracin le permite extender el comportamiento de los tipos de
clase, estructura, enumeracin y existentes. Declaraciones de extensin se declaran
usando la palabra clave de extensin y tienen la siguiente forma:

extension type name : adopted protocols {

declarations
El cuerpo de una ampliacin de declaracin contiene cero o
ms declaraciones . Estas declaraciones pueden incluir propiedades calculadas,
propiedades estticas calculadas, mtodos de instancia, los mtodos estticos y de clase,
inicializadores, declaraciones subndice, e incluso de clase, la estructura, y las
declaraciones de enumeracin. Declaraciones de extensin no pueden contener
deinitializer o protocolo declaraciones, propiedades almacenadas, observadores de
propiedad, u otras declaraciones de extensin.Para una discusin y varios ejemplos de
extensiones que incluyen diversos tipos de declaraciones, veaExtensiones .
Declaraciones de extensin pueden aadir conformidad protocolo para una clase,
estructura y tipo de enumeracin existente en los protocolos aprobados . Declaraciones
de extensin no pueden aadir herencia de clases para una clase existente, y por lo tanto

353

slo se puede especificar una lista de protocolos despus de que el nombre del tipo y el
colon.
Propiedades, mtodos y inicializadores de un tipo existente no se pueden sustituir en
una extensin de ese tipo.
Declaraciones de extensin pueden contener declaraciones de inicializador. Dicho esto,
si el tipo que est extendindose est definida en otro mdulo, una declaracin
inicializador debe delegar en un inicializador ya definido en ese mdulo para asegurar
que los miembros de ese tipo se inicializan correctamente.
GRAMTICA DE UNA AMPLIACIN DE DECLARACIN
extension-declaration access-level-modifieroptextensiontype-identifiertypeinheritance-clauseoptextension-body
extension-body {declarationsopt}
Declaracin Subndice
Un subndice declaracin le permite aadir soporte subndices para los objetos de un
tipo determinado y se utilizan normalmente para proporcionar una sintaxis conveniente
para acceder a los elementos de una coleccin, una lista o secuencia. Declaraciones
subndices se declaran utilizando la palabra clave subndice y tienen la siguiente
forma:

subscript ( parameters ) -> return type {


get {

statements

set( setter name ) {


statements

}
Declaraciones subndices pueden aparecer slo en el contexto de una estructura,
enumeracin, extensin, o declaracin protocolo clase.
Los parmetros especifican uno o ms ndices que se utilizan para acceder a los
elementos del tipo correspondiente en una expresin de subndice (por ejemplo, la i en
la expresin object[i] ). Aunque los ndices utilizados para acceder a los elementos
pueden ser de cualquier tipo, cada parmetro debe incluir una anotacin de tipo para
especificar el tipo de cada ndice. El tipo de retorno especifica el tipo de elemento que
se est accediendo.
Al igual que con las propiedades calculadas, declaraciones subndice apoyar la lectura y
la escritura el valor de los elementos de los que se accede. El captador se utiliza para
leer el valor, y el colocador se utiliza para escribir el valor. La clusula setter es
opcional, y cuando slo se necesita un captador, puede omitir ambas clusulas y

354

devuelva directamente el valor solicitado. Dicho esto, si usted proporciona una clusula
setter, tambin debe proporcionar una clusula getter.
El nombre del organismo y los parntesis que encierran son opcionales. Si proporciona
un nombre de setter, que se utiliza como el nombre del parmetro al setter. Si no se
proporciona un nombre de setter, el nombre del parmetro por defecto para el setter
es valor . El tipo del nombre setter debe ser el mismo que el tipo de retorno .
Usted puede sobrecargar una declaracin subndice en el tipo en el que se declara,
siempre y cuando losparmetros o el tipo de retorno son diferentes de la que usted est
sobrecargando. Tambin puede anular una declaracin subndice heredado de una
superclase. Al hacerlo, debe marcar la declaracin subndice se reemplaza con
la anulacin modificador declaracin.
Tambin puede declarar subndices en el contexto de una declaracin de protocolo, tal
como se describe en la Declaracin Protocolo Subndice .
Para obtener ms informacin acerca de subndices y para ver ejemplos de
declaraciones de subndice, versubndices .
GRAMTICA DE UNA DECLARACIN SUBNDICE
subscript-declaration subscript-headsubscript-resultcode-block
subscript-declaration subscript-headsubscript-resultgetter-setter-block
subscript-declaration subscript-headsubscript-resultgetter-setter-keyword-block
subscript-head attributesoptdeclaration-modifiersoptsubscriptparameter-clause
subscript-result ->attributesopttype
Declaracin del operador
Una declaracin de operador introduce un nuevo infijo, prefijo, o operador de sufijo en
su programa y se declara utilizando la palabra clave operator .
Puede declarar los operadores de tres empotramientos diferentes: infijo, prefijo, y
postfix. La fijeza de un operador especifica la posicin relativa de un operador a sus
operandos.
Hay tres formas bsicas de una declaracin del operador, una para cada fijeza. La fijeza
de la operadora se especifica mediante el marcado de la declaracin del operador con
el infijo , prefijo o de sufijo modificador declaracin ante el operador
de la palabra clave. En cada formulario, el nombre del operador puede contener slo los
caracteres operadores definidos en Operadores .
El siguiente formulario se declara un nuevo operador infijo:

infix operator operator name {

precedence precedence level

associativity associativity

}
Un operador infijo es un operador binario que se escribe entre sus dos operandos, como
el operador de suma familiarizados ( + ) en la expresin 1 + 2 .
Operadores infijos pueden especificar opcionalmente una precedencia, asociatividad, o
ambos.

355

La precedencia de un operador especifica cmo un operador fuertemente se une a sus


operandos en ausencia de agrupar parntesis. Se especifica la precedencia de un
operador escribiendo la palabra clave contextual prioridad seguido por el nivel de
precedencia . El nivel de precedencia puede ser cualquier nmero entero (nmero
entero decimal) de 0 a 255; a diferencia de literales enteros decimales, que no puede
contener caracteres de subrayado. Aunque el nivel de precedencia es un nmero
especfico, es significativo slo en relacin a otro operador. Es decir, cuando dos
operadores compiten entre s por sus operandos, como en la expresin 2 + 3 * 5 , el
operador con el nivel de prioridad ms alta se une ms estrechamente a sus operandos.
La asociatividad de un operador especifica cmo una secuencia de operadores con el
mismo nivel de precedencia se agrupan en ausencia de parntesis de agrupacin. Se
especifica la asociatividad de un operador escribiendo la palabra clave
contextual asociatividad seguido de la asociatividad , que es una de las palabras
clave contextuales izquierda , derecha , o ninguno . Los operadores que son
asociativos por la izquierda del grupo de izquierda a derecha. Por ejemplo, el operador
de resta ( - ) se asociativo por la izquierda, y por lo tanto la expresin 4 - 5 - 6 se
agrupan como (4 - 5) - 6 y evala a -7 . Los operadores que son grupo asociativo
por la derecha derecha a izquierda, y los operadores que se especifican con una
asociatividad de ninguno no asocian en absoluto. Operadores no asociativo de la
misma nivel de precedencia no pueden aparecer adyacente a cada uno para el otro. Por
ejemplo, 1 <2 <3 no es una expresin vlida.
Operadores infijos que se declaran sin especificar una precedencia o asociatividad se
inicializan con un nivel de precedencia de 100 y una asociatividad de ninguno .
El siguiente formulario se declara un nuevo operador de prefijo:

prefix operator operator name {}


Un operador de prefijo es un operador unitario que est escrito inmediatamente antes de
su operando, tales como el operador de incremento prefijo ( ++ ) es en la expresin ++
i.
Declaraciones operadores de prefijo no especifican un nivel de precedencia. Operadores
de prefijo son no asociativo.
El siguiente formulario se declara un nuevo operador de sufijo:

postfix operator operator name {}


Un operador de sufijo es un operador unario que se escribe inmediatamente despus de
su operando, como el operador de incremento postfix ( ++ ) est en la expresin i ++ .
Al igual que con los operadores de prefijo, declaraciones operador postfix no
especifican un nivel de precedencia. Operadores de Postfix son no asociativo.
Despus de declarar un nuevo operador, a ponerla en prctica, al declarar una funcin
que tiene el mismo nombre que el operador. Si est implementando un operador de
prefijo o de sufijo, tambin debe marcar esa declaracin de la funcin con el
correspondiente prefijo o de sufijo modificador declaracin. Si est
implementando un operador infijo, no marca que declaracin de la funcin con
el infijo modificador declaracin. Para ver un ejemplo de cmo crear e implementar
un nuevo operador, consulte Operadores personalizados .

356

GRAMTICA DE UNA DECLARACIN DE OPERADOR


operator-declaration prefix-operator-declaration postfix-operator-declarationinfix-operator-declaration
prefix-operator-declaration prefixoperatoroperator{}
postfix-operator-declaration postfixoperatoroperator{}
infix-operator-declaration infixoperatoroperator{infix-operator-attributesopt}
infix-operator-attributes precedence-clauseoptassociativity-clauseopt
precedence-clause precedenceprecedence-level
precedence-level A decimal integer between 0 and 255, inclusive
associativity-clause associativityassociativity
associativity left right none
Los modificadores de la Declaracin
Modificadores de la Declaracin son palabras clave o palabras clave de contexto, que
modifican el comportamiento o el significado de una declaracin. Se especifica un
modificador de declaracin escribiendo la palabra clave apropiada o palabra clave
contextual entre los atributos de una declaracin (si existe) y la palabra clave que
presenta la declaracin.
dynamic

Aplicar este modificador a cualquier miembro de una clase que se puede
representar por Objective-C.Cuando se marca una declaracin de miembro con
la dybnamic modificador, el acceso a ese miembro siempre se distribuye de
forma dinmica con el tiempo de ejecucin de Objective-C. El acceso a ese
miembro no se colocarn en lnea o desvirtualizada por el compilador.
Debido a las declaraciones marcadas con el dinamic modificador se envan
usando el tiempo de ejecucin de Objective-C, que estn implcitamente
marcados con el objc atributo.
final
Aplicar este modificador a una clase oa una propiedad, mtodo o miembro
subndice de una clase. Se aplica a una clase para indicar que la clase no puede
tener subclases. Se aplica a una propiedad, mtodo o subndice de una clase para
indicar que ese miembro de la clase no se puede anular en cualquier subclase.
lazy
Aplicar este modificador a un almacenado propiedad de variable de una clase o
estructura para indicar que el valor inicial de la propiedad se calcula y almacena
como mximo una vez, cuando la propiedad se accede por primera vez. Para ver
un ejemplo de cmo utilizar el perezoso modificador, consulte Lazy
Propiedades almacenados .
optional

357

Aplicar este modificador a la propiedad, mtodo o miembros subndice de un


protocolo para indicar que un tipo de conformacin no est obligado a poner en
prctica esos miembros.
Puede aplicar el opcional modificador slo a los protocolos que estn
marcados con el objc atributo. Como resultado, slo los tipos de clase pueden
adoptar y cumplir con un protocolo que contiene requisitos miembro
opcionales. Para obtener ms informacin acerca de cmo utilizar la opcin de
modificacin y de orientacin sobre cmo acceder opcional ejemplo de
protocolo miembros-para, cuando no ests seguro de si un tipo de conformacin
implementa ellos-vase Requisitos del Protocolo Facultativo .
required
Aplicar este modificador a un inicializador designado o conveniencia de una
clase para indicar que cada subclase debe implementar que inicializador. La
implementacin de la subclase de que inicializador tambin debe estar marcado
con el required modificador.
weak
La weakmodificador se aplica a una variable o una propiedad de variable
almacenada para indicar que la variable o propiedad tiene una referencia dbil
para el objeto almacenado como su valor. El tipo de la variable o propiedad debe
ser un tipo de clase opcional. Utilice la weak modificador para evitar los ciclos
de referencia fuertes. Para ver un ejemplo y obtener ms informacin acerca de
la weak modificador, consultelas referencias dbiles .
Los niveles de control de acceso
Swift proporciona tres niveles de control de acceso: pblico, internos y privados. Puede
marcar una declaracin con uno de los modificadores de nivel de acceso siguientes para
especificar el nivel de acceso de la declaracin. El control de acceso se discute en
detalle en el control de acceso .
public
Aplicar este modificador a una declaracin que indique la declaracin se puede
acceder con el cdigo en el mismo mdulo como la declaracin. Declaraciones
marcados con el pblico modificador-nivel de acceso tambin se puede
acceder con el cdigo en un mdulo que importa el mdulo que contiene la
declaracin.
internal
Aplicar este modificador a una declaracin que indique la declaracin slo se
puede acceder con el cdigo en el mismo mdulo como la declaracin. Por
defecto, la mayora de las declaraciones estn marcados implcitamente con
el internal modificador-nivel de acceso.
private
Aplicar este modificador a una declaracin que indique la declaracin slo se
puede acceder con el cdigo en el mismo archivo de origen como la declaracin.

358

Cada modificador de nivel de acceso por encima opcionalmente acepta un solo


argumento, que consiste en la palabra clave conjunto entre parntesis (por
ejemplo, private(set) ). Utilice esta forma de un modificador de nivel de acceso
cuando desea especificar un nivel de acceso para el colocador de una variable o
subndice que es menor o igual al nivel de acceso de la variable o subndice en s, como
se discute en los captadores y definidores .
GRAMTICA DE UN MODIFICADOR DE DECLARACIN
declaration-modifier class convenience dynamic final infix lazy mutatingnonmutating optional override postfix prefix required static unownedunowned(safe) unowned(unsafe) weak
declaration-modifier access-level-modifier
declaration-modifiers declaration-modifierdeclaration-modifiersopt
access-level-modifier internal internal(set)
access-level-modifier private private(set)
access-level-modifier public public(set)
access-level-modifiers access-level-modifieraccess-level-modifiersopt

Atributos
Los atributos proporcionan ms informacin acerca de una declaracin o escribe. Hay
dos tipos de atributos en Swift, los que se aplican a las declaraciones y las que se
aplican a los tipos.
Se especifica un atributo escribiendo el @ smbolo seguido por el nombre del atributo y
cualquier argumento que el atributo acepta:

@ attribute name

@ attribute name ( attribute arguments )


Algunos atributos de declaracin aceptan argumentos que especifican ms informacin
sobre el atributo y cmo se aplica a una declaracin particular. Estos argumentos de
atributos se escriben entre parntesis, y su formato est definido por el atributo al que
pertenecen.
Atributos Declaracin
Se puede aplicar un atributo de declaracin a slo declaraciones. Sin embargo, tambin
se puede aplicar elNoReturn atributo a una funcin o mtodo tipo .
disponibilidad
Aplique este atributo a toda declaracin que indique la declaracin de ciclo de
vida en relacin con determinadas plataformas y versiones de sistema operativo.
La disponibilidad de atributos siempre aparece con una lista de dos o ms
argumentos de atributos separados por comas. Estos argumentos comienzan con
uno de los siguientes nombres de
plataforma: iOS, iOSApplicationExtension , OSX ,
o OSXApplicationExtension . Tambin puede utilizar un asterisco ( * )

359

para indicar la disponibilidad de la declaracin de todos los nombres de


plataformas mencionadas anteriormente.Los argumentos restantes pueden
aparecer en cualquier orden y especificar informacin adicional acerca del ciclo
de vida de la declaracin, incluyendo los hitos importantes.
El disponible argumento indica que la declaracin no est disponible en
la plataforma especificada.
El introducido argumento indica la primera versin de la plataforma
especificada en el que se introdujo la declaracin. Tiene la siguiente forma:
El introducido argumento tiene la siguiente forma:
introduced= version number
El nmero de versin se compone de un nmero entero positivo o nmero de
coma flotante decimal.
El obsoleto argumento indica la primera versin de la plataforma
especificada en el que est desfasada y la declaracin. Tiene la siguiente
forma:
o

deprecated= version number


El nmero de versin se compone de un nmero entero positivo o nmero de
coma flotante decimal.
El Obsoleted argumento indica la primera versin de la plataforma
especificada en el que se obsoleta la declaracin. Cuando es obsoleto una
declaracin, se elimina de la plataforma especificada y ya no se puede
utilizar. El Obsoleted argumento tiene la siguiente forma:
o

obsoleted= version number


El nmero de versin se compone de un nmero entero positivo o nmero de
coma flotante decimal.
El mensaje argumento se utiliza para proporcionar un mensaje de texto
que se muestra por el compilador al emitir una advertencia o de error sobre
el uso de una declaracin en desuso o obsoleto.Tiene la siguiente forma:
o

message= message
El mensaje consiste en una cadena literal.
El renamed argumento se utiliza para proporcionar un mensaje de texto
que indica el nuevo nombre para una declaracin que se ha cambiado el
nombre. El nuevo nombre se muestra por el compilador cuando se emite un
error acerca de la utilizacin de una declaracin renombrado. Tiene la
siguiente forma:
o

renamed= new name


El nuevo nombre se compone de una cadena literal.
Usted puede utilizar el renamed argumento junto con el unavailable
argumento y una declaracin alias tipo para indicar a los clientes de su
cdigo que una declaracin se ha cambiado de nombre. Por ejemplo, esto es
til cuando el nombre de una declaracin se cambia entre versiones de un
marco o biblioteca.
o

360

// Primera versin
o

protocol MyProtocol {

// Definicin de protocolo

// Posterior liberacin renombra MyProtocol


o

protocol MyRenamedProtocol {

// Definicin de protocolo
o

o
o

@availability(*, unavailable, renamed="MyRenamedProtocol")

typealias MyProtocol = MyRenamedProtocol


Puede aplicar mltiples availability atributos en una sola declaracin
para especificar la disponibilidad de la declaracin en diferentes plataformas. El
compilador utiliza una availability atributo slo cuando el atributo
especifica una plataforma que coincida con la plataforma de destino actual.
NoReturn
o

Aplique este atributo a una declaracin de la funcin o mtodo para indicar que
el tipo correspondiente de esa funcin o mtodo, T , se noreturn T . Puede
marcar un tipo de funcin o mtodo con este atributo para indicar que la funcin
o el mtodo no devuelve a su invocador.
Puede sustituir una funcin o mtodo que no est marcado con
la NoReturn atributo con una funcin o mtodo que es. Dicho esto, no se
puede anular una funcin o mtodo que est marcado con el NoReturnatributo
con una funcin o mtodo que no es. Reglas similares se aplican cuando se
implementa un mtodo de protocolo en un tipo conforme.
NSCopying
Aplique este atributo a un almacenado propiedad de variable de una clase. Este
atributo hace setter de la propiedad que se sintetiza con una copia del valor
devuelto de la propiedad por el copyWithZone mtodo-en lugar del valor de
la propiedad en s. El tipo de la propiedad debe cumplir con
la NSCopying protocolo.
El NSCopying atributo se comporta de una manera similar a la de ObjectiveC copia atributo de propiedad.
NSManaged
Aplique este atributo a un almacenado propiedad de variable de una clase que
hereda de NSManagedObjectpara indicar que el almacenamiento y la
aplicacin de la propiedad se proporciona dinmicamente de Datos Bsicos en
tiempo de ejecucin basado en la descripcin de la entidad asociada.
objc

361

Aplique este atributo a toda declaracin que se puede representar en ObjectiveC, por ejemplo, las clases no anidadas, protocolos, propiedades y mtodos
(incluyendo getters y setters) de las clases y los protocolos, inicializadores,
deinitializers y subndices. El objc atributo le dice al compilador que la
declaracin est disponible para su uso en el cdigo de Objective-C.
Si aplica el objc atributo a una clase o un protocolo, se aplica implcitamente a
los miembros de esa clase o protocolo. El compilador tambin se aaden
automticamente las objc atributo a una clase que hereda de otra clase marcada
con el objc atributo. Protocolos marcados con el objc atributo no pueden
heredar de protocolos que no son.
El objc atributo opcionalmente acepta un solo argumento atributo, que consta
de un identificador. Utilice este atributo cuando desee exponer un nombre
diferente a Objective-C para la entidad la objc atributo se aplica a. Usted puede
utilizar este argumento para nombrar clases, protocolos, mtodos getters, setters,
y inicializadores. El ejemplo a continuacin expone el comprador para
el habilitado propiedad delExampleClass al cdigo de Objective-C
como isEnabled y no slo como el nombre de la propiedad en s.

@objc

class ExampleClass {

var enabled: Bool {

@objc(isEnabled) get {

// Return the appropriate value

}
UIApplicationMain

Aplicar este atributo para una clase para indicar que es el delegado aplicacin. El
uso de este atributo es equivalente a llamar la UIApplicationMain funcin
y pasando el nombre de esta clase como el nombre de la clase delegada.
Si no se utiliza este atributo, suministrar un main.swift archivo con
un principal funcin que llama a laUIApplicationMain funcin. Por
ejemplo, si su aplicacin utiliza una subclase personalizada
de UIApplicationcomo su clase principio, llame a
la UIApplicationMain funcin en lugar de utilizar este atributo.
Atributos Declaracin usados por Interface Builder
Atributos Interface Builder son atributos de declaracin utilizados por Interface Builder
para sincronizar con Xcode. Swift proporciona atributos de la interfaz siguiente
Constructor: IBAction , IBDesignable , IBInspectabley IBOutlet . Estos
atributos son conceptualmente lo mismo que sus homlogos de Objective-C.
Se aplica la IBOutlet y IBInspectable atributos a las declaraciones de
propiedades de una clase. Se aplica laIBAction atributo a declaraciones de mtodos
de una clase y la IBDesignable atributo a las declaraciones de clase.

362

Tipo Atributos
Puede aplicar los atributos de texto a slo tipos. Sin embargo, tambin se puede aplicar
el NoReturn atributo a una funcin o mtodo declaracin .
autoclosure
Este atributo se utiliza para demorar la evaluacin de una expresin envolviendo
automticamente esa expresin en un cierre sin argumentos. Aplique este
atributo a una funcin o mtodo de tipo que no toma ningn argumento y que
devuelve el tipo de la expresin. Para ver un ejemplo de cmo utilizar
elautoclosure atributo, vea Tipo de funcin .
NoReturn
Aplicar este atributo para el tipo de una funcin o mtodo para indicar que la
funcin o el mtodo no devuelve a su llamador. Tambin puede marcar una
funcin o declaracin de mtodo con este atributo para indicar que el tipo
correspondiente de esa funcin o mtodo, T , es noreturn T .
GRAMTICA DE UN ATRIBUTO
attribute @attribute-nameattribute-argument-clauseopt
attribute-name identifier
attribute-argument-clause (balanced-tokensopt)
attributes attributeattributesopt
balanced-tokens balanced-tokenbalanced-tokensopt
balanced-token (balanced-tokensopt)
balanced-token [balanced-tokensopt]
balanced-token {balanced-tokensopt}
balanced-token Any identifier, keyword, literal, or operator
balanced-token Any punctuation except (, ), [, ], {, or }

Patrones
Un patrn representa la estructura de un solo valor o un valor compuesto. Por ejemplo,
la estructura de una tupla (1, 2) es una lista separada por comas de dos
elementos. Dado que los patrones representan la estructura de un valor en lugar de
cualquier valor particular, puede hacer coincidir con una variedad de valores. Por
ejemplo, el patrn (x, y) coincide con la tupla (1, 2) y cualquier otro elemento de
la tupla de dos. Adems de hacer coincidir un patrn con un valor, puede extraer parte o
todo de un valor compuesto y unir cada parte a un nombre constante o variable.
En Swift, los patrones se producen en las declaraciones de variables y constantes (en su
lado izquierdo), en for- in las declaraciones y en los switch declaraciones (en
sus etiquetas de caso). Aunque ningn patrn puede ocurrir en las etiquetas de caso de
un switch de declaracin, en los otros contextos, slo los patrones de comodn,
patrones de identificador, y los patrones que contienen esos dos patrones pueden
ocurrir.

363

Puede especificar una anotacin de tipo para un patrn de comodines, un patrn


identificador, y un patrn de tupla para restringir el modelo que debe coincidir slo los
valores de un tipo determinado.
GRAMTICA DE UN PATRN
pattern wildcard-patterntype-annotationopt
pattern identifier-patterntype-annotationopt
pattern value-binding-pattern
pattern tuple-patterntype-annotationopt
pattern enum-case-pattern
pattern type-casting-pattern
pattern expression-pattern
Comodn Patrn
Un patrn de comodines coincide e ignora cualquier valor y se compone de un guin
bajo ( _ ). Utilice un patrn de comodn cuando no se preocupan por los valores que se
comparan con. Por ejemplo, los cdigo siguiente se repite a travs de la gama cerrado 1
... 3 , ignorando el valor actual de la gama en cada iteracin del bucle:

for _ in 1...3 {

// Do something three times.

GRAMTICA DE UN PATRN DE COMODINES


wildcard-patrn _
Patrn Identificador
Un patrn identificador coincide con cualquier valor y se une el valor coincidente con
un nombre de variable o constante. Por ejemplo, en la siguiente declaracin
constante, someValue es un patrn identificador que coincide con el valor 42 de
tipo Int :

let someValue = 42
Cuando el partido tiene xito, el valor 42 est obligado (asignado) para el nombre de
constante someValue .
Cuando el patrn en el lado izquierdo de una declaracin de variable o constante es un
patrn de identificador, el identificador de modelo es implcitamente un sub-patrn de
un patrn de enlace de valor-.
GRAMTICA DE UN PATRN IDENTIFICADOR
identifier-pattern identifier
Valor de Unin Patrn
Un patrn de enlace de valor- ata el valor corresponde a los nombres de variables o
constantes. Patrones de enlace de valor-que se unen un valor coincidente con el nombre

364

de una constante comenzar con la palabra clave dejar ; los que se unen al nombre de
la variable comienzan con la palabra clave var .
Identificadores de patrones dentro de un patrn de enlace de valor-se unen las nuevas
variables o constantes con nombre a sus valores coincidentes. Por ejemplo, se puede
descomponer los elementos de una tupla y enlazar el valor de cada elemento a un patrn
identificador correspondiente.

let point = (3, 2)

switch point {

// Bind x and y to the elements of point.

case let (x, y):

println("The point is at (\(x), \(y)).")

// imprime "El punto es en (3, 2)."


En el ejemplo anterior, dejar que distribuye a cada patrn identificador en el patrn
tupla (x, y) . Debido a este comportamiento, el interruptor casos caso dej
(x, y): y caso (sea x, y mucho y): coincide con los mismos valores.
GRAMTICA DE UN PATRN DE ENLACE DE VALORvalue-binding-pattern varpattern letpattern
Patrn Tuple
Un patrn tupla es una lista separada por comas de cero o ms patrones, entre
parntesis. Patrones Tuple coinciden los valores de tipos de tupla correspondientes.
Puede restringir un patrn tupla para que coincida con ciertos tipos de tipos de tupla
utilizando anotaciones de tipo. Por ejemplo, el patrn de tupla (x, y): (Int,
Int) en la declaracin constante let (x, y): (Int, Int) = (1,
2) coincide nicos tipos de tupla en la que ambos elementos son del tipo Int . Para
restringir slo algunos elementos de un patrn tupla, proporcionar anotaciones de tipo
directamente a los elementos individuales. Por ejemplo, el patrn de tupla en let (x:
Stinrg, y) coincide con cualquier tipo tupla de dos elementos, siempre que el
primer elemento es de tipo String.
Cuando se utiliza un patrn tupla como el patrn en una for- in estado o en una
declaracin de variable o constante, que slo puede contener patrones de comodines, los
patrones de identificadores, u otros patrones de tupla que contienen esos. Por ejemplo,
el siguiente cdigo no es vlido porque el elemento 0 en el patrn tupla (x, 0) es un
patrn de expresin:

let points = [(0, 0), (1, 0), (1, 1), (2, 0), (2, 1)]

// This code isn't valid.

for (x, 0) in points {

/* ... */

365

Los parntesis alrededor de un patrn tupla que contiene un solo elemento no tienen
ningn efecto. El patrn coincide con los valores de tipo de ese solo elemento. Por
ejemplo, los siguientes son equivalentes:

let a = 2 // a: Int = 2

let (a) = 2 // a: Int = 2

let (a): Int = 2 // a: Int = 2

GRAMTICA DE UN PATRN TUPLA


tuple-pattern (tuple-pattern-element-listopt)
tuple-pattern-element-list tuple-pattern-element tuple-pattern-element,tuple-patternelement-list
tuple-pattern-element pattern
Patrn Enumeracin Caso
Un patrn de la enumeracin caso coincide con un caso de un tipo de enumeracin
existente. Patrones de casos de enumeracin slo aparecen en el switch etiquetas
case declaracin.
Si el caso de enumeracin que ests tratando de coincidir con los valores asociados, el
patrn caso enumeracin correspondiente deber especificar un patrn de tupla que
contiene un elemento por cada valor asociado. Para ver un ejemplo que utiliza
un switch de declaracin para que coincida con los casos de enumeracin que
contienen valores asociados, ver valores asociados .
GRAMTICA DE UN PATRN DE CASO ENUMERACIN
enum-case-pattern type-identifieropt.enum-case-nametuple-patternopt
Patrones Tipo-casting
Hay dos patrones de tipo de fundicin a presin, el es patrn y el como patrn. Ambos
patrones de tipo de fundicin a presin slo aparecen en el interruptor etiquetas
case declaracin. El es y como los patrones tienen la siguiente forma:

is type

pattern as type
El es el patrn coincide con un valor si el tipo de valor que en tiempo de ejecucin es
el mismo que el tipo especificado en el lado derecho de la que is patrn o una
subclase de ese tipo. El is el patrn se comporta como el is operador en que ambos
realizan una conversin de tipos, pero descartan el tipo devuelto.
El as patrn coincide con un valor si el tipo de ese valor en tiempo de ejecucin es el
mismo que el tipo especificado en el lado derecho de la as patrn o una subclase de
ese tipo. Si el partido tiene xito, el tipo del valor coincidente se convierte
al modelo especificado en el lado izquierdo de la as patrn.
Para ver un ejemplo que utiliza un switch de declaracin para que coincida con los
valores es y comopatrones, vea la conversin de tipos para Todas y AnyObject .

366

GRAMTICA DE UN PATRN DE CONVERSIN DE TIPOS


(CASTING PATTERN)
type-casting-pattern is-pattern as-pattern
is-pattern istype
as-pattern patternastype
Patrn de Expresin
Un patrn de expresin representa el valor de una expresin. Los patrones de expresin
slo aparecen en el switch etiquetas case declaracin.
La expresin representada por el patrn de expresin se compara con el valor de una
expresin de entrada utilizando la biblioteca estndar Swift ~ = operador. Los partidos
tiene xito si el ~ = operador devuelve true .Por defecto, el ~ = operador compara
dos valores del mismo tipo con el == operador. Tambin puede coincidir con un valor
entero con un rango de enteros en un rango de objetos, como muestra el siguiente
ejemplo:

let point = (1, 2)

switch point {

case (0, 0):

println("(0, 0) is at the origin.")

case (-2...2, -2...2):

println("(\(point.0), \(point.1)) is near the origin.")

default:

println("The point is at (\(point.0), \(point.1)).")

// imprime "(1, 2) se encuentra cerca del origen."


Usted puede sobrecargar el ~ = operador para proporcionar un comportamiento a juego
expresin personalizada. Por ejemplo, se puede reescribir el ejemplo anterior para
comparar el punto de expresin con representaciones de serie de puntos.
// Sobrecargue el ~ = operador para que coincida con una
cadena con un entero

func ~=(pattern: String, value: Int) -> Bool {

return pattern == "\(value)"

switch point {

case ("0", "0"):

println("(0, 0) is at the origin.")

default:

println("The point is at (\(point.0), \(point.1)).")

// imprime "El punto est en (1, 2)."


367

GRAMTICA DE UN PATRN DE EXPRESIN


expression-pattern expression

Parmetros genricos y argumentos
En este captulo se describen los parmetros y argumentos de tipos genricos, las
funciones y los inicializadores. Cuando se declara un tipo genrico, funcin o
inicializador, se especifican los parmetros de tipo genrico que el tipo, funcin o
inicializador pueden trabajar. Estos parmetros de tipo actan como marcadores de
posicin que se reemplazan por los argumentos de tipo concretas reales cuando se crea
una instancia de un tipo genrico o de una funcin genrica o inicializador se llama.
Para una visin general de los genricos en Swift, vea Genricos .
Clusula Parmetro genrico
Una clusula de parmetro genrico especifica los parmetros de tipo de un tipo o una
funcin genrica, junto con las limitaciones y requisitos asociados en esos
parmetros. Una clusula parmetro genrico est entre corchetes angulares (<>) y tiene
una de las siguientes formas:

< generic parameter list >

< generic parameter list where requirements >


La lista de parmetros genricos es una lista separada por comas de parmetros
genricos, cada uno de los cuales tiene la siguiente forma:

type parameter : constraint


Un parmetro genrico consta de un parmetro de tipo seguido por una
opcional restriccin . Un parmetro de tipo es simplemente el nombre de un tipo de
marcador de posicin (por ejemplo, T , U , V , KeyType ,ValueType , y as
sucesivamente). Usted tiene acceso a los parmetros de tipo (y cualquiera de sus tipos
asociados) en el resto de la clase, funcin, o declaracin de inicializacin, incluso en la
firma de la funcin o inicializador.
La restriccin se especifica que un parmetro de tipo hereda de una clase especfica o se
ajusta a una composicin de protocolo o protocolo. Por ejemplo, en la funcin genrica
a continuacin, el parmetro genrico T: Comparable indica que cualquier
argumento de tipo sustituido por el parmetro de tipo T debe ser conforme a
la Comparable protocolo.

func simpleMin<T: Comparable>(x: T, y: T) -> T {

if x < y {

return y

return x

}
Debido a que Int y double , por ejemplo, ambos se ajustan a
la Comparable protocolo, esta funcin acepta argumentos de cualquier tipo. En

368

contraste con los tipos genricos, no se especifica una clusula argumento genrico
cuando se utiliza una funcin genrica o inicializador. Los argumentos de tipo en
cambio se infiere a partir del tipo de los argumentos que se pasan a la funcin o
inicializador.

simpleMin(17, 42) // T is inferred to be Int

simpleMin(3.14159, 2.71828) // T is inferred to be Double



Where Clusulas
Puede especificar requisitos adicionales sobre los parmetros de tipo y sus tipos
asociados mediante la inclusin de una where la clusula despus de la lista de
parmetros genricos . A where clusula consiste en la palabra clave en where,
seguido por una lista separada por comas de uno o varios requisitos .
Los requisitos en una where clusula especifica que un parmetro de tipo hereda de
una clase o se ajusta a una composicin de protocolo o protocolo. Aunque el where
clusula prev azcar sintctico para expresar restricciones simples sobre los parmetros
de tipo (por ejemplo, T: Comparable es equivalente a T where T:
Comparable y as sucesivamente), se puede utilizar para proporcionar restricciones
ms complejas sobre los parmetros de tipo y sus tipos asociados . Por ejemplo, puede
expresar las limitaciones que un tipo genricoT hereda de una clase C y se ajusta a un
protocolo P como <T donde T: C, T: P> .
Como se mencion anteriormente, puede restringir los tipos asociados de parmetros de
tipo para cumplir con los protocolos. Por ejemplo, la clusula de parmetro
genrico <T: Generador where T.Element: equatable> especifica
que T se ajusta al Generador de protocolo y el tipo asociado de T , T.Element ,
se ajusta a la equatable protocolo ( T tiene el tipo
asociado Element porque Generador declara Element y T se ajusta
aGenerador ).
Tambin puede especificar el requisito de que dos tipos sean idnticos, utilizando
el == operador. Por ejemplo, la clusula de parmetro genrico <T: Generador,
U: Generador donde T.Element == U.Element>expresa las restricciones
que T y U se ajustan al Generador de protocolo y que sus tipos asociados deben ser
idnticos.
Cualquier argumento de tipo sustituido por un parmetro de tipo debe cumplir con todas
las restricciones y requisitos que debe cumplir el parmetro de tipo.
Usted puede sobrecargar una funcin genrica o inicializador proporcionando diferentes
restricciones, requisitos, o ambos en los parmetros de tipo en la clusula parmetro
genrico. Cuando se llama a una funcin genrica sobrecargado o inicializador, el
compilador utiliza estas limitaciones para resolver la funcin o el inicializador para
invocar sobrecargado.
GRAMTICA DE UNA CLUSULA DE PARMETRO GENRICO
generic-parameter-clause <generic-parameter-listrequirement-clauseopt>
generic-parameter-list generic-parameter generic-parameter,generic-parameter-list
generic-parameter type-name
generic-parameter type-name:type-identifier

369

generic-parameter type-name:protocol-composition-type
requirement-clause whererequirement-list
requirement-list requirement requirement,requirement-list
requirement conformance-requirement same-type-requirement
conformance-requirement type-identifier:type-identifier
conformance-requirement type-identifier:protocol-composition-type
same-type-requirement type-identifier==type-identifier
Clusula Argumento Genrico
Una clusula argumento genrico especifica los argumentos de tipo de un tipo
genrico. Una clusula argumento genrico est entre corchetes angulares (<>) y tiene
la siguiente forma:
< generic argument list >
La lista de argumentos genricos es una lista separada por comas de los argumentos de
tipo. Un argumento de tipo es el nombre de un tipo concreto real que sustituye a un
parmetro de tipo correspondiente en la clusula genrica de un parmetro de tipo
genrico. El resultado es una versin especializada de este tipo genrico. Como
ejemplo, la biblioteca estndar Swift define un tipo de diccionario genrico como:

struct Dictionary<KeyType: Hashable, ValueType>: CollectionType,


DictionaryLiteralConvertible {

/* ... */

}
La versin especializada de la genrica Diccionario tipo, Diccionario
<String, int> se forma mediante la sustitucin de los parmetros
genricos KeyType: Hashable y ValueType con los argumentos de tipo
concreto de Cuerda y Int . Cada argumento de tipo debe satisfacer todas las
restricciones del parmetro genrico al que sustituye, incluidos cualesquiera requisitos
adicionales especificados en donde clusula. En el ejemplo anterior,
el KeyType parmetro de tipo est obligado a cumplir con la Hashable protocolo y,
por tanto, de cuerdastambin debe ajustarse a la Hashable protocolo.
Tambin puede sustituir un parmetro de tipo con un argumento de tipo que es en s una
versin especializada de un tipo genrico (siempre que cumplan las restricciones y los
requisitos apropiados). Por ejemplo, puede reemplazar el parmetro de tipo T en
el array <T> con una versin especializada de una matriz, array <Int> , para
formar una matriz cuyos elementos son a su vez matrices de enteros.

let arrayOfArrays: Array<Array<Int>> = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]


Como se menciona en la clusula genrica de parmetros , no utiliza una clusula
argumento genrico para especificar los argumentos de tipo de una funcin genrica o
inicializador.

370

GRAMTICA DE UNA CLUSULA ARGUMENTO GENRICO


generic-argument-clause <generic-argument-list>
generic-argument-list generic-argument generic-argument,generic-argument-list
generic-argument type


Resumen de la gramtica
En esta pgina
Declaraciones
GRAMMAR OF A STATEMENT
statement expression;opt
statement declaration;opt
statement loop-statement;opt
statement branch-statement;opt
statement labeled-statement;opt
statement control-transfer-statement;opt
statements statementstatementsopt
GRAMMAR OF A LOOP STATEMENT
loop-statement for-statement
loop-statement for-in-statement
loop-statement while-statement
loop-statement do-while-statement
GRAMMAR OF A FOR STATEMENT
for-statement forfor-initopt;expressionopt;expressionoptcode-block
for-statement for(for-initopt;expressionopt;expressionopt)code-block
for-init variable-declaration expression-list
GRAMMAR OF A FOR-IN STATEMENT
for-in-statement forpatterninexpressioncode-block
GRAMMAR OF A WHILE STATEMENT
while-statement whilewhile-conditioncode-block
while-condition expression declaration
GRAMMAR OF A DO-WHILE STATEMENT
do-while-statement docode-blockwhilewhile-condition
GRAMMAR OF A BRANCH STATEMENT
branch-statement if-statement
branch-statement switch-statement
GRAMMAR OF AN IF STATEMENT
if-statement ifif-conditioncode-blockelse-clauseopt
if-condition expression declaration
else-clause elsecode-block elseif-statement
GRAMMAR OF A SWITCH STATEMENT

371

switch-statement switchexpression{switch-casesopt}
switch-cases switch-caseswitch-casesopt
switch-case case-labelstatements default-labelstatements
switch-case case-label; default-label;
case-label casecase-item-list:
case-item-list patternguard-clauseopt patternguard-clauseopt,case-item-list
default-label default:
guard-clause whereguard-expression
guard-expression expression
GRAMMAR OF A LABELED STATEMENT
labeled-statement statement-labelloop-statement statement-labelswitch-statement
statement-label label-name:
label-name identifier
GRAMMAR OF A CONTROL TRANSFER STATEMENT
control-transfer-statement break-statement
control-transfer-statement continue-statement
control-transfer-statement fallthrough-statement
control-transfer-statement return-statement
GRAMMAR OF A BREAK STATEMENT
break-statement breaklabel-nameopt
GRAMMAR OF A CONTINUE STATEMENT
continue-statement continuelabel-nameopt
GRAMMAR OF A FALLTHROUGH STATEMENT
fallthrough-statement fallthrough
GRAMMAR OF A RETURN STATEMENT
return-statement returnexpressionopt
Generic Parameters and Arguments
GRAMMAR OF A GENERIC PARAMETER CLAUSE
generic-parameter-clause <generic-parameter-listrequirement-clauseopt>
generic-parameter-list generic-parameter generic-parameter,generic-parameter-list
generic-parameter type-name
generic-parameter type-name:type-identifier
generic-parameter type-name:protocol-composition-type
requirement-clause whererequirement-list
requirement-list requirement requirement,requirement-list
requirement conformance-requirement same-type-requirement
conformance-requirement type-identifier:type-identifier
conformance-requirement type-identifier:protocol-composition-type
same-type-requirement type-identifier==type-identifier
GRAMMAR OF A GENERIC ARGUMENT CLAUSE
generic-argument-clause <generic-argument-list>
generic-argument-list generic-argument generic-argument,generic-argument-list

372

generic-argument type
Declarations
GRAMMAR OF A DECLARATION
declaration import-declaration
declaration constant-declaration
declaration variable-declaration
declaration typealias-declaration
declaration function-declaration
declaration enum-declaration
declaration struct-declaration
declaration class-declaration
declaration protocol-declaration
declaration initializer-declaration
declaration deinitializer-declaration
declaration extension-declaration
declaration subscript-declaration
declaration operator-declaration
declarations declarationdeclarationsopt
GRAMMAR OF A TOP-LEVEL DECLARATION
top-level-declaration statementsopt
GRAMMAR OF A CODE BLOCK
code-block {statementsopt}
GRAMMAR OF AN IMPORT DECLARATION
import-declaration attributesoptimportimport-kindoptimport-path
import-kind typealias struct class enum protocol var func
import-path import-path-identifier import-path-identifier.import-path
import-path-identifier identifier operator
GRAMMAR OF A CONSTANT DECLARATION
constant-declaration attributesoptdeclaration-modifiersoptletpattern-initializer-list
pattern-initializer-list pattern-initializer pattern-initializer,pattern-initializer-list
pattern-initializer patterninitializeropt
initializer =expression
GRAMMAR OF A VARIABLE DECLARATION
variable-declaration variable-declaration-headpattern-initializer-list
variable-declaration variable-declaration-headvariable-nametype-annotationcodeblock
variable-declaration variable-declaration-headvariable-nametype-annotationgettersetter-block
variable-declaration variable-declaration-headvariable-nametype-annotationgettersetter-keyword-block
variable-declaration variable-declaration-headvariable-nametype-annotationinitializeroptwillSet-didSet-block

373

variable-declaration-head attributesoptdeclaration-modifiersoptvar
variable-name identifier
getter-setter-block {getter-clausesetter-clauseopt}
getter-setter-block {setter-clausegetter-clause}
getter-clause attributesoptgetcode-block
setter-clause attributesoptsetsetter-nameoptcode-block
setter-name (identifier)
getter-setter-keyword-block {getter-keyword-clausesetter-keyword-clauseopt}
getter-setter-keyword-block {setter-keyword-clausegetter-keyword-clause}
getter-keyword-clause attributesoptget
setter-keyword-clause attributesoptset
willSet-didSet-block {willSet-clausedidSet-clauseopt}
willSet-didSet-block {didSet-clausewillSet-clause}
willSet-clause attributesoptwillSetsetter-nameoptcode-block
didSet-clause attributesoptdidSetsetter-nameoptcode-block
GRAMMAR OF A TYPE ALIAS DECLARATION
typealias-declaration typealias-headtypealias-assignment
typealias-head attributesoptaccess-level-modifieropttypealiastypealias-name
typealias-name identifier
typealias-assignment =type
GRAMMAR OF A FUNCTION DECLARATION
function-declaration function-headfunction-namegeneric-parameter-clauseoptfunction-signaturefunction-body
function-head attributesoptdeclaration-modifiersoptfunc
function-name identifier operator
function-signature parameter-clausesfunction-resultopt
function-result ->attributesopttype
function-body code-block
parameter-clauses parameter-clauseparameter-clausesopt
parameter-clause () (parameter-list...opt)
parameter-list parameter parameter,parameter-list
parameter inoutoptletopt#optexternal-parameter-nameoptlocal-parameter-nametypeannotationdefault-argument-clauseopt
parameter inoutoptvar#optexternal-parameter-nameoptlocal-parameter-nametypeannotationdefault-argument-clauseopt
parameter attributesopttype
external-parameter-name identifier _
local-parameter-name identifier _
default-argument-clause =expression
GRAMMAR OF AN ENUMERATION DECLARATION
enum-declaration attributesoptaccess-level-modifieroptunion-style-enum
enum-declaration attributesoptaccess-level-modifieroptraw-value-style-enum
union-style-enum enumenum-namegeneric-parameter-clauseopttype-inheritanceclauseopt{union-style-enum-membersopt}

374

union-style-enum-members union-style-enum-memberunion-style-enum-membersopt
union-style-enum-member declaration union-style-enum-case-clause
union-style-enum-case-clause attributesoptcaseunion-style-enum-case-list
union-style-enum-case-list union-style-enum-case union-style-enum-case,unionstyle-enum-case-list
union-style-enum-case enum-case-nametuple-typeopt
enum-name identifier
enum-case-name identifier
raw-value-style-enum enumenum-namegeneric-parameter-clauseopttype-inheritanceclause{raw-value-style-enum-members}
raw-value-style-enum-members raw-value-style-enum-memberraw-value-styleenum-membersopt
raw-value-style-enum-member declaration raw-value-style-enum-case-clause
raw-value-style-enum-case-clause attributesoptcaseraw-value-style-enum-case-list
raw-value-style-enum-case-list raw-value-style-enum-case raw-value-style-enumcase,raw-value-style-enum-case-list
raw-value-style-enum-case enum-case-nameraw-value-assignmentopt
raw-value-assignment =literal
GRAMMAR OF A STRUCTURE DECLARATION
struct-declaration attributesoptaccess-level-modifieroptstructstruct-namegenericparameter-clauseopttype-inheritance-clauseoptstruct-body
struct-name identifier
struct-body {declarationsopt}
GRAMMAR OF A CLASS DECLARATION
class-declaration attributesoptaccess-level-modifieroptclassclass-namegenericparameter-clauseopttype-inheritance-clauseoptclass-body
class-name identifier
class-body {declarationsopt}
GRAMMAR OF A PROTOCOL DECLARATION
protocol-declaration attributesoptaccess-level-modifieroptprotocolprotocol-nametypeinheritance-clauseoptprotocol-body
protocol-name identifier
protocol-body {protocol-member-declarationsopt}
protocol-member-declaration protocol-property-declaration
protocol-member-declaration protocol-method-declaration
protocol-member-declaration protocol-initializer-declaration
protocol-member-declaration protocol-subscript-declaration
protocol-member-declaration protocol-associated-type-declaration
protocol-member-declarations protocol-member-declarationprotocol-memberdeclarationsopt
GRAMMAR OF A PROTOCOL PROPERTY DECLARATION
protocol-property-declaration variable-declaration-headvariable-nametypeannotationgetter-setter-keyword-block
GRAMMAR OF A PROTOCOL METHOD DECLARATION

375

protocol-method-declaration function-headfunction-namegeneric-parameter-clauseoptfunction-signature
GRAMMAR OF A PROTOCOL INITIALIZER DECLARATION
protocol-initializer-declaration initializer-headgeneric-parameter-clauseoptparameter-clause
GRAMMAR OF A PROTOCOL SUBSCRIPT DECLARATION
protocol-subscript-declaration subscript-headsubscript-resultgetter-setter-keywordblock
GRAMMAR OF A PROTOCOL ASSOCIATED TYPE
DECLARATION
protocol-associated-type-declaration typealias-headtype-inheritance-clauseopttypealias-assignmentopt
GRAMMAR OF AN INITIALIZER DECLARATION
initializer-declaration initializer-headgeneric-parameter-clauseoptparameter-clauseinitializer-body
initializer-head attributesoptdeclaration-modifiersoptinit
initializer-body code-block
GRAMMAR OF A DEINITIALIZER DECLARATION
deinitializer-declaration attributesoptdeinitcode-block
GRAMMAR OF AN EXTENSION DECLARATION
extension-declaration access-level-modifieroptextensiontype-identifiertypeinheritance-clauseoptextension-body
extension-body {declarationsopt}
GRAMMAR OF A SUBSCRIPT DECLARATION
subscript-declaration subscript-headsubscript-resultcode-block
subscript-declaration subscript-headsubscript-resultgetter-setter-block
subscript-declaration subscript-headsubscript-resultgetter-setter-keyword-block
subscript-head attributesoptdeclaration-modifiersoptsubscriptparameter-clause
subscript-result ->attributesopttype
GRAMMAR OF AN OPERATOR DECLARATION
operator-declaration prefix-operator-declaration postfix-operator-declarationinfix-operator-declaration
prefix-operator-declaration prefixoperatoroperator{}
postfix-operator-declaration postfixoperatoroperator{}
infix-operator-declaration infixoperatoroperator{infix-operator-attributesopt}
infix-operator-attributes precedence-clauseoptassociativity-clauseopt
precedence-clause precedenceprecedence-level
precedence-level A decimal integer between 0 and 255, inclusive
associativity-clause associativityassociativity
associativity left right none
GRAMMAR OF A DECLARATION MODIFIER

376

declaration-modifier class convenience dynamic final infix lazy mutatingnonmutating optional override postfix prefix required static unownedunowned(safe) unowned(unsafe) weak
declaration-modifier access-level-modifier
declaration-modifiers declaration-modifierdeclaration-modifiersopt
access-level-modifier internal internal(set)
access-level-modifier private private(set)
access-level-modifier public public(set)
access-level-modifiers access-level-modifieraccess-level-modifiersopt
Patterns
GRAMMAR OF A PATTERN
pattern wildcard-patterntype-annotationopt
pattern identifier-patterntype-annotationopt
pattern value-binding-pattern
pattern tuple-patterntype-annotationopt
pattern enum-case-pattern
pattern type-casting-pattern
pattern expression-pattern
GRAMMAR OF A WILDCARD PATTERN
wildcard-pattern _
GRAMMAR OF AN IDENTIFIER PATTERN
identifier-pattern identifier
GRAMMAR OF A VALUE-BINDING PATTERN
value-binding-pattern varpattern letpattern
GRAMMAR OF A TUPLE PATTERN
tuple-pattern (tuple-pattern-element-listopt)
tuple-pattern-element-list tuple-pattern-element tuple-pattern-element,tuple-patternelement-list
tuple-pattern-element pattern
GRAMMAR OF AN ENUMERATION CASE PATTERN
enum-case-pattern type-identifieropt.enum-case-nametuple-patternopt
GRAMMAR OF A TYPE CASTING PATTERN
type-casting-pattern is-pattern as-pattern
is-pattern istype
as-pattern patternastype
GRAMMAR OF AN EXPRESSION PATTERN
expression-pattern expression
Attributes
GRAMMAR OF AN ATTRIBUTE
attribute @attribute-nameattribute-argument-clauseopt

377

attribute-name identifier
attribute-argument-clause (balanced-tokensopt)
attributes attributeattributesopt
balanced-tokens balanced-tokenbalanced-tokensopt
balanced-token (balanced-tokensopt)
balanced-token [balanced-tokensopt]
balanced-token {balanced-tokensopt}
balanced-token Any identifier, keyword, literal, or operator
balanced-token Any punctuation except (, ), [, ], {, or }
Expressions
GRAMMAR OF AN EXPRESSION
expression prefix-expressionbinary-expressionsopt
expression-list expression expression,expression-list
GRAMMAR OF A PREFIX EXPRESSION
prefix-expression prefix-operatoroptpostfix-expression
prefix-expression in-out-expression
in-out-expression &identifier
GRAMMAR OF A BINARY EXPRESSION
binary-expression binary-operatorprefix-expression
binary-expression assignment-operatorprefix-expression
binary-expression conditional-operatorprefix-expression
binary-expression type-casting-operator
binary-expressions binary-expressionbinary-expressionsopt
GRAMMAR OF AN ASSIGNMENT OPERATOR
assignment-operator =
GRAMMAR OF A CONDITIONAL OPERATOR
conditional-operator ?expression:
GRAMMAR OF A TYPE-CASTING OPERATOR
type-casting-operator istype
type-casting-operator astype
type-casting-operator as?type
GRAMMAR OF A PRIMARY EXPRESSION
primary-expression identifiergeneric-argument-clauseopt
primary-expression literal-expression
primary-expression self-expression
primary-expression superclass-expression
primary-expression closure-expression
primary-expression parenthesized-expression
primary-expression implicit-member-expression
primary-expression wildcard-expression
GRAMMAR OF A LITERAL EXPRESSION
literal-expression literal

378

literal-expression array-literal dictionary-literal


literal-expression __FILE__ __LINE__ __COLUMN__ __FUNCTION__
array-literal [array-literal-itemsopt]
array-literal-items array-literal-item,opt array-literal-item,array-literal-items
array-literal-item expression
dictionary-literal [dictionary-literal-items] [:]
dictionary-literal-items dictionary-literal-item,opt dictionary-literal-item,dictionaryliteral-items
dictionary-literal-item expression:expression
GRAMMAR OF A SELF EXPRESSION
self-expression self
self-expression self.identifier
self-expression self[expression]
self-expression self.init
GRAMMAR OF A SUPERCLASS EXPRESSION
superclass-expression superclass-method-expression superclass-subscriptexpression superclass-initializer-expression
superclass-method-expression super.identifier
superclass-subscript-expression super[expression]
superclass-initializer-expression super.init
GRAMMAR OF A CLOSURE EXPRESSION
closure-expression {closure-signatureoptstatements}
closure-signature parameter-clausefunction-resultoptin
closure-signature identifier-listfunction-resultoptin
closure-signature capture-listparameter-clausefunction-resultoptin
closure-signature capture-listidentifier-listfunction-resultoptin
closure-signature capture-listin
capture-list [capture-specifierexpression]
capture-specifier weak unowned unowned(safe) unowned(unsafe)
GRAMMAR OF A IMPLICIT MEMBER EXPRESSION
implicit-member-expression .identifier
GRAMMAR OF A PARENTHESIZED EXPRESSION
parenthesized-expression (expression-element-listopt)
expression-element-list expression-element expression-element,expression-elementlist
expression-element expression identifier:expression
GRAMMAR OF A WILDCARD EXPRESSION
wildcard-expression _
GRAMMAR OF A POSTFIX EXPRESSION
postfix-expression primary-expression
postfix-expression postfix-expressionpostfix-operator
postfix-expression function-call-expression
postfix-expression initializer-expression

379

postfix-expression explicit-member-expression
postfix-expression postfix-self-expression
postfix-expression dynamic-type-expression
postfix-expression subscript-expression
postfix-expression forced-value-expression
postfix-expression optional-chaining-expression
GRAMMAR OF A FUNCTION CALL EXPRESSION
function-call-expression postfix-expressionparenthesized-expression
function-call-expression postfix-expressionparenthesized-expressionopttrailingclosure
trailing-closure closure-expression
GRAMMAR OF AN INITIALIZER EXPRESSION
initializer-expression postfix-expression.init
GRAMMAR OF AN EXPLICIT MEMBER EXPRESSION
explicit-member-expression postfix-expression.decimal-digits
explicit-member-expression postfix-expression.identifiergeneric-argument-clauseopt
GRAMMAR OF A SELF EXPRESSION
postfix-self-expression postfix-expression.self
GRAMMAR OF A DYNAMIC TYPE EXPRESSION
dynamic-type-expression postfix-expression.dynamicType
GRAMMAR OF A SUBSCRIPT EXPRESSION
subscript-expression postfix-expression[expression-list]
GRAMMAR OF A FORCED-VALUE EXPRESSION
forced-value-expression postfix-expression!
GRAMMAR OF AN OPTIONAL-CHAINING EXPRESSION
optional-chaining-expression postfix-expression?
Lexical Structure
GRAMMAR OF AN IDENTIFIER
identifier identifier-headidentifier-charactersopt
identifier `identifier-headidentifier-charactersopt`
identifier implicit-parameter-name
identifier-list identifier identifier,identifier-list
identifier-head Upper- or lowercase letter A through Z
identifier-head _
identifier-head U+00A8, U+00AA, U+00AD, U+00AF, U+00B2U+00B5, or
U+00B7U+00BA
identifier-head U+00BCU+00BE, U+00C0U+00D6, U+00D8U+00F6, or
U+00F8U+00FF
identifier-head U+0100U+02FF, U+0370U+167F, U+1681U+180D, or
U+180FU+1DBF
identifier-head U+1E00U+1FFF

380

identifier-head U+200BU+200D, U+202AU+202E, U+203FU+2040, U+2054,


or U+2060U+206F
identifier-head U+2070U+20CF, U+2100U+218F, U+2460U+24FF, or U+2776
U+2793
identifier-head U+2C00U+2DFF or U+2E80U+2FFF
identifier-head U+3004U+3007, U+3021U+302F, U+3031U+303F, or U+3040
U+D7FF
identifier-head U+F900U+FD3D, U+FD40U+FDCF, U+FDF0U+FE1F, or
U+FE30U+FE44
identifier-head U+FE47U+FFFD
identifier-head U+10000U+1FFFD, U+20000U+2FFFD, U+30000U+3FFFD, or
U+40000U+4FFFD
identifier-head U+50000U+5FFFD, U+60000U+6FFFD, U+70000U+7FFFD, or
U+80000U+8FFFD
identifier-head U+90000U+9FFFD, U+A0000U+AFFFD, U+B0000U+BFFFD,
or U+C0000U+CFFFD
identifier-head U+D0000U+DFFFD or U+E0000U+EFFFD
identifier-character Digit 0 through 9
identifier-character U+0300U+036F, U+1DC0U+1DFF, U+20D0U+20FF, or
U+FE20U+FE2F
identifier-character identifier-head
identifier-characters identifier-characteridentifier-charactersopt
implicit-parameter-name $decimal-digits
GRAMMAR OF A LITERAL
literal integer-literal floating-point-literal string-literal
literal true false nil
GRAMMAR OF AN INTEGER LITERAL
integer-literal binary-literal
integer-literal octal-literal
integer-literal decimal-literal
integer-literal hexadecimal-literal
binary-literal 0bbinary-digitbinary-literal-charactersopt
binary-digit Digit 0 or 1
binary-literal-character binary-digit _
binary-literal-characters binary-literal-characterbinary-literal-charactersopt
octal-literal 0ooctal-digitoctal-literal-charactersopt
octal-digit Digit 0 through 7
octal-literal-character octal-digit _
octal-literal-characters octal-literal-characteroctal-literal-charactersopt
decimal-literal decimal-digitdecimal-literal-charactersopt
decimal-digit Digit 0 through 9
decimal-digits decimal-digitdecimal-digitsopt
decimal-literal-character decimal-digit _
decimal-literal-characters decimal-literal-characterdecimal-literal-charactersopt
hexadecimal-literal 0xhexadecimal-digithexadecimal-literal-charactersopt

381

hexadecimal-digit Digit 0 through 9, a through f, or A through F


hexadecimal-literal-character hexadecimal-digit _
hexadecimal-literal-characters hexadecimal-literal-characterhexadecimal-literalcharactersopt
GRAMMAR OF A FLOATING-POINT LITERAL
floating-point-literal decimal-literaldecimal-fractionoptdecimal-exponentopt
floating-point-literal hexadecimal-literalhexadecimal-fractionopthexadecimalexponent
decimal-fraction .decimal-literal
decimal-exponent floating-point-esignoptdecimal-literal
hexadecimal-fraction .hexadecimal-digithexadecimal-literal-charactersopt
hexadecimal-exponent floating-point-psignoptdecimal-literal
floating-point-e e E
floating-point-p p P
sign + GRAMMAR OF A STRING LITERAL
string-literal "quoted-textopt"
quoted-text quoted-text-itemquoted-textopt
quoted-text-item escaped-character
quoted-text-item \(expression)
quoted-text-item Any Unicode extended grapheme cluster except ", \, U+000A, or
U+000D
escaped-character \0 \\ \t \n \r \" \'
escaped-character \u{unicode-scalar-digits}
unicode-scalar-digits Between one and eight hexadecimal digits
GRAMMAR OF OPERATORS
operator operator-headoperator-charactersopt
operator dot-operator-headdot-operator-charactersopt
operator-head / = - + ! * % < > & | ^ ~
operator-head U+00A1U+00A7
operator-head U+00A9 or U+00AB
operator-head U+00AC or U+00AE
operator-head U+00B0U+00B1, U+00B6, U+00BB, U+00BF, U+00D7, or
U+00F7
operator-head U+2016U+2017 or U+2020U+2027
operator-head U+2030U+203E
operator-head U+2041U+2053
operator-head U+2055U+205E
operator-head U+2190U+23FF
operator-head U+2500U+2775
operator-head U+2794U+2BFF
operator-head U+2E00U+2E7F
operator-head U+3001U+3003
operator-head U+3008U+3030

382

operator-character operator-head
operator-character U+0300U+036F
operator-character U+1DC0U+1DFF
operator-character U+20D0U+20FF
operator-character U+FE00U+FE0F
operator-character U+FE20U+FE2F
operator-character U+E0100U+E01EF
operator-characters operator-characteroperator-charactersopt
dot-operator-head ..
dot-operator-character . operator-character
dot-operator-characters dot-operator-characterdot-operator-charactersopt
binary-operator operator
prefix-operator operator
postfix-operator operator
Types
GRAMMAR OF A TYPE
type array-type dictionary-type function-type type-identifier tuple-type optionaltype implicitly-unwrapped-optional-type protocol-composition-type metatype-type
GRAMMAR OF A TYPE ANNOTATION
type-annotation :attributesopttype
GRAMMAR OF A TYPE IDENTIFIER
type-identifier type-namegeneric-argument-clauseopt type-namegeneric-argumentclauseopt.type-identifier
type-name identifier
GRAMMAR OF A TUPLE TYPE
tuple-type (tuple-type-bodyopt)
tuple-type-body tuple-type-element-list...opt
tuple-type-element-list tuple-type-element tuple-type-element,tuple-type-element-list
tuple-type-element attributesoptinoutopttype inoutoptelement-nametype-annotation
element-name identifier
GRAMMAR OF A FUNCTION TYPE
function-type type->type
GRAMMAR OF AN ARRAY TYPE
array-type [type]
GRAMMAR OF A DICTIONARY TYPE
dictionary-type [type:type]
GRAMMAR OF AN OPTIONAL TYPE
optional-type type?
GRAMMAR OF AN IMPLICITLY UNWRAPPED OPTIONAL TYPE
implicitly-unwrapped-optional-type type!
GRAMMAR OF A PROTOCOL COMPOSITION TYPE

383

protocol-composition-type protocol<protocol-identifier-listopt>
protocol-identifier-list protocol-identifier protocol-identifier,protocol-identifier-list
protocol-identifier type-identifier
GRAMMAR OF A METATYPE TYPE
metatype-type type.Type type.Protocol
GRAMMAR OF A TYPE INHERITANCE CLAUSE
type-inheritance-clause :class-requirement,type-inheritance-list
type-inheritance-clause :class-requirement
type-inheritance-clause :type-inheritance-list
type-inheritance-list type-identifier type-identifier,type-inheritance-list
class-requirement class








384

You might also like