Swift es un nuevo lenguaje de programación para iOS, OS X, watchOS y aplicaciones tvOS que se basa en lo mejor de C y Objective-C, sin las limitaciones de compatibilidad C. Swift adopta patrones de programación seguras y añade características modernas para que la programación sea más fácil, más flexible y más divertida. Borrón y cuenta nueva de Swift, respaldado por Cacao y Touch framework, es una oportunidad para re-imaginar cómo funciona el desarrollo de software.
Swift ha surgido en base a años de elaboración. La manzana sentó las bases de Swift por el avance de nuestro compilador, depurador, y la infraestructura marco existente. Sea simplificado la gestión de memoria con el Automatic Reference Counting (ARC). Se ha modernizado y estandarizado en todas partes. Objective-C en sí ha evolucionado para soportar bloques, literales colección, y los módulos, lo que permite la adopción de las tecnologías framework lingüísticas modernas sin interrupción. Gracias a este trabajo preliminar, pueden introducir un nuevo lenguaje para el futuro del desarrollo de software de Apple.
Swift le resulta familiar a los desarrolladores de Objective-C. Adopta la legibilidad de los parámetros con nombre de Objetivo-C y el poder del modelo de objetos dinámicos de Objective-C. Proporciona un acceso transparente a los marcos de cacao existentes y la interoperabilidad mezclar y combinar con el código de Objective-C. La construcción de esta base común, Swift introduce muchas nuevas características y unifica las partes procesales y orientados a objetos del lenguaje.
Swift es amigable para los nuevos programadores. Es el primer lenguaje de programación de sistemas de calidad industrial que es tan expresiva y agradable como un lenguaje de script. Es compatible con juegos infantiles, una característica innovadora que permite a los programadores para experimentar con el código Swift y ver los resultados inmediatamente, sin la sobrecarga de la construcción y funcionamiento de una aplicación.
Swift combina lo mejor del pensamiento lengua moderna, con la sabiduría de la cultura más amplia de ingeniería de Apple. El compilador está optimizado para el rendimiento y el lenguaje está optimizado para el desarrollo, sin comprometer a ambos. Está diseñado para escalar desde "hola, mundo" a un sistema operativo completo. Todo esto hace que Swift una inversión de futuro para los desarrolladores y sonido para Apple.
Swift es una fantástica manera de escribir iOS, OS X, watchOS y aplicaciones tvOS, y seguirá evolucionando con nuevas características y capacidades.
Tour de Swift
La tradición sugiere que el primer programa en un nuevo lenguaje debe imprimir las palabras "Hola, mundo!" En la pantalla. En Swift, esto se puede hacer en una sola línea:print("Hello, world!")
Valores simples.
Si usted ha escrito el código en C o Objective-C, esta sintaxis es familiar en Swift, esta línea de código es un programa completo. No es necesario importar una biblioteca independiente para la funcionalidad como de entrada/salida o el manejo de cadenas. El código escrito en el ámbito global se utiliza como punto de entrada para el programa, por lo que no necesita una función main(). También no es necesario escribir un punto y coma al final de cada declaración.
Este tour le da suficiente información para empezar a escribir código en Swift, mostrando cómo llevar a cabo una variedad de tareas de programación.
Este tour le da suficiente información para empezar a escribir código en Swift, mostrando cómo llevar a cabo una variedad de tareas de programación.
Usamos 'let' para hacer una constante y 'var' para hacer una variable. El valor de una constante no tiene por qué ser conocido en tiempo de compilación, pero hay que asignarle un valor exactamente una vez. Esto significa que puede usar constantes para nombrar un valor que se determina una vez, pero se utiliza en muchos lugares.
Por ejemplo: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 de forma explícita. Proporcionar un valor al crear una constante o variable permite al compilador inferir su tipo. En el ejemplo anterior, el compilador infiere que Variable es un número entero, ya que su valor inicial es un número entero.
Si el valor inicial no proporciona suficiente información (o si no hay valor inicial), especifique el tipo escribiéndolo después de la variable, separados por dos puntos.
let implicitInteger = 70Si el valor inicial no proporciona suficiente información (o si no hay valor inicial), especifique el tipo escribiéndolo después de la variable, separados por dos puntos.
let implicitDouble = 70.0
let explicitDouble: Double = 70
Los valores no se convierten implícitamente a otro tipo. Si necesitamos convertir un valor a un tipo diferente, crearemos una instancia del tipo deseado.
let label = "The width is "
let width = 94
let widthLabel = label + String(width)
Hay una manera aún más sencilla para incluir valores en cadenas: Escribir el valor entre paréntesis, y escribir una barra invertida (\) antes del paréntesis. Por ejemplo:let width = 94
let widthLabel = label + String(width)
let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."
Crear matrices y diccionarios utilizando corchetes ([]), y acceder a sus elementos escribiendo el índice o una clave entre paréntesis. Una coma se permite después del último elemento.
var shoppingList = ["catfish", "water", "tulips", "blue paint"]
shoppingList[1] = "bottle of water"
var occupations = [
"Malcolm": "Captain",
"Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"
let emptyArray = [String]()
let emptyDictionary = [String: Float]()
Si la información de tipo se puede deducir, se puede escribir como una matriz vacía [] y un diccionario vacío como [:] - por ejemplo, cuando se establece un nuevo valor para una variable o al pasar un argumento a una función.
shoppingList = []
occupations = [:]
Flujo de control
Utilice if y switch para hacer condicionales y el uso for-in, for, while y repeat-while para hacer bucles. Los paréntesis alrededor de la variable de condición o de bucle son opcionales. Se requieren 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
}
}
print(teamScore)
var teamScore = 0
for score in individualScores {
if score > 50 {
teamScore += 3
} else {
teamScore += 1
}
}
print(teamScore)
En una sentencia if, el condicional debe ser una expresión booleana, esto significa que el código if puntuación{...} es un error, no una comparación implícita a cero.
Se puede utilizar if y let para trabajar con valores que pudieran faltar. Estos valores se representan como opcionales. Un valor opcional o bien contiene un valor nulo o contiene para indicar que se pierde un valor. Escribe un signo de interrogación (?) Después de que el tipo de un valor para marcar el valor como opcional.
var optionalString: String? = "Hello"Se puede utilizar if y let para trabajar con valores que pudieran faltar. Estos valores se representan como opcionales. Un valor opcional o bien contiene un valor nulo o contiene para indicar que se pierde un valor. Escribe un signo de interrogación (?) Después de que el tipo de un valor para marcar el valor como opcional.
print(optionalString == nil)
var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
greeting = "Hello, \(name)"
}
Si el optionalName es nulo, el condicional es falso y el código entre llaves se omite. De lo contrario, el valor opcional se desenvuelve y se asigna a la constante después de let, que hace que el desempaquetado valor disponible en el interior del bloque de código.
Otra forma de manejar los valores opcionales es proporcionar un valor por defecto utilizando el ?? operador. Si el valor opcional no está presente, el valor predeterminado se utiliza en su lugar.
let nickName: String? = nil
let fullName: String = "John Appleseed"
let informalGreeting = "Hi \(nickName ?? fullName)"
let nickName: String? = nil
let fullName: String = "John Appleseed"
let informalGreeting = "Hi \(nickName ?? fullName)"
Los switches soportan cualquier tipo de datos y una amplia variedad de operadores de comparación, que no se limitan a los números enteros y las pruebas para la igualdad.
let vegetable = "red pepper"
switch vegetable {
case "celery":
print("Add some raisins and make ants on a log.")
case "cucumber", "watercress":
print("That would make a good tea sandwich.")
case let x where x.hasSuffix("pepper"):
print("Is it a spicy \(x)?")
default:
print("Everything tastes good in soup.")
}
let vegetable = "red pepper"
switch vegetable {
case "celery":
print("Add some raisins and make ants on a log.")
case "cucumber", "watercress":
print("That would make a good tea sandwich.")
case let x where x.hasSuffix("pepper"):
print("Is it a spicy \(x)?")
default:
print("Everything tastes good in soup.")
}
Let puede ser usado en un patrón para asignar el valor que este emparejado, que parte de un patrón a una constante.
Después de ejecutar el código dentro de la caja del interruptor que hacía juego, el programa sale de la sentencia switch. La ejecución no continúa al siguiente caso, lo que no hay necesidad de romper explícitamente al final del código de cada caso.
Se utiliza for-in para iterar sobre los elementos de un diccionario, proporcionando un par de nombres a utilizar para cada par clave-valor. Los diccionarios son una colección desordenada, por lo que sus claves y valores se repiten a lo largo de un orden arbitrario.
Después de ejecutar el código dentro de la caja del interruptor que hacía juego, el programa sale de la sentencia switch. La ejecución no continúa al siguiente caso, lo que no hay necesidad de romper explícitamente al final del código de cada caso.
Se utiliza for-in para iterar sobre los elementos de un diccionario, proporcionando un par de nombres a utilizar para cada par clave-valor. Los diccionarios son una colección desordenada, por lo que sus claves y valores se repiten a lo largo de 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
}
}
}
print(largest)
Usaremos while para repetir un bloque de código hasta que una condición cambie. 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
}
print(n)
var m = 2
repeat {
m = m * 2
} while m < 100
while n < 100 {
n = n * 2
}
print(n)
var m = 2
repeat {
m = m * 2
} while m < 100
print(m)
Podemos mantener un índice en un bucle, ya sea mediante el uso .. <para hacer una serie de índices o escribiendo una inicialización explícita, condición, y el incremento. Estos dos bucles hacen lo mismo:
var firstForLoop = 0
for i in 0..<4 {
firstForLoop += i
}
print(firstForLoop)
var secondForLoop = 0
for var i = 0; i < 4; ++i {
secondForLoop += i
}
print(secondForLoop)
for i in 0..<4 {
firstForLoop += i
}
print(firstForLoop)
var secondForLoop = 0
for var i = 0; i < 4; ++i {
secondForLoop += i
}
print(secondForLoop)
Utilizamos ..< para hacer una gama que omite su valor superior, y utilizamos ... para hacer una gama que incluye ambos valores.
Funciones y cierres
Utilizaremos func para declarar una función. Para llamar a una función necesitaremos poner su nombre con una lista de argumentos entre paréntesis. Utilizaremos -> para separar los nombres de los parámetros y tipos de tipo de retorno de la función.
func greet(name: String, day: String) -> String {return "Hello \(name), today is \(day)."
}
greet("Bob", day: "Tuesday")
Utilizaremos una tupla para hacer un compuesto de valor, por ejemplo, para devolver varios valores de una función. Los elementos de una tupla pueden ser referidos por nombre o por número.
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])
print(statistics.sum)
print(statistics.2)
}
let statistics = calculateStatistics([5, 3, 100, 3, 9])
print(statistics.sum)
print(statistics.2)
Las funciones también pueden tomar un número variable de argumentos, 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)
Las funciones se pueden anidar. Funciones anidadas tienen acceso a las variables que fueron declaradas en la función externa. Puedes utilizar las funciones anidadas para organizar el código en una función 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 función puede devolver otra función como su valor.
func makeIncrementer() -> ((Int) -> Int) {
func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
var increment = makeIncrementer()
increment(7)
Una función puede tener otra función 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, condition: lessThanTen)
Las funciones son en realidad un caso especial de los cierres: bloques de código que se pueden llamar más tarde. El código 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 está en un ámbito diferente cuando se ejecuta, como vimos en un ejemplo de esto ya con funciones anidadas. Podemos escribir un cierre sin un nombre por el que rodea código con llaves ({}). El uso en separar los argumentos y el tipo de retorno del cuerpo.
numbers.map({
(number: Int) -> Int in
let result = 3 * number
return result
})
Tiene varias opciones para la escritura de los cierres más concisa. Cuando un tipo de cierre es ya conocida, como la devolución de llamada para un delegado, se puede omitir el tipo de sus parámetros, el tipo de retorno, o ambas cosas. cierres sola declaración implícita devuelven el valor de su única declaración.
let mappedNumbers = numbers.map({ number in 3 * number })
print(mappedNumbers)
Se puede hacer referencia a los parámetros por número en lugar de por su nombre, este enfoque es especialmente útil en los cierres muy cortos. Un cierre de la última pasada como argumento a una función puede aparecer inmediatamente después del paréntesis. Cuando el cierre es el único argumento a una función, se puede omitir el paréntesis en su totalidad.
let sortedNumbers = numbers.sort { $0 > $1 }
print(sortedNumbers)
Objetos y clases
Utilizaremos class seguido del nombre de la clase para crear una clase. Una declaración de propiedad en una clase se escribe de la misma manera que una declaración constante o variable, excepto que es en el contexto de una clase. Del mismo modo, el método y las declaraciones de función se escriben de la misma manera.
class Shape {
var numberOfSides = 0
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
var numberOfSides = 0
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
Crear una instancia de una clase, poniendo entre paréntesis después del nombre de la clase. Utilice la sintaxis con punto para acceder a las propiedades y métodos de la instancia.
var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()
Esta versión de la clase Shape le falta algo importante: un inicializador para establecer la clase cuando se crea una instancia. Utilizamos init para crear uno.
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 cómo self se utiliza para distinguir la propiedad del nombre, del nombre de argumento al inicializador. Los argumentos del inicializador se pasan como una llamada a la función cuando se crea una instancia de la clase. Cada propiedad necesita un valor asignado, ya sea en su declaración (al igual que con numberOfSides) o en el inicializador (al igual que con el nombre).
Utilice deinit para crear un deinitializer si es necesario realizar alguna tarea de limpieza antes de que se cancela la asignación del objeto.
Subclases incluyen su nombre de superclase del nombre de la clase, separados por dos puntos. No hay ningún requisito para las clases a la subclase cualquier clase raíz estándar, por lo que pueden incluir u omitir una superclase, según sea necesario.
Métodos en una subclase que tienen preferencia sobre la implementación de la superclase están marcados con override-overriding para evitar la sobreescritura de un método por accidente, es detectado por el compilador como un error si no lo ponemos. El compilador también detecta métodos con anulación que en realidad no anulan cualquier método en la superclase.
Utilice deinit para crear un deinitializer si es necesario realizar alguna tarea de limpieza antes de que se cancela la asignación del objeto.
Subclases incluyen su nombre de superclase del nombre de la clase, separados por dos puntos. No hay ningún requisito para las clases a la subclase cualquier clase raíz estándar, por lo que pueden incluir u omitir una superclase, según sea necesario.
Métodos en una subclase que tienen preferencia sobre la implementación de la superclase están marcados con override-overriding para evitar la sobreescritura de un método por accidente, es detectado por el compilador como un error si no lo ponemos. El compilador también detecta métodos con anulación que en realidad no anulan cualquier método 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 {
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()
Además de las propiedades simples que se almacenan, las propiedades pueden tener un getter y 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)."
}
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
print(triangle.perimeter)
triangle.perimeter = 9.9
print(triangle.sideLength)
return "An equilateral triangle with sides of length \(sideLength)."
}
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
print(triangle.perimeter)
triangle.perimeter = 9.9
print(triangle.sideLength)
En el setter para el perimeter, el nuevo valor tiene el nombre implicito newValue.
Podemos proporcionar un nombre explícito entre paréntesis después del set.
Observamos que el inicializador para la clase de triángulo equilátero tiene tres etapas diferentes:
Observamos que el inicializador para la clase de triángulo equilátero tiene tres etapas diferentes:
- Mediante la configuración de las propiedades que declara la subclase.
- Llamando a la inicializador superclase.
- Cambiar el valor de las propiedades definidas por la superclase. Cualquier otra configuración funciona pero utiliza métodos getters o setters, también se puede hacer en este momento.
Si no es necesario para calcular la propiedad, pero todavía tiene que proporcionar el código que se ejecuta antes y después de establecer un nuevo valor, utilice willSet y didSet. El código que proporciona es ejecutar en cualquier momento los cambios de valor fuera de un inicializador. Por ejemplo, la clase a continuación se asegura de que la longitud del lado de su triángulo 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")
print(triangleAndSquare.square.sideLength)
print(triangleAndSquare.triangle.sideLength)
triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
print(triangleAndSquare.triangle.sideLength)
Cuando se trabaja con valores opcionales, podemos escribir ? antes de las operaciones como los métodos, propiedades y subíndices. Si el valor antes de ? es nil, todo después de que el ? es ignorado y el valor de toda la expresión es nula. De lo contrario, el valor opcional se desenvuelve, y todo después de la ? actúa sobre el valor sin envolver. En ambos casos, el valor de toda la expresión es un valor opcional.
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength
Enumeraciones y estructuras
Utilice enum para crear una enumeración. Al igual que las clases y todos los otros tipos de nombres, las enumeraciones pueden tener métodos 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 { //this en Java
case .Ace:
return "ace"
case .Jack:
return "jack"
case .Queen:
return "queen"
case .King:
return "king"
default:
return String(self.rawValue)
}
}
}
let ace = Rank.Ace
let aceRawValue = ace.rawValue
En el ejemplo anterior, el tipo de valor de la enumeración es de tipo int, por lo que sólo tiene que especificar el primer valor. El resto de los valores se asignan en orden. También puede utilizar cadenas o números de punto flotante como el tipo de prima de una enumeración. Utilice la propiedad rawValue para acceder al valor de un caso de enumeración. Utilice el init? (RawValue :) inicializador para hacer una instancia de una enumeración de un valor en bruto.
if let convertedRank = Rank(rawValue: 3) {
let threeDescription = convertedRank.simpleDescription()
}
let threeDescription = convertedRank.simpleDescription()
}
Los valores del caso de una enumeración, son valores reales, no sólo otra manera de escribir sus valores. De hecho, en los casos donde no hay un valor significativo, no tenemos que proporcionar uno.
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
let heartsDescription = hearts.simpleDescription()
let heartsDescription = heart.simpleDescription()
Observemos las dos formas en que el caso de los corazones de la enumeración se hace referencia más arriba: Cuando se asigna un valor a las constantes hearts, los casos Suit.Hearts enumeración se refiere por su nombre completo debido a que la constante no tiene un tipo explícito especificado. En el interior del switch, el caso de enumeración es referido por los .Hearts forma abreviada debido a que el valor del self ya es conocido por ser un traje. Puede utilizar la forma abreviada en cualquier momento el tipo del valor que ya se conoce.
Utilice struct para crear una estructura. Las estructuras soportan muchas de las mismas conductas como las clases, incluyendo métodos y inicializadores. Una de las diferencias más importantes entre las estructuras y las clases de estructuras es que siempre se copian cuando se pasan alrededor de su código, pero las clases se pasan por referencia.
Utilice struct para crear una estructura. Las estructuras soportan muchas de las mismas conductas como las clases, incluyendo métodos y inicializadores. Una de las diferencias más importantes entre las estructuras y las clases de estructuras es que siempre se copian cuando se pasan alrededor de su código, 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()
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()
Un ejemplo de un caso de enumeración puede tener valores asociados a la instancia. Las instancias de la misma enumeración pueden tener diferentes valores asociados con ellos. Usted proporciona los valores asociados al crear la instancia. valores asociados y los valores brutos son diferentes: El valor bruto de un caso de enumeración es el mismo para todas sus instancias, y le proporcionará el valor bruto cuando se define la enumeración.
Por ejemplo, consideremos el caso de solicitar la hora de salida y puesta de sol desde un servidor. El servidor responde ya sea con la información o responde con información de error.
Por ejemplo, consideremos el caso de solicitar la hora de salida y puesta de sol desde un servidor. El servidor responde ya sea con la información o responde con información de error.
enum ServerResponse {
case Result(String, String)
case Error(String)
}
let success = ServerResponse.Result("6:00 am", "8:09 pm")
let failure = ServerResponse.Error("Out of cheese.")
switch success {
case let .Result(sunrise, sunset):
print("Sunrise is at \(sunrise) and sunset is at \(sunset).")
case let .Error(error):
print("Failure... \(error)")
}
Observe cómo se extraen las horas de salida y puesta del sol a partir del valor de respuesta del servidor como parte de la búsqueda de valor frente a los casos switch.
Protocolos y Extensiones
Utilizar el protocolo para declarar un protocolo.
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
}
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
}
Las clases, enumeraciones, estructuras y todos 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)"
}
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription
Observe el uso de la palabra clave mutating en la declaración de estructura simple para marcar un método que modifica la estructura. La declaración de clase simple no necesita ninguno de sus métodos marcados como mutando porque los métodos de una clase siempre pueden modificar a la clase.
Utilizar la extensión para agregar funcionalidad a un tipo existente, como los nuevos métodos y las propiedades calculadas. Se puede utilizar una extensión para añadir conformidad protocolo para un tipo que se declara en otro lugar, o incluso a un tipo que ha importado de una biblioteca o un framework.
extension Int: ExampleProtocol {
var simpleDescription: String {
return "The number \(self)"
}
mutating func adjust() {
self += 42
}
}
print(7.simpleDescription)
var simpleDescription: String {
return "The number \(self)"
}
mutating func adjust() {
self += 42
}
}
print(7.simpleDescription)
Se puede utilizar un nombre de protocolo al igual que cualquier otro tipo, por ejemplo el nombre, para crear una colección de objetos que tienen diferentes tipos, sino que todos ajustarse a un protocolo único. Cuando se trabaja con valores cuyo tipo es un tipo de protocolo, métodos fuera de la definición de protocolo no están disponibles.
let protocolValue: ExampleProtocol = a
print(protocolValue.simpleDescription)
// print(protocolValue.anotherProperty) // Uncomment to see the error
A pesar de que el valor de protocolo variable tiene un tipo de tiempo de ejecución de SimpleClass, el compilador lo trata como el tipo dado de ExampleProtocol. Esto significa que no se puede acceder accidentalmente a los métodos o propiedades que la clase implementa además de su cumplimiento del protocolo.
Genéricos
Escribe un nombre dentro de paréntesis angulares para realizar una función genérica o tipo.func repeatItem<Item>(item: Item, numberOfTimes: Int) -> [Item] {
var result = [Item]()
for _ in 0..<numberOfTimes {
result.append(item)
}
return result
}
repeatItem("knock", numberOfTimes:4)
Puedes hacer que las formas genéricas de funciones y métodos, así como las clases, enumeraciones y estructuras.
// Reimplement the Swift standard library's optional type
enum OptionalValue<Wrapped> {
case None
case Some(Wrapped)
}
var possibleInteger: OptionalValue<Int> = .None
possibleInteger = .Some(100)
Donde después de usar el nombre de tipo para especificar una lista de requisitos, por ejemplo, para implementar un protocolo, para requerir dos tipos que pueden ser el mismo, o para requerir una clase para tener una superclase particular.
func anyCommonElements <T: SequenceType, U: SequenceType where 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])
for lhsItem in lhs {
for rhsItem in rhs {
if lhsItem == rhsItem {
return true
}
}
}
return false
}
anyCommonElements([1, 2, 3], [3])
anyCommonElements([1,2,3,4,5,6],[3])
anyCommonElements([1,2,3,4,5,6],[7])
Es posible que necesitemos hacer:
import Foundation
para que funcione correctamente.
Más información:
Developer swift.
Ejercicios.
Soluciones propuestas apple.
Cap comentari :
Publica un comentari a l'entrada