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

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Pantalla home: programación de interfaces estáticas

13/36
Recursos

Aportes 11

Preguntas 6

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Les dejo acá las variables con las URLs 😄

struct SubModuloHome:View {
    @State var url = "https://cdn.cloudflare.steamstatic.com/steam/apps/256658589/movie480.mp4"
    @State var isPlayerActive = false
    let urlVideos:[String] = ["https://cdn.cloudflare.steamstatic.com/steam/apps/256658589/movie480.mp4","https://cdn.cloudflare.steamstatic.com/steam/apps/256671638/movie480.mp4","https://cdn.cloudflare.steamstatic.com/steam/apps/256720061/movie480.mp4","https://cdn.cloudflare.steamstatic.com/steam/apps/256814567/movie480.mp4","https://cdn.cloudflare.steamstatic.com/steam/apps/256705156/movie480.mp4","https://cdn.cloudflare.steamstatic.com/steam/apps/256801252/movie480.mp4","https://cdn.cloudflare.steamstatic.com/steam/apps/256757119/movie480.mp4"]

Debajo del HStack de input de busqueda va este pedazo

...
}.padding([.top, .leading, .bottom], 11.0)
                .background(Color("Blue-Gray"))
                .clipShape(Capsule())

ScrollView(showsIndicators: false){
                SubModuloHome()
                    
                }

Porque al parecer no muestra como lo hace

No me gustó que del video 12 al 13 se saltararon una asignacion de codigo, por ejemplo, el struct llamado “SubModuloHome” y el Spacer que asignaron a la imagen y al textfield para que estos subieran, los anterior pensando en personas que quizá les sea mas dificl identificar esto que dieron por hecho

Es importante mencionar que el NavigationLink(destination:isActive:label) va ser deprecado en futuras versiones, es recomendable utilizar NavigationLink(isActive:destination:label).

Esta es la nueva url del recurso de la API: link la otra dejo de funcionar pero ya la arreglaron.

Para los que tengan problemas con el tema del Navigation, les dejo cómo lo solucione:

NavigationStack {
                ZStack {
                    Button(action: {
                        url = urlVideos[0]
                        print("URL: \(url)")
                        isPlayerActive = true
                    }, label: {
                        VStack (spacing: 0){
                            Image("The Witcher 3").resizable().scaledToFill()
                            Text("The Witcher 3").frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
                                .background(Color("Blue-Gray"))
                        }
                    })
                    
                    Image(systemName: "play.circle.fill")
                        .resizable()
                        .foregroundColor(.white)
                        .frame(width: 42, height: 42)
                    
                    
                }.frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
                    .padding(.vertical)
            }.navigationDestination(isPresented: $isPlayerActive) {
                VideoPlayer(player: AVPlayer(url: URL(string: url)!))
                    .frame(width: 400, height: 300)
            }

Hola. alguien tiene la resolución a este problema con la nueva versión 16.0?

Arregle el error de NavigationLink de la siguiente manera ```js VStack { Text("THE MOST POPULAR") .font(.title3) .foregroundStyle(.white) .bold() .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) .padding(.top) ZStack { Button(action: { url = urlVideos[0] print("URL: \(url)") isPlayerActive = true }, label: { VStack(spacing: 0) { Image("The Witcher 3").resizable().scaledToFill() Text("The Witcher 3").frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) .background(Color("Blue-Gray")) } }) Image(systemName: "play.circle.fill") .resizable() .foregroundStyle(.white) .frame(width: 42, height: 42) }.frame(minWidth: 0, maxWidth: .infinity, alignment: .center) .padding(.vertical) .navigationDestination(isPresented: $isPlayerActive) { VideoPlayer(player: AVPlayer(url: URL(string: url)!)) .frame(width: 400, height: 300) } } ```VStack { Text("THE MOST POPULAR") .font(.title3) .foregroundStyle(.white) .bold() .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) .padding(.top) ZStack { Button(action: { url = urlVideos\[0] print("URL: \\(url)") isPlayerActive = **true** }, label: { VStack(spacing: 0) { Image("The Witcher 3").resizable().scaledToFill() Text("The Witcher 3").frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) .background(Color("Blue-Gray")) } }) Image(systemName: "play.circle.fill") .resizable() .foregroundStyle(.white) .frame(width: 42, height: 42) }.frame(minWidth: 0, maxWidth: .infinity, alignment: .center) .padding(.vertical) .navigationDestination(isPresented: $isPlayerActive) { VideoPlayer(player: AVPlayer(url: URL(string: url)!)) .frame(width: 400, height: 300) } }

Button Vs NavigationLink

Mientras sigo las clases del profesor y me doy cuenta que la forma que utiliza esta o será deprecada me toca buscar alternativas que solucionen el problema, hasta el momento he encontrado 2 formas, una es muy similar a la del profesor que seria con un Button y la otra que encontré es solo utilizar un NavigationLink:

Solución con button

ZStack {
	Button(action: {
		url = urlVideos[0]
		print("URL: \(url)")
		isPlayerActive = true
	}) {
			VStack(spacing: 0) {
			Image("thewitcher").resizable().scaledToFit()
			Text("The Witcher 3").frame(minWidth: 0, maxWidth: .infinity, alignment: .leading).background(Color("Blue-Gray"))
			}
		}.navigationDestination(isPresented: $isPlayerActive, destination: {
			VideoPlayer(player: AVPlayer(url: URL(string: url)!)).frame(width: 400, height: 300)
		})
	Image(systemName: "play.circle.fill").resizable().foregroundStyle(.white).frame(width: 42, height: 42)
}.frame(minWidth: 0, maxWidth: .infinity, alignment: .center).padding(.vertical)

Como podemos observar en lugar de agregar un NavigationLink lo ponemos como un modificador del botón (esta solución la vi en un comentario de este curso)

Solución con navigationLink

NavigationLink(destination: {
	VideoPlayer(player: AVPlayer(url: URL(string: url)!)).frame(width: 400, height: 300)
 }) {
	ZStack {
		VStack(spacing: 0) {
			Image("thewitcher").resizable().scaledToFit()
			Text("The Witcher 3").frame(minWidth: 0, maxWidth: .infinity, alignment: .leading).background(Color("Blue-Gray")).foregroundStyle(.white)
		}
		Image(systemName: "play.circle.fill").resizable().foregroundStyle(.white).frame(width: 42, height: 42)
	}.frame(minWidth: 0, maxWidth: .infinity, alignment: .center).padding(.vertical)
}

Personalmente mi favorita porque considero que el código se ve más legible, pero no se si es una buena practica así que toca escoger la que mas te guste.

```js ZStack { Button(action: { url = urlVideos[0] isPlayerActive = true }, label: { VStack(spacing: 0) { Image("The Witcher 3") .resizable() .scaledToFill() Text("The Witcher 3") .frame( minWidth: 0, maxWidth: .infinity, minHeight: 42, alignment: .leading ).padding(.leading) .background(.blueGray) .font(.subheadline) .bold() } }).navigationDestination(isPresented: $isPlayerActive, destination: { VideoView(url: URL(string: url)!) }) Image(systemName: "play.circle.fill").resizable() .foregroundStyle(.white) .frame(width: 42, height: 42) } .frame(minWidth: 0, maxWidth: .infinity, alignment: .center) .padding(.vertical) import SwiftUI import AVKit struct VideoView: View { let url: URL private var player: AVPlayer init(url: URL) { self.url = url self.player = AVPlayer(url: url) } var body: some View { VideoPlayer(player: player) .onAppear() { player.play() } .onDisappear() { player.pause() } .edgesIgnoringSafeArea(.all) } } #Preview { VideoView(url: URL(string: "https://cdn.cloudflare.steamstatic.com/steam/apps/256658589/movie480.mp4")!) } ```