imagen

Funciones en swift

Funciones

Función sin parámetros de entrada

func showMessage()->String{
  return "welcome"
}

showMessage()

Función que recibe una variable name de tipo string y retorna un string

func sayHello(name: String) -> String{
  let greet = "Hi \(name)"
  return greet
}

sayHello(name: "Jhon")

Función que recibe 2 parámetros Int y retorna otro Int

func plus(number1 : Int, number2: Int)->Int{
  let result = number1 + number2
  return result
}

plus( number1: 5 , number2: 7 )

Función sin valor de retorno

func hi(name: String){
  print("Hi \(name)")
}

hi(name: "Louis")

Función que retorna una tupla

func minMax(numeros:[Int])->(min: Int , max: Int){
  var currentMin = numeros[0]
  var currentMax = numeros[0]
  
  for value in numeros{
    if value < currentMin {
      currentMin = value
    }else if value > currentMax {
      currentMax = value
    }
    
  }
  
  return (currentMin, currentMax)
}

minMax(numeros: [5,2,6,8,6,2])

Misma función anterior, pero valida si es un array vació y el retorno de la tupla sera opcional (?)

func minMaxGood(numeros:[Int])->(min: Int , max: Int)?{
  
  // Si es vacio, retorna nil
  if( numeros.isEmpty){ return nil }
  
  var currentMin = numeros[0]
  var currentMax = numeros[0]
  
  for value in numeros{
    if value < currentMin {
      currentMin = value
    }else if value > currentMax {
      currentMax = value
    }
    
  }
  
  return (currentMin, currentMax)
}

minMaxGood(numeros: [])

Podemos definir etiquetas (alias) para 1 o mas parametros

func suma(n1 primerNumero : Int, n2 segundoNumero : Int){
  // internamente usaremos primerNumero y segundoNumero
  
}

// Asi, usaremos las etiquetas al llamar a la función
suma(n1: 5 , n2 : 10)

Podemos omitir una o mas etiquetas

func saluda(_ name : String, from ciudad : String){
  // use primerNumero and segundoNumero
}

saluda("Juan" , from: "Sidney")

Definir un parámetro por defecto

func saludaDeNuevo(_ name : String, from ciudad : String = "Santiago"){
  // use primerNumero and segundoNumero
  
}

// Puede pasar solo el primer parametro, y usara el segundo con su valor predefinido
saludaDeNuevo("Oliver")

// o puede pasar ambos parámetros
saludaDeNuevo("Heriberto", from: "Italy")

Recibir una cantidad de parámetros no determinados

func promedio(_ numbers: Int... )-> Double{
  var suma : Int = 0
  for number in numbers {
    suma += number
  }
  var promedio = Double(suma) / Double(numbers.count)
  return Double(promedio)
}

promedio(2,2,3)
promedio(2,2,3,3,4,5,6,7)

Modificar parámetros fuera de la función

var intentos = 0

func notificar(_ contador : inout Int){
  contador += 1
  // hacer cosas
}

notificar(&intentos)

Definir función como variable

func resta(_ n1 : Int , _ n2 : Int) -> Int {
  return n1-n2
}
var operacion : (Int, Int) -> Int = resta

operacion(5,7)

Funciones anidadas

func calculadora(_ operacion : String, _ n1 : Int , _ n2 : Int ) -> Int{
  var resultado = 0
  
  func suma()->Int{
    return n1+n2
  }
  
  func resta()->Int{
    return n1-n2
  }
  
  switch operacion {
    case "suma":
      resultado = suma()
    case "resta":
      resultado = resta()
    default:
      break;
  }
  
  return resultado
}

calculadora("suma", 1, 2)
calculadora("resta", 14, 1)
Closures

En palabras simples, un closure es una función anónima ( una función sin nombre ) que sera pasada como parámetro a otra función. Su sintaxis es algo así:

 { (params) -> return type in
    //Código del closure
 }
 

Un ejemplo pasando un closure al método sorted de un array

// Opción 1
letrasReversas = letras.sorted(by: { (s1: String, s2: String) -> Bool in return s1>s2 })

// Opción 2
letrasReversas = letras.sorted(by: { s1, s2 in return s1>s2 })

// Opción 3
letrasReversas = letras.sorted(by: { s1, s2 in s1>s2 })

// Opción 4
letrasReversas = letras.sorted(by: { $0>$1 })

// Opción 5
letrasReversas = letras.sorted(by: >)

// Todas generan el mismo resultado, lo podemos imprimir, asi:
print(letrasReversas)

Ejemplo de closure en una función normal

// Definimos la función
func tarea1(closure: () -> Void){

  // Aquí irían las instrucciones de tarea 1
  print("instruccion 1 de la funcion tarea 1")
  print("instruccion 2 de la funcion tarea 1")
  
  // Llamamos al closure
  closure()
}

// Llamando a la función y pasandole el closure como parámetro (sintaxis completa)
tarea1(closure: {
  //Aquí iria el cuerpo del closure
  print("instruccion en el closure")
})

// Llamando a la función y pasandole el closure como parámetro (sintaxis simplificada)
tarea1 {
    //Añadir el closure aquí
  print("instruccion en el closure")
}

Escapando un closure

// Variable en la que almacenaremos el closure
var closureAlmacenado : ()->Void = {};

// Definimos nuestra función
func tarea2 (closureRecibido: @escaping ()->Void){
  print("instruccion 1 de la funcion tarea 2")
  print("instruccion 2 de la funcion tarea 2")

  // No ejecuta el closure, lo almacena en una variable de un scope superior
  closureAlmacenado = closureRecibido
}

// Llamamos a nuestra función y le pasamos el closure
tarea2 {
  print("Instrucción en closure async")
}

// Ejecutamos nuestro closure almacenado
closureAlmacenado()
Enumerados

Definir un enumerado

enum miEnumerado{
  // Define los valores posibles
}
enum sexo{
  case femenino
  case masculino
  case indeterminado
}

print(sexo.femenino)
// femenino

Ejemplo de uso de un enumerado

// Definimos el enumerado y sus casos
enum Barcode{
  case upc(Int, Int, Int, Int)
  case qrCode(String)
}

// Podemos definir el codigo de un item de tipo barcode respetando la estructura
var itemACode = Barcode.upc(8, 2346, 2365, 8)
print(itemACode)
// upc(8, 2346, 2365, 8)

// Podemos definir el código de un item de tipo qrCode respetando la estructura
var itemBCode = Barcode.qrCode("hgasjdgasj")
print(itemBCode)
//qrCode("hgasjdgasj")



// Respondemos según el tipo de código
switch itemACode {
  case let .upc(n1 , n2, n3, n4):
    print("Es UPC :\(n1) \(n2) \(n3) \(n4)")
    // Es UPC :5 6534 62525 33
  case let .qrCode(qrString):
    print("Es QR: \(qrString)")
    // Es QR: hgasjdgasj
  
}

Trabajando con rawValues

/**
 Podemos asignar valores de referencia (rawValue) a cada caso
 asignamos a mercury 2
 y venus asume 3, y earth 4, respectivamente
 */
enum Planets: Int{
  case mercury = 2
  case venus
  case earth
}

/**
 Podemos consultar que rawValue tiene un caso
 */
print(Planets.earth.rawValue)

/**
Podemos consultar que valor tiene un rawValue
*/
if let planetOne = Planets(rawValue: 2){
  print(planetOne)
}