Introducción al curso

1

Construyamos una app para iOS

2

Introducción a la arquitectura MVVM

3

Planeando nuestra app

Creando las primeras pantallas de la app

4

Programando la primera pantalla en módulos

5

Escribiendo la lógica para mostrar dos pantallas

6

Pantalla de inicio de sesión con SecureField y Scroll

7

Completando nuestra pantalla de inicio de sesión

8

Pantalla de registro de usuario

9

Comprobando el funcionamiento de nuestras pantallas

10

Estructura de las pantallas con TabView

11

Creando nuestra pantalla home

12

Pantalla home: logo y barra de búsqueda

13

Pantalla home: programación de interfaces estáticas

14

Pantalla home: carruseles

Aplicando arquitectura MVVM

15

Creando estructura para arquitectura MVVM

16

Modelando nuestro JSON

17

Peticiones al servidor

18

Mostrar información de un servidor de manera dinámica

19

Mostrar imágenes de forma dinámica y eficiente con LazyVGrid

Reproductor y búsqueda de video

20

Pasar datos entre pantallas

21

Darle datos de inicio a un Canvas

22

Reproducir videos dinámicamente de un servidor

23

Mostrar imágenes dinámicamente de un servidor

24

Mostrar alertas

25

Programar clase de búsqueda

26

Programar método de búsqueda

Últimas pantallas de la app

27

Pantalla de favoritos

28

Pantalla de perfil de usuario

29

Módulo de ajustes de perfil con Toggle

30

Pantalla de edición de perfil

31

Módulo de edición de perfil

32

Guardado interno de datos

Utilizando la cámara y fotos del iPhone

33

Captura de foto de perfil: ImagePicker y vista Sheet

34

Captura de foto de perfil con la cámara: modificar librerías de terceros

35

Captura de foto de perfil con la cámara: recuperar imágenes guardadas

¿Qué más posibilidades tiene SwiftUI?

36

Mejoremos nuestra app

Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Mostrar imágenes de forma dinámica y eficiente con LazyVGrid

19/36
Recursos

Aportes 6

Preguntas 1

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

A partir de iOS15+ ahora existe la opción de usar AsyncImage algo así, por lo que no sería estrictamente necesario utilizar Kingfisher

AsyncImage(url: URL(string: "https://example.com/icon.png"))
    .frame(width: 200, height: 200)

En la nueva versión de Xcode (13), la forma de agregar librerías (paquetes) es:
Menu File -> Add Packages… -> En la siguiente ventana, en el campo de “Buscar”, se coloca la URL de la librería (en este caso "https://github.com/onevcat/Kingfisher.git), se selecciona el botón “Add Package”. Después de terminar el Feching, se vuelve a seleccionar el botón “Add Package”… y listo!
Aquí un breve video del proceso: https://youtu.be/bN0AkBT-C7M

Esta es la URL del repo de la dependencia de Swift que hay que añadir:

https://github.com/onevcat/Kingfisher.git

(También la puedes encontrar en los recursos de la clase 😉 )

  • Si usan AsynImage puede no funcionar resizable(). Entonces pueden usar lo siguiente.

  • Yo le deje el Text que el profe Juan había puesto para probar como se veía.

// Imagen y título de cada juego.
                                VStack
                                {
                                    AsyncImage( url: URL( string: juego.galleryImages[0] )!  )
                                    { image in
                                        image
                                            .resizable()
                                            .aspectRatio(contentMode: .fit)
                                            .clipShape(RoundedRectangle(cornerRadius: 15))
                                            .padding()
                                    } placeholder: {
                                        placeholderImage()
                                    }
                                        
                                        
                                    Text("\(juego.title)").foregroundColor(.white)
                                        .font(.body)
                                        .padding(.bottom, 12.0)
                                    
                                }


  • Pero es necesaria esta función, que cargara un View por si no puede tomar la imagen del servidor. Mientras carga pone el símbolo de cámara del SF symbols
// 
@ViewBuilder
    func placeholderImage() -> some View {
        Image(systemName: "photo")
            .renderingMode(.template)
            .resizable()
            .aspectRatio(contentMode: .fit)
    
            .frame(width: 150, height: 150)
            .foregroundColor(.gray)
    }

  • Y queda así:

Dejo modificación del botón por si alguien quiere tener el texto…
dejo código del botón y código de una función

Button(action: {
                                gameVO = GameViewObject(game: juego)
                                print("Pulse el juego \(gameVO!.title)")
                            }, label: {
                                
                                VStack {
                                    KFImage(URL(string: juego.galleryImages[0])!).resizable().aspectRatio(contentMode: .fit).clipShape(RoundedRectangle.init(cornerRadius: 4)).padding(.bottom, 8)//.frame(maxHeight: 100, alignment: .center)
                                    
//                                    Text("\(juego.title)")
                                    Text(cortarString(24, textoIn:juego.title)).font(.footnote).foregroundColor(.white).padding(EdgeInsets(top: 16, leading: 0, bottom: 30, trailing: 0))
                                    
                                }//.frame(maxHeight: 100, alignment: .center)
                                
                            })
func cortarString(_ cantidad: Int, textoIn:String) -> String {
    var stringToReturn:String = ""
    let mySubstring = textoIn.prefix(cantidad)

    stringToReturn = String(mySubstring)
    
    if textoIn.count > cantidad {
        stringToReturn = stringToReturn + "..."
    }

//    print("Texto entero \(textoIn)")
//    print("Texto cortado \(mySubstring)")
//    print("Texto a retornar \(stringToReturn)")
    return String(stringToReturn)
}