Categories
Swift Development

100 Dias de Swift Día 6

Día 6

Estas son mis notas para el curso de Swift https://www.hackingwithswift.com

Entrada anterior

“you can’t expect to hit the jackpot if you don’t put a few nickels in the machine.”

Flip Wilson’s law

«No esperes darle al premio gordo, sin antes poner un par de monedas en la maquina»

Flip Wilson’s law

Closures, part one

Este tema es la principal razón por la que decidí volver a a retomar las lecciones básicas de Swift este tema se me había complicado bastante y no lo entendí al 100% la primera vez

Creating basic closures

Swift nos deja crear funciones como si fueran cualquier otro tipo de dato como Strings o Int, asignarla a una variable e incluso pasar esta función a otra función como parámetro.

Comencemos un simple ejemplo

let manejar = {
    print("Estoy manejando un auto")
}

Esto crea una función sin nombre que ahora podemos llamar a esa función con el nombre de la constante que creamos

manejar()

Accepting parameters in a closure

Aceptar parámetros en un «closure» es posible pero de forma un poco diferente al de una función , los parámetros se listan dentro de las llaves, dentro de paréntesis y seguidos de la palabra reservada «in»

let manejar = { (destino: String) in 
    print("Estoy manejando a \(destino) en un auto")
}

Una de las diferencias entre closures y functions es que closures no necesitan etiquetas para los parámetros

Returning values from a closure

Closures también pueden regresar valores, de manera similar a los parámetros, solo debemos indicarlos antes del «in» y usar «return» como en una función normal

 let manejar = { (destino: String) -> String in
     return "Estoy manejando a \(destino) en un auto"
 }
 
let mensaje = manejar("Pachuca")
print(mensaje)

Closures as parameters

Los closures pueden ser usados como parámetros dentro de una función, pero la sintaxis puede ser complicada

let manejar = {
    print("Estoy manejando un auto")
}

Si queremos pasar ese closure en una función debemos especificar el parámetro como «( ) -> Void». Eso significa que que no acepta parámetros y no regresa nada.

 let manejar = {
     print("Estoy manejando en un auto")
 }
 
 func viajar(acción: () -> Void) {
     print("Estoy listo para partir.")
     acción()
     print("¡Ya llegue!")
 }

 viajar(acción: manejar)

Trailing closure syntax

Si el ultimo parámetro de tu función es un closures Swift te permite pasarlo de manera especial esto es llamado trailing closure syntax. En lugar de pasar tu closure como un parámetro, lo pasas directo después de la función entre llaves.

 func viajar(acción: () -> Void) {
     print("Estoy listo para partir.")
     acción()
     print("¡Ya llegue!")
 }
 
 viajar(){
    print("Estoy viajando en un Barco")
 }

De hecho como esta función no tiene ningún parámetro podemos omitir los paréntesis

 viajar{
    print("Estoy viajando en un Avión")
 }

// Aquí termina la parte 1 mañana continuare la parte 2 y  hare el resumen de ambas 

Referencias

https://www.hackingwithswift.com/100

https://www.hackingwithswift.com/100/6

Proximo día

Categories
Swift Development

100 Dias de Swift Día 5

Día 5

Estas son mis notas para el curso de Swift https://www.hackingwithswift.com

Entrada anterior

“Dennis Ritchie (the creator of the C programming language) encouraged modularity by telling all and sundry that function calls were really, really cheap in C. Everybody started writing small functions and modularizing. Years later we found out that function calls were still expensive, and our code was often spending 50% of its time just calling them. Dennis had lied to us! But it was too late; we were all hooked…”

Steve Johnson

“Dennis Ritchie (el creador del lenguaje de programación C) alentó la modularidad diciendo a todos que cada una de las llamadas a funciones eran realmente muy rápidas en C. Todos comenzaron a escribir pequeñas funciones y modularizar. Años después descubrimos que las llamadas a funciones seguían siendo lentas, y nuestro código a menudo pasaba el 50% de su tiempo simplemente haciendo las llamadas. ¡Dennis nos había mentido! Pero era demasiado tarde; todos estábamos enganchados … “

Steve Johnson

Esta cita es de tiempos mas oscuros cuando las llamadas a funciones eran algo lento

Writing functions

Las funciones nos permiten reciclar código y usarlo en varios lugares después, repertir código es normalmente una mala idea.

Para crear una función usamos la palabra reservada «func» luego el nombre de tu función, luego abrimos y cerramos paréntesis como en el siguiente ejemplo.

func bienvenida() {
 let mensaje = "Bienvenido a mi App"
 print(mensaje)
}

ahora podemos correr este código solo usando «bienvenida()»

bienvenida()

Correr el código de una función también se conoce como Llamar a una función

Accepting parameters

Las funcione se vuelven mas poderosas cuando permitimos que acepten parámetros para hacer esto solo debemos especificar entre paréntesis el nombre del parámetro y el tipo de dato.

func bienvenida(nombre: String) {
 let mensaje = "Bienvenido \(nombre) a mi App"
 print(mensaje)
}

bienvenida(nombre: "Misael")
bienvenida(nombre: "Juan")

Este código puede imprimir un mensaje de saludo personalizado para cada usuario

Otro ejemplo para sumar números

func suma(numeroA: Int , NumeroB: Int){
    let suma = numeroA + NumeroB
    print(suma)
}

suma(numeroA: 4, NumeroB: 5)
suma(numeroA: 12, NumeroB: 10)

Returning values

Regresar valores

Así como podemos proporcionar parámetros podemos devolver valores para hacer esto usamos « ->» y ademas el tipo de dato, para devolver el valor usamos «return»

func suma(numeroA: Int , NumeroB: Int) -> Int{
     let suma = numeroA + NumeroB
     return suma
     // ningún código sera ejecutado después del return
 }

Ahora podemos usar el valor que nos regresa la función para algo mas

let resultadoDeLaSuma = suma(numeroA: 4, NumeroB: 12)
print("El resultado de la suma es \(resultadoDeLaSuma)")

Parameter labels

Etiquetas para los parámetros

Podemos usar las etiquetas de los parámetros para hacer mas legible nuestro código, para eso solo suministramos dos nombres separados por un espacio. El primero se usa fuera de la función y el otro de manera externa.

 func bienvenida(a nombre: String) {
  let mensaje = "Bienvenido \(nombre) a mi App"
  print(mensaje)
 }

bienvenida(a: "Misael")

Omitting parameter labels

Ahora habrás notado que funciones como «print(“Hello”)» no tienen una etiqueta en el parámetro, en ciertas ocasiones es también mas legible omitir el nombre del parámetro por ejemplo

 func saludarA(_ nombre: String) {
  let mensaje = "Bienvenido \(nombre) a mi App"
  print(mensaje)
 }

saludarA("Misael")
saludarA("Juan")

Esto puede hacer mas legible nuestro código, pero también podría hacerlo mas confuso por ejemplo

ponerAlarma(5)

Este código es bastante confuso ¿La alarma es para las 5am o 5pm o es para dentro de 5 minutos u horas o días?

Así que piensa con cuidado como hacer tu código mas legible

Default parameters

Podemos suministrar valores por default para nuestras funciones solo agregando «=» después del tipo de dato

func saludarA(_ nombre: String, amablemente: Bool = true) {
    var mensaje = ""
    if amablemente == true {
        mensaje = "Bienvenido \(nombre) a mi App"
    } else {
        mensaje = "¡Oh no, es \(nombre) de nuevo 🤢!"
    }
    
  print(mensaje)
 }

saludarA("Misael")
saludarA("Juan", amablemente: false)

Como ves podemos llamar a esta función de dos maneras diferentes

Variadic functions

Algunas funciones pueden usar varios parámetros del mismo tipo, para eso solo añadimos «…» después del tipo de dato, swift creara un Array con los valores que suministremos

func calcularCuadrados(numeros: Int...) {
    for numero in numeros {
        print("\(numero) al cuadrado es \(numero * numero)")
    }
}

calcularCuadrados(numeros: 1,2,3,4,5,6,7,8,9,10)

Writing throwing functions

Cuando se suministra un dato erróneo a una función esta puede fallar, swift nos deja «tirar» errores cuando algo sale mal, usando la palabra reservada «throw»

Para empezar debemos crear un enum con los tipos de error

enum errorDeContraseña: Error {
    case muyObvia
}
func revisarContraseña(_ contraseña: String) throws -> Bool {
    if contraseña == "contraseña" {
        throw errorDeContraseña.muyObvia
    }

    return true
}
Sin embargo podemos ver que usar la función de esta forma nos muestra una alerta

y así podemos saber exactamente en que fallo nuestra función

Running throwing functions

Ahora bien a Swift no le gusta tener errores cuando llamamos a una función así que necesitamos llamarla de manera segura, para hacer esto usamos las palabras reservadas «do» para iniciar un código que podría causar problemas, «try» frente a la función que puede causar problemas, y «catch» para manejar el error de manera mas elegante

 do {
     try revisarContraseña("contraseña")
     print("¡Buena contraseña!")
 } catch {
     print("¿Enserio 😐?")
 }
Ahora todo funciona fluido

Inout parameters

Los parámetros de una función son constantes, si queremos que nuestros parámetros cambien el valor suministrado en lugar de regresar uno nuevo debemos usar «inout» antes del tipo de dato y ademas «&» antes de el nombre de tu variable, que por cierto no puedes usar constates pues tu valor sera cambiado

 func dobleOnada(numero: inout Int) {
     numero *= 2
 }
 
 var miNumero = 10
 dobleOnada(numero: &miNumero)
 
 print(miNumero)
como puedes ver esta función cambia efectivamente el valor de tu variable

Resumen

Las funciones nos permiten reutilizar código

Las funciones aceptan parámetros solo especia a Swift que tipo de parámetros son

Las funciones pueden regresaros valores, solo especifica que tipo de valor deseas recibir

Puedes usar diferentes etiquetas para los parámetros u omitir sus nombres para hacer mas legible tu código

Los parámetros pueden tener valores por default lo cual es util para escribir menos código que tiende a repetirse

Podemos usar parámetros que usen cero o mas valores y Swift los convertirá en un Array

Las funciones pueden arrojar errores (throw errors) pero debemos usarlas con try y catch

Podemos usar inout para cambiar variables dentro de una función, aunque lo mejor es devolver una valor nuevo.

// y bueno eso fue el resumen de funciones, la verdad es que hay algunos temas muy simples como arrojar errores que son muy útiles 

Referencias

https://www.hackingwithswift.com/100

https://www.hackingwithswift.com/100/5

Proximo Día

Categories
Swift Development

100 Dias de Swift Día 4

Día 4

Estas son mis notas del curso hackingwithswift

Entrada anterior

“it’s hardware that makes a machine fast, but it’s software that makes a fast machine slow.”

Craig Bruce

«Es el hardware lo que hace rápida a una maquina, pero el software es lo que la hace lenta.»

Craig Bruce

Loops

Los loops adoptan varias formas pero su mecánica es la misma, un código que se repite hasta que una condición se vuelva falsa

For

El loop mas comun es «For», que itera sobre Arrays y Ranges, cada iteración nueva asigna un elemento a una constante. Por ejemplo en el siguiente Range

let contar = 1...10
for numero in contar {
    print("el numero es \(numero)")
}

super simple verdad, lo mismo con los Arrays

let albums = ["Red", "1989", "Reputation"]

for album in albums {
    print("\(album) esta en Apple Music")
}

Si no necesitas crear ninguna constante puedes hacer el loop de esta manera

for _ in 1...5 {
    print("Hoy no se fia, mañana si")
}

While

«While» es también un loop muy usado, básicamente ejecuta una acción si se cumple la condición

var numero = 1

while numero <= 10 {
    print(numero)
    numero += 1
}

print("Listos o no, allá voy!")

Repeat

Es similar a While solo que la condición va al final esto quiere decir que el código se ejecuta primero y luego verifica la condición

var numero = 1

repeat {
    print(numero)
    numero += 1
} while number <= 20

print("Listos o no, allá voy!")

La mayor diferencia como puedes ver es que el código con «repeat» se ejecutara por lo menos una vez

while false {
//Este código nunca se ejecuta
    print("Esto es falso")
}

repeat {
//Este código se ejecutara una vez
    print("Esto es falso")
} while false

Break

Si quieres salir de un bucle puedes usar «break»

var numero = 1

repeat {
    print(numero)
    if numero == 10 {
      print("Ya me aburrí, Listos o no, allá voy!")
      break
    }
    numero += 1

} while number <= 20

print("Listos o no, allá voy!")

Si tienes loops anidados y quieres salir de ambos puedes usar «break (etiqueta de tu loop principal)»

etiquetaLoopPadre: for i in 1...10 {
    for j in 1...10 {
        let resultado = i * j
        print ("\(i) * \(j) es igual a \(resultado)")

        if resultado == 50 {
            print("Eso es todo")
            break etiquetaLoopPadre
        }
    }
}

Continue

Así como podemos salir de un loop podemos omitir ciertos elementos usando «continue» por ejemplo en el siguiente ejemplo solo imprimimos números pares

for i in 1...10 {
    if i % 2 == 1 {
    //omitir si es primo
        continue
    }

    print(i)
}

Loops infinitos

Los loop infinitos son algo muy común en iOS básicamente son loops que se ejecutan de manera indeterminada, pero ten cuidado recuerda establecer una salida para tu bucle si no se repetirá para siempre.

Lo mas común es poner una condición verdadera en un While

var contador = 0

while true {
    print(" ")
    contador += 1

    if contador == 273 {
        break
    }
}

Resumen

Los loops se repiten hasta que una condición es falsa

Los loops mas comunes son For y While

Puedes omitir usar la constate de For si no la necesitas

Puedes usar Repeat en lugar de While si quieres que tu código se ejecute por lo menos una vez

Para salir de un bucle usa break y para omitir un elemento continue

y por ultimo los loops infinitos necesitan que les suministres una salida para

//y bueno esos son los loops 

Referencias

https://www.hackingwithswift.com/100/4

https://www.hackingwithswift.com/100

Proximo Día

Categories
Swift Development

100 Dias de Swift Día 3

Día 3

Estas son mis notas del curso hackingwithswift

Entrada Anterior

“Computers are like Old Testament gods: lots of rules and no mercy.”

Joseph Campbell

“Las computadoras son como el Antiguo Testamento : Un montón de reglas y sin misericordia .”

Joseph Campbell

Operators and conditions

Operadores y condiciones

Los operadores nos permiten combinar diferentes tipos de datos, los operadores son símbolos matemáticos, como «+» y «-», en Swift hay muchos de estos.

Empecemos con dos variables de ejemplos

let primerPuntaje = 12
let segundoPuntaje = 8

Podemos sumar y restar de esta forma

let total = primerPuntaje + segundoPuntaje
let diferencia = primerPuntaje - segundoPuntaje

y podemos dividir y multiplicar usando «*» y «/» :

let producto = primerPuntaje * segundoPuntaje
let división = primerPuntaje / segundoPuntaje

Swift tiene un operador especial para calcular el residuo de una operación, calcula cuántas veces un numero cabe en otro, entonces regresa el valor que queda.

let residuo = 25 % segundoPuntaje
El resultado es 1

Operator overloading

Operator overloading es una forma sofisticada de decir que lo que el operador hace depende del valor con el que lo usemos aquí un ejemplo + puede sumar números

let sentidoDeLaVidaElUniversoYTodoLoDemás = 42
let elDobleSentidoDeLaVidaElUniversoYTodoLoDemás = 42 + 42

//disculpa la fuerte referencia a The Hitchhiker's Guide to the Galaxy, de Douglas Adams así venia en el curso 😅

Pero también puede unir cadenas de texto

let celos = "Estos celos me hacen "
let acción =  celos + "Daño"

Incluso podemos unir Arrays

let primeraMitad = ["Jorge", "Hernán"]
let segundaMitad = ["Eduardo", "Luis", "Óscar"]

let 🐯Norte =  primeraMitad + segundaMitad

Recuerda que Swift no permite mezclar diferentes tipos de datos así que no trates de sumar un String y un Int

Compound assignment operators

Swift permite combinar los operadores con un cambio de valor, de esta forma podemos reasignar valores en un solo paso, usando los operados que ya conocemos «+,-,*,/» pero con «=» al final

Por ejemplo

var puntaje = 95
puntaje -= 5

De forma similar podemos combinar dos Strings en un paso

var refrán = "Camarón que se duerme"
refrán += " se lo lleva la corriente"

Comparison operators

Estos operadores funciona mas o menos como en matemáticas

let primerPuntaje = 6
let segundoPuntaje = 4

hay dos operadores para revisar igualdad:

« == » revisa que dos valores sean iguales y « != » que se pronuncia no iguales y revisa que dos valores no sean el mismo

primerPuntaje == segundoPuntaje
primerPuntaje != segundoPuntaje

Hay cuatro operadores para comparar valores como en matemáticas

« > » mayor que

« < » menor que

« >= » mayor o igual que

« <= » menor o igual que

primerPuntaje >= segundoPuntaje
primerPuntaje <= segundoPuntaje

Ademas estos funciona con Strings también, ya que las Strings tienen un orden alfabético natural

"Taylor" <= "Swift"

Conditions

Condiciones ahora que conocemos los operadores podemos usar declaraciones condicionales con « if »

Para demostrar esto usaremos una de las funciones de Swift llamada « print( )» que nos sirve para mostrar texto

Por ejemplo podemos usar una condición cuando se llega al puntaje mas alto para imprimir un mensaje de victoria

let primerPuntaje = 30
let segundoPuntaje = 70

if primerPuntaje + segundoPuntaje == 100 {
 print("Ganaste 🥳")
}

El código entre las llaves « { } » se ejecutara cuando la condición sea cierta, y puedes ademas proveer una alternativa si la condición retorna falso usando « else »

if primerPuntaje + segundoPuntaje == 100 {
 print("Ganaste 🥳")
} else {
 print("Sigue intentando")
}

Puedes ademas proveer mas condiciones usando « else if»

if primerPuntaje + segundoPuntaje == 100 {
 print("Ganaste 🥳")
} else if primerPuntaje + segundoPuntaje == 50 {
 print("Bien vas a la mitad sigue intentando")
}else {
 print("Sigue intentando")
}

Combining conditions

Swift tiene tiene dos operadores para combinar operadores estos son « && » (pronunciado «y») y « || » (pronunciado « o » )

Por ejemplo

let edad1 = 16
let edad2 = 21
if edad1 > 18 && edad2 > 18 {
 print("Ambos son mayores de edad")
}

En esta caso Swift no ejecutara el código pues la primera condición no es verdadera de hecho ni siquiera revisara la segunda pues la primera es falsa

Por otro lado el operador « Or » evaluara las segunda condición incluso si la primera no es verdadera

if edad1 > 18 || edad2 > 18 {
 print("Al menos uno es mayor de edad")
}

Aunque se pueden usar mas de un && y || en una condición lo mejor es mantener las cosas simples para facilitar la lectura

The ternary operator

Operadores terciarios

Existe un operador muy poco usado llamado operador terciario « : »

//Bueno el curso decía eso pero yo lo uso mucho en SwiftUI 

Aqui un ejemplo

print(edad1 > 18 && edad2 > 18 ? "Ambos son mayores de edad" : "Alguno de ellos no lo es")

Switch statements

Si tienes muchas condiciones if y else es mejor usar otra estructura llamada « switch case » veamos el siguiente ejemplo

let clima = "soleado"

Se puede usar switch en un bloque para para imprimir diferentes mensajes

switch clima {
case "lluvia":
    print("Lleva un paraguas")
case "nieve":
    print("Usa un abrigo ")
case "soleado":
    print("Usa protector solar")
default:
    print("¡Disfruta tu día!")
}

En el ultimo ejemplo « default » es requiero por Swift para asegurarnos que se cubran todos los posibles casos

Swift solo correrá el código dentro de cada caso si quieres que Swift pase al siguiente caso usa « fallthrough »

switch clima {
case "lluvia":
    print("Lleva un paraguas")
case "nieve":
    print("Usa un abrigo ")
case "soleado":
    print("Usa protector solar")
    fallthrough
default:
    print("¡Disfruta tu día!") 
}

Range operators

Swift nos ofrece dos maneras de hacer rangos « ranges » para eso tenemos los operados « ..< » y « … » el primer crear un rango de valores excluyendo el ultimo valor, el segundo crear un rango de valores que incluye el ultimo valor

Por ejemplo

let rango = 1..<5
//contiene los números 1,2,3 y 4

let rango2 = 1...5
//contiene los valores 1,2,3,4 y 5

Los rangos pueden ser usados en un switch

let puntaje = 85

switch puntaje {
case 0..<50:
    print("fallaste")
case 50..<85:
    print("lo hiciste bien")
default:
    print("¡Lo hiciste genial!")
}

Resumen

Los operados en swift sirven para hacer operaciones aritméticas +,-,*,/

Hay operadores que sirven para modificar tus variables en un paso como += y -=

Puedes usar if, else y else if para correr código en base a una condición

Swift tiene un operador terciario que si bien no es muy conveniente usarlo en bloques de código de Swift es mejor usarlo solo en SwiftUI

Si tenemos varias condiciones es mejor usar una estructura switch

Podemos crea rangos usando ..< y … dependiendo de cual usemos el ultimo numero podría excluirse

//y bueno ese fue le día 3

Referencias

https://www.hackingwithswift.com/100/3

https://www.hackingwithswift.com/100

Proximo Día

Categories
Swift Development

100 Dias de Swift Día 2

Día 2

Estas son mis notas del curso del curso hackingwithswift

Entrada Anterior

“when the going gets tough, everyone leaves.”

Lynch’s Law

«Cuando las cosas se ponen difíciles, todos se van.»

Lynch’s Law 

Arrays

Matrizes

Los Arrays son una colección de valores que se guardan como si fueran uno.

Por ejemplo la Liga de la Justicia

let batman = "Bruno Días"
let superMan = "Clark Ken"
let wonderWoman = " Diana Prince"

let ligaDeLaJusticia = [batman, superMan, wonderWoman]

Un Array inicia y termina con corchetes « [ ]» , los elementos deben estar separados por comas, y para poder leer los elementos dentro del Array usamos el numero de elemento, comenzando la cuenta desde el cero, por ejemplo para acceder al primer elemento seria así

//Acceder a batman
ligaDeLaJusticia[0]

Si tratas de un leer un valor que no existe en el array por ejemplo ligaDeLaJusticia[3] Swift fallara

Si estas usando type annotations se especifican dentro de los corchetes por ejemplo

let númerosEnteros = [Int]
let númerosDecimales = [Double]
let nombres = [String]

Sets

Colecciones

Los Sets son colecciones de de valores igual que los Arrays. pero con dos diferencias, 1) los elementos no se guardan en ningún orden y 2) ningún elemento se puede repetir

Puedes crear un Set a partír de un Array así:

let colores = Set(["rojo","Azul", "Amarillo"])

Estos valores no se guardan en nigua orden y no puedes acceder a ellos como en un Array, y si tratas de agregar un valor duplicado este se ignorara

Tuples

Tuplas

Las Tuplas permiten guardar varios valores en forma de uno solo, son diferentes de los array en tres cosas 1) no puedes añadir o remover elementos, 2) no puedes cambiar el tipo de dato de los elementos dentro de ella, 3) puedes acceder a los elementos en su interior usando su posición numérica o el nombre, pero swift no te dejara leer números o nombres que no existen.

Ejemplo

var name = (first: "Taylor", last: "Swift")

Luego acceder a los valores por nombre o numero

//accedemos al mismo valor de dos formas diferentes 
name.0
name.first

finalmente recuerda que puedes cambiar los valores dentro pero no su tipo de dato.

Arrays vs Sets vs Tuples

Si bien estos valores podrían parecer iguales tienen distintos usos

Para una colección de valores fijos donde cada elemento tiene una posición o valor único, usamos una Tupla («Tuple»)

Para un colección de valores que debe ser único o donde necesitas revisar rápido que el valor exista, usa un Colección («Set»)

y si necesitas una colección de valores que contenga valors duplicados y el orden importa debería usar una Matriz («Array»)

//Spoiler la mayoría de las veces sera un Array

Dictionaries

Los diccionarios son colecciones de datos igual que las matrices, pero a diferencia de las matrices en lugar de acceder a ellas por medio de su posición numérica, puedes acceder a ellas usando lo que quieras

Por ejemplo podemos usar un String para acceder a las profesiones de un grupo de amigos

var ocupaciones = [ 
    "Misael" : "Programador", 
    "Armando": "Sistemas", 
] 
 
ocupaciones["Armando"] = "Soporte Tecnico" 
 
print(ocupaciones["Armando"]) 

Cuando usamos type anotations podemos declarar el tipo usando dos puntos para separar, por ejemplo:

var diccionarioVacio = [String:Float]() 

Dictionary default values

Valores por defecto para diccionarios

Si tratamos de acceder a un valor que no existe Swift nos regresara un valor «nil» o nulo; nada en absoluto

Pero podemos usar un valor por defecto o «default»

var ocupaciones = [ 
    "Misael" : "Programador", 
    "Armando": "Sistemas", 
] 
  
//esta devuelve nil 
print(ocupaciones["Luis"]) 

//esta devuelve un valor por default

print(ocupaciones["Luis"], default: "Desconocido") 

Creando Colecciones vacías

Para crear una matriz vacía o un diccionario, usamos la sintaxis de iniciación  

let arregloVacio = [String]() 
 
let diccionarioVacio = [String:Float]() 

Si el tipo de información puede ser inferida, se puede escribir de manera simplificada 

var arregloVacio = [String]() 
 
var diccionarioVacio = [String:Float]() 
 
    arregloVacio = [] 
 
    diccionarioVacio = [:] 

Esto es útil cuando queremos cambiar el valor o pasar un valor a una función.  

Enums 

Numeraciones

Sirven para agrupar valores relacionados de forma que son mas fáciles de usar por ejemplo

En lugar de tener :

let resultado = "Fallo"
let resultado2 = "Falla"
let resultado3 = "Fallido"

Esto genera diferentes valores que podrían tener diferentes significados así que los Enums nos ayudan a tener todo mas organizado por ejemplo

enum Resultado {
    case éxito
    case error
}

let resultado = Resultado.error

Con eso evitamos usar diferentes tipos cada vez y nuestro código gana coherencia por lo que es mas fácil de leer y mantener

Valores Asociados a los Enums

Ademas de simplemente guardar valores los Enums pueden tener valores asociados por ejemplo si tenemos un Enum con varias actividades

enum Actividades {
    case aburrido
    case corriendo
    case conversando
    case cantando 
}

Imaginemos ahora que queremos especificar de que estamos hablando

enum Actividades {
    case aburrido
    case corriendo(destino: String)
    case conversando(tema: String)
    case cantando(volumen: Int)
}

let hablando = Actividades.hablando(tema: "Star Wars")

Resumen

«Arrays» ,«Sets» , «Tuples», y «Dictionaries» te permiten guardar grupos de elementos bajo un solo valor, de formas diferentes.

Los Arrays guardan valores en el orden que tu dispongas, se pueden repetir y acceder a ellos por su posición numérica

Los Sets guarda elementos sin ningún orden y no puedes acceder a ellos por su posición numérica

Las Tuples tienen un tamaño fijo, puedes añadir nombres a cada elemento, puedes leer elementos usando posiciones numéricas o los nombres.

Los Dictionaries guardan elementos de acuerdo a sus llaves y puedes leerlos de nuevo usando sus llaves

Los Enums son una forma de agrupar valores relacionados para que no te equivoques al escribirlos, por ejemplo para tipos de errores, adicionalmente puedes relacionarlos con otros valores.

//y bien ese fue el día 2, la verdad casi siempre se usan Arrays y Dictionaries es muy raro que se usen otros a excepción de los Enums que son muy utiles para hacer tu codigo mas legible

Referencias

Todas estas notas están basadas en el curso de hackingwithswift el cual te recomiendo tomar directo en su sitio web

Aqui los enlaces

https://www.hackingwithswift.com/100

https://www.hackingwithswift.com/100/2

Proximo Día

Categories
Swift Development

100 Dias de Swift Día 1

Día 1

Después de termina 100daysOfSwiftUI tenia dudas sobre que seguir aprendiendo para mejorar mis habilidades como desarrollador y encontrar un trabajo.

Si bien creo firmemente que SwiftUI es el futuro y lo usare al 100% para mis apps personales y trabajos freelancer, sin duda UIKIT va a estar por aquí un largo rato así que decidí tomar a 100daysOfSwift classic para aprender UIKIT y esta vez ire documentado todo en mi blog personal para tener una referencia en español para mi, espero esto sea de ayuda para quienes se aventuren en este interesante reto.

“the secret to getting ahead is getting started.” 

Mark Twain

«El secreto para avanzar es iniciar»

Mark Twain

Bien para comenzar Abrimos Xcode y creamos un nuevo playground

Variables

Las variables son espacios donde podemos guardar datos, declarar una variable es tan fácilmente como esto;

var saludo = "Hola 🖖🏼"

Algo genial de el ecosistema apple es que podemos usar emojis en todas partes

Ahora como esto es una variable podemos cambiar su valor tan fácilmente como esto;

saludo = "Adios ✌🏼"

No es necesario volver a escribir «var» otra vez por que la variable ya fue creada y ahora solo estamos cambiando su valor

Strings and integers

Cadenas de texto y Números Enteros

Swift es un lenguaje «type-safe» o de escritura segura, eso significa que cada variable debe tener un tipo de dato especifico

En nuestra variable saludo, escribimos un texto por tanto era un variable de tipo «String»

Ahora si queremos escribir la edad de alguien lo hacemos de la siguiente manera

var edad = 24

Eso contiene un numero entero, así que swift le asigna el tipo «Int» un tipo de valor entero.

si queremos escribir números grandes de manera mas legible podemos hacerlo de la siguiente manera

var población = 8_000_000

Strings y Int son diferentes tipos de datos y no se deben mezclar, así pues si bien pudimos asignar un nuevo valor a saludo como «Adios» no podemos asignarle un valor de un tipo diferente como «24».

Multi-line strings

Cadenas de texto multi linea, como ya vimos para crear una variable de tipo String usamos comillas dobles «”» pero para una cadena de texto con multiples lineas debemos usar tres comillas dobles de la siguiente manera:

var texto = """
Este texto
tiene 
multiples 
lineas
"""

Swift espera que las comillas tanto iniciales como finales vayan en su propia linea

Ahora si lo que quieres es simplemente dar formato a tu código para hacerlo mas legible pero no quieres los saltos de linea realmente en tu texto solo tienes que añadir una «\» al final

var texto = """
Este texto \
no tiene \
multiples \
lineas
"""
¿Genial no?

Doubles and booleans

Números con punto decimal y valores verdadero / falso

cada vez que creamos una variable con punto decimal swift nos asigna el tipo Double por ejemplo:

var pi = 3.1416

Double es un tipo diferente de Int y no pueden ser mezclados

Los Booleanos son mucho mas simples son simplemente valores que pueden ser Verdaderos o Falsos (true / false )

Por ejemplo

var ellaTeAma = false
//Lo gracioso es que es verdad 😹
//💔😢

String interpolation

Incrustando variables en texto

Ahora vemos como incrustar variables directo a texto, para hacer es bátanme simple solo usamos «\» seguido de tu variable entre paréntesis «( )»

Por ejemplo

var tuPuntaje = 95
var texto = "Tu puntaje fue \(tuPuntaje)"

como ves es bástate sencillo y lo puedes hacer a veces que quieras

var resultados = "Los resultados del examen \(texto)"

Lo mejor de todo esto es que «string interpolation» no esta limitado a variables si no que podemos correr código también.

Constantes

Las variables son geniales para guardar valores que cambian, ahora bien algunas veces tenemos valores que nunca cambian, en ese caso es mejor usar constantes en swift este tipo es «Let»

Por ejemplo

let yoSoy = "Batman 🦇"

si tratas de modificar ese valor Xcode no te dejara, esto es bueno pues así evitas cambiar constantes por accidente

yoSoy = "Bruno Días"

Type annotations

Especificar el tipo

Swift sigan a cada variable y constate un tipo basado en que valor es dado al momento de ser creada. Por ejemplo aquí swift puede deducir que es un String

var saludo = "Hola 🖖🏼"

y no podrás asignarle un tipo de valor diferente después

esto se llama «type inference» o deducción de tipo

Ahora si quieres ser explícito sobre el tipo de valor de tu variable debes decláralas de esta forma:

let nombre: String = "Bruno Días"
let edad: Int = 50
let altura: Double = 1.78
let elEsBatman: Bool = true

Como nota Baléanos (Booleans) y Enteros (Intergers) tiene el nombre corto «Bool» e «Int»

Resumen

Creamos variables usando «var» y constantes usando «let»

Las cadenas de texto inician y terminan con comillas dobles «”», pero si quires que el texto sea multi linea debes usar tres cada una en su propia linea

Variables de tipo Enteros (Int) guardan números completos, variables con Punto decimal (Double) guarda números con fracciones, y variables de tipo Booleano (Bool) guardan valores verdaderos o falsos (true/false)

«String Interpolation» permite incrustar en el texto variables, constantes y ejecutar código.

Swift usa deducción de tipos (type inference) cuando creas una variable o constate para asignarle un tipo, pero si quieres puedes especificarlo tú mismo.

// y ese fue el resumen del día 1

Referencias

Todas estas notas están basadas en el curso de hackingwithswift

https://www.hackingwithswift.com/100

https://www.hackingwithswift.com/100/1

Proximo día

Categories
Swift Development

Core Data y CloudKit en las nuevas Apps MultiPlatafora de SwiftUI

En mi entrada anterior agregué Core Data a mi App MultiPlaforma ahora veamos si podemos agregar CloudKit para que se sincronice entre nuestros diferentes dispositivos.

Si no has leído el articulo anterior seria bueno que le dieras una leída

Paso 1

En primer lugar tenemos que añadir CloudKit a nuestro proyecto

Para eso nos dirigimos al archivo de nuestro proyecto donde podemos ver nuestros targets

Seleccionamos nuestro target y luego singning & Capabilities

Ahora seleccionamos el botón + capability y elegimos iCloud

Una vez añadido seleccionamos la casilla de CloudKit y en Containers elegimos alguno que ya tengamos o creamos uno nuevo.

Lo mismo para iOS y nuestros demás targets (Exceptuando los test )

También es necesario que en iOS añadamos BackGround Modes

y marcamos Remote Notifications

Paso 2

Así que ahora en nuestra clase PersistentCloudKitContainer.swift vamos cambiar nuestro container

En nuestra clase PersistentCloudKitContainer
let container = NSPersistentContainer(name: "ruleOfThree")

Por este que funciona con CloudKit

let container = NSPersistentCloudKitContainer(name: "ruleOfThree")

y lo mismo en el valor que retorna

...
public static var persistentContainer: NSPersistentContainer = {
...

por este otro

...
public static var persistentContainer: NSPersistentCloudKitContainer = {
...

De forma que nuestra clase queda de la siguiente forma

import CoreData
public class PersistentCloudKitContainer {
    // MARK: - Define Constants / Variables
    public static var context: NSManagedObjectContext {
        return persistentContainer.viewContext
    }
    // MARK: - Initializer
    private init() {}
    // MARK: - Core Data stack
    public static var persistentContainer: NSPersistentCloudKitContainer = {
        let container = NSPersistentCloudKitContainer(name: "ruleOfThree")
        
        guard let description = container.persistentStoreDescriptions.first else {
            fatalError("No descriptions found")
        }
        
        description.setOption(true as NSObject, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
        
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        container.viewContext.automaticallyMergesChangesFromParent = true
        container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
        
        
        return container
    }()
    // MARK: - Core Data Saving support
    public static func saveContext () {
        let context = persistentContainer.viewContext
        if context.hasChanges {
            do {
                try context.save()
            } catch {
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        }
    }
}

Paso 3

Ahora el siguiente paso es dirigirnos a nuestro modelo de datos y marcar bajo Configurations > Default y en la vista del inspector marcamos used with CloudKit

Con eso ya podemos correr nuestros simuladores y probar sí están sincronizando. Para esto es necesario loggearnos en nuestros dos simuladores

Paso 4 (Extra)

Bien en este punto CloudKit y la sincronización ya funciona de manera correcta pero quiero añadir algunos ajustes extras para optimizar mis registros, evitar duplicados y poder reordenar los elementos.

así que regresamos a nuestra clase y añadimos el siguiente bloque de código

guard let description = container.persistentStoreDescriptions.first else {
            fatalError("No descriptions found")
}

description.setOption(true as NSObject, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)

Con este código podemos recibir notificaciones cuando algo cambie en nuestro modelo de datos

NotificationCenter.default.addObserver(self, selector: #selector(self.processUpdate), name: .NSPersistentStoreRemoteChange, object: nil)

Ahora gracias a la recomendación de un profesional en twitter encontré una mejor forma de implementar la sincronización

Bien esta nueva implementación tiene muchas mejoras la principal es que ahora utilizamos @StateObject para manejar nuestro modelo de datos

Para eso es necesario hacer que nuestra clase se ajuste a ObservableObject

...
public class PersistentCloudKitContainer: ObservableObject {
...

Así que borramos

...  
// MARK: - Define Constants / Variables
    public static var context: NSManagedObjectContext {
        return persistentContainer.viewContext
    }
    // MARK: - Initializer
    private init() {}
...

y ahora nuestra clase queda de esta forma

import CoreData
public class PersistentCloudKitContainer: ObservableObject {
    
    // MARK: - Core Data stack
    lazy var persistentContainer: NSPersistentCloudKitContainer = {
        let container = NSPersistentCloudKitContainer(name: "ruleOfThree")
        
        guard let description = container.persistentStoreDescriptions.first else {
            fatalError("No descriptions found")
        }
        
        description.setOption(true as NSObject, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
        
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        container.viewContext.automaticallyMergesChangesFromParent = true
        container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
        
        NotificationCenter.default.addObserver(self , selector: #selector(processUpdate), name: .NSPersistentStoreRemoteChange, object: nil)
        
        return container
    }()
    
}

Ahora lo que sigue es modificar en nuestro @main


import SwiftUI
import CoreData

@main
struct ruleOfThreeApp: App {
    @StateObject var coreData = PersistentCloudKitContainer()
    var body: some Scene {
        WindowGroup {
            ContentView().environment(\.managedObjectContext, coreData.persistentContainer.viewContext)
        }
    }
}

y con eso podemos agregar funciones extras a nuestra clase por ejemplo en mi caso para poder reorder mis listas.

Referencias

En este caso base mi código en el siguiente tutorial

Categories
Swift Development

CoreData en SwiftUI

Dub Dub ah llegado a su fin y SwiftUI ha evolucionado para convertirse en el rey de los frameworks, ahora podemos usarlo para crear apps a través de todo el ecosistema. Sin embargo la nueva arquitectura de las apps multi plataforma tiene un problema, hemos perdido la casilla de CoreData 😨, así que ahora tendremos que agregarlo a mano.

En este blog voy a documentar la manera de añadir CoreData a las nuevas apps multiplataforma de SwiftUI.

Paso 1

Creamos nuestra nueva app multi plataforma para eso solo seleccionamos crear nuevo proyecto, seleccionamos Multiplataforma > App y Nueva

Con eso tenemos una nueva aplicación multi plataforma que corre tanto en iOS como en MacOS

Así que aquí es donde comenzamos el hermoso nacimiento de una app multi plataforma, ahora vemos que necesitamos para añadir CoreData

Paso 2

Añadir nuestro nuevo modelo de datos, esto venia por default cuando creábamos un app con CoreData en iOS Anteriormente pero ahora tendremos que hacerlo a mano.

Para añadir nuestro modelo de datos solo presionamos ⌘ + N y elegimos Data Model en la sección de Core Data

Un punto importante al crear el modelo es poner dentro de Shared y elegir como targets tanto nuestros test como nuestras apps para iOS y macOS

Ahora creamos nuestro modelo de datos como siempre con sus entidades y relaciones

En este caso estoy haciendo una App para guardar reglas de tres

Nota: no olvides definir tus constraints para evitar que se te dupliquen tus valores

Paso 3

Crear las Clases de nuestro modelo de datos, esto no es algo obligatorio pero nos permite crear wrappers para no tener problemas con los optionals, principalmente en los Strings ademas nos permitirá agregar un mejor manejo de nuestras relaciones entre entidades, como explicare a continuación.

Primero que nada, no olvidemos en el inspector de la entidad definir que el codegen sera manual/none si no tendremos un error como el que se muestra a continuación

Esto ocurre cuando generamos nuestras subclases de manera manual y olvidamos decírselo al modelo de datos.

Una ves hecho eso, nos dirigimos al menu Editor > Create NSManagedObject Subclass

Seleccionamos nuestro modelo de datos

Seleccionamos las entidades de las cuales queremos crear su subclases

y de la misma forma que lo hicimos anteriormente nos aseguramos de que nuestros targets estén seleccionados y que la carpeta sea shared

Voilà con eso ya tenemos listas nuestras subclases ahora podemos deshacernos de los valores opcionales

Para eliminar los valores opcionales en las strings es tan fácilmente como crear una nueva variable

 public var wname : String {
      name ?? "No name"
    }

y para facilitar el manejo de nuestra relaciones agregamos otra variable con un Array de nuestra relación

 public var elementArray: [Element] {
        
        let set = elements as? Set<Element> ?? []
         
        return set.sorted {
            $0.wName > $1.wName
        }
        
    }

Lo mismo haremos en la otra entidad que creamos, si prestas atención al código a continuación veras que añadí una nueva variable para que Date no sea opcional

//
//  Element+CoreDataProperties.swift
//  3Rule
//
//  Created by Francisco Misael Landero Ychante on 02/06/20.
//  Copyright © 2020 Francisco Misael Landero Ychante. All rights reserved.
//
//

import Foundation
import CoreData


extension Element {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Element> {
        return NSFetchRequest<Element>(entityName: "Element")
    }

    @NSManaged public var decimals: Int16
    @NSManaged public var direct: Int16
    @NSManaged public var name: String?
    @NSManaged public var plurarlLabel: String?
    @NSManaged public var unitLabel: String?
    @NSManaged public var unitLabelExponent: String?
    @NSManaged public var usePlural: Bool
    @NSManaged public var useUnitLabel: Bool
    @NSManaged public var value: Double
    @NSManaged public var rule: Rule?
    @NSManaged public var date: Date?
    @NSManaged public var id: UUID?
    
    public var wDate : Date {
           date ?? Element.defaultTime
       }
    
    public var wName : String {
        name ?? "Sin Nombre"
    }
    
    public var wPlurarlLabel : String {
        plurarlLabel ?? ""
    }
    
    public var wUnitLabel : String {
           unitLabel ?? ""
    }
    
    public var wUnitLabelExponent : String {
           unitLabelExponent ?? ""
    }
    
    static var defaultTime: Date {
        var components =  Calendar.current.dateComponents([.hour, .minute, .month, .day, .year], from: Date())
        components.year = 2014
        components.month = 3
        components.day = 3
        return Calendar.current.date(from: components) ?? Date()
    }
    
}

Paso 4

Conectando SwiftUI y Core Data

ok esta la parte importante, primero nos dirigimos a donde nuestra app es declarada

import SwiftUI 

@main
struct ruleOfThreeApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

La nueva estructura de SwiftUI es Elegante y simple

Aquí añadiremos «import CoreData» y nuestro context «let context = PersistentCloudKitContainer.persistentContainer.viewContext» ademas de que lo añadimos a nuestro ContentView con «ContentView().environment(.managedObjectContext, context)»

Esto que antes iba en AppDelegate ahora se incorpora en @main que es la declaración de nuestra app.

import SwiftUI
import CoreData

@main
struct ruleOfThreeApp: App {
    
    let context = PersistentCloudKitContainer.persistentContainer.viewContext
        
    var body: some Scene {
        WindowGroup {
            ContentView().environment(\.managedObjectContext, context)
        }
    }
}

Muy bien finalmente ahora añadiremos una clase para conectar Core Data y nuestro modelo de datos.

Lo mismo que antes nuevo archivo ⌘ + N y nos aseguramos que sea en shared y que seleccionemos nuestros targets de manera apropiada

Ahora hay dos puntos importantes en el siguiente código

El primero en la linea 18

 let container = NSPersistentContainer(name: “ruleOfThree”)

Donde definimos el nombre de nuestro modelo de datos previamente creado

y el segundo en lineas 24 y 25

 container.viewContext.automaticallyMergesChangesFromParent = true

container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy

Donde definimos nuestras políticas de merge

//
//  PersistentCloudKitContainer.swift
//  ruleOfThree
//
//  Created by Francisco Misael Landero Ychante on 27/06/20.
//

import CoreData
public class PersistentCloudKitContainer {
    // MARK: - Define Constants / Variables
    public static var context: NSManagedObjectContext {
        return persistentContainer.viewContext
    }
    // MARK: - Initializer
    private init() {}
    // MARK: - Core Data stack
    public static var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "ruleOfThree")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        container.viewContext.automaticallyMergesChangesFromParent = true
        container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
        return container
    }()
    // MARK: - Core Data Saving support
    public static func saveContext () {
        let context = persistentContainer.viewContext
        if context.hasChanges {
            do {
                try context.save()
            } catch {
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        }
    }
}

Paso 5

Ahora solo resta probar que nuestro modelo funciona y que podemos guardar datos en él, para simplemente cree una lista y un botón para añadir elementos de prueba.

import SwiftUI

struct ContentView: View {
    
    // MARK: - Core Data
    @Environment(\.managedObjectContext) var moc
    
    @FetchRequest(entity: Rule.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Rule.order, ascending: true)] ) var rules: FetchedResults<Rule>
    
    var body: some View {
        List{
            ForEach(self.rules, id: \.self){ rule in
                Text("\(rule.order) \(rule.wname)")
            }
            Button(action: {
                saveTheRule()
            }) {
                Text("Add Rule")
            }
        }
    }

  func saveTheRule(){
        
        //New Rule
        
        let newRule = Rule(context: self.moc)
        
        newRule.baseLabel = "test"
        newRule.name = "Test name \(Int.random(in: 1..<100))" 
        
        
        //simple rule
          
            let newElement = Element(context: self.moc)
         
            newElement.name = "parameter name"
        
            
            newElement.rule = newRule

         try? self.moc.save()
         
    }

}
y bueno ahi esta en lo que agregan la casilla de CoreData otra vez esta es la forma manual de implementarlo.

En el siguiente post vamos a añadir sincronización con CloudKit

Para todo este proceso me base en las siguiente entradas del foro de desarrolladores de apple

https://developer.apple.com/forums/thread/117655

https://developer.apple.com/forums/thread/117655

https://developer.apple.com/forums/thread/650309

Categories
Articulo personal CSS Web Development WordPress

Personalizando el CSS de WordPress Soporte para Modo Oscuro y Claro

Ahora que comienzo mi blog personal decidí usar WordPress mas que nada por que no tenia ganas por el momento de reinventar la rueda y lo cierto es que como blog funciona a la perfección.

Aun así algo es claro y eso es; que el estilo CSS del tema por defecto no coincide con el de mi pagina web principal por tanto me decidí a investigar como editar el estilo css del tema de WordPress y ademas darle soporte para modo oscuro.

Es mas fácil editar el estilo desde CSS adicional en Apariencia > Temas > Personalizar > CSS adicional pero hay que estar inspeccionando los elementos para encontrar las clases por lo que es más fácil editarlo directamente desde el archivo css principal.

Para comenzar encontré que es posible editar el CSS del tema en Apariencia > Editor de temas

Al parecer al Inicio hay un indice de lo que contiene el archivo CSS principal ya que el cero se supone que es para reiniciar el estilo vamos a dejarlo tal y como esta.

Así que comienzo añadiendo mis constantes de colores

:root {
  --blacklc: #141619;
  --blacktwo: #212228;
  --blackthree: #1d1d21;
  --greelc: #69baa0;
  --bluelc: #589b99; 
}

Ahora esto hace que me marque errores en el código pero los ignoraremos por ahora.

para que nuestro sitio se adapte al modo oscuro o claro del dispositivo del usuario añadiremos estas dos etiquetas

@media (prefers-color-scheme: dark) {
	body {
		background: var(--blacktwo);
	}
}

@media (prefers-color-scheme: light) { 
	body {
		background: var(--greelc);
	}
}

Como puede verse he añadido mis dos constantes de color como fondo solo para probar si esta funcionado, así que ahora solo hay que hacer click en el botón actualizar archivo y recargar el sitio sin cache.

Modo claro
Modo oscuro

Ademas de editar el archivo CSS fue necesario editar un archivo php así que trate de elegir un color que funcionara tanto en modo oscuro como claro.

Ademas de editar el css fue necesario editar functions.php

Nota: al editar directamente en el editor del tema el css adicional que hagas quedara incrustado como una etiqueta style al principio del body del sitio así que tendrá prioridad.

Después de editar mi código tanto en personalizar tema como en archivo css principal y el php obtuve este resultado.

Antes de terminar me di cuenta me había faltado definir otro color para las categorías en el modo claro y no se veían por ser del mismo color que el del tema de fondo.

y por ultimo el toque final

power by WordPress & landercorp.mx

con eso ya queda listo mi blog para comenzar a narrar mis aventuras haciendo sitios WEB y aplicaciones en SwiftUI

Categories
Articulo personal Swift Development Web Development

print(“Hola :D mundo”)

Bienvenidos a mi blog donde escribiré sobre mi aventura para convertirme en un desarrollador de iOS / Swift y Desarrollador Web.