Repositorios

Podcast Próxima Parada Swift

Reproductor del podcast Próxima parada swift

Reproductor del podcast Próxima Parada Swift publicado en https://proximaparadaswift.dev

Proyecto realizado con MVVM en SwiftUI, utilizando Observable, SwiftData, Combine, AVFoundation, Regex,

Funcionalidades

Ordena los episodios por fecha, búscalos por título o filtra por categoría

Escucha el episodio ajustando la velocidad de reproducción

Descarga el audio de los episodios para escucharlos después

Lleva el registro de tus episodios favoritos y escuchados

Obtén un listado de enlaces que recomiendo para aprender Swift

Retos personales conseguidos

* AVFoundation para reproducir los audios del podcast y poder cambiar la velocidad de reproducción.

* Regex (Expresiones Regulares) para obtener a patir del json generado por la API de WordPress el contenido y de ahí obtener la url del audio.

* SwiftData para la persistencia de datos 

* Convertir correctamente un post de WordPress en formato HTML a un `AttributedString` 

Referencias

Date Formatter

Swifty Place

Swift Data by Example

Json Beautify

Chat GP3

AV Player & SwiftUI

Vista Previa

Apuntes

Convertir un html a un attributedString

//Convierte de un html a un AttributedString
func attributedTextFromHTML(_ html: String) -> AttributedString? {
    guard let data = html.data(using: .utf8) else { return nil }
    
    do {
        let options: [NSAttributedString.DocumentReadingOptionKey: Any] = [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue]
        
        let attributtedString = try AttributedString.init(NSAttributedString(data: data, options: options, documentAttributes: nil))
                                                          
        return attributtedString
    } catch {
        return nil
    }
}

Container de SwiftData con dos schemas

extension ModelContainer {
    
    static var previewContainer: ModelContainer {
        let schema = Schema([
            Episodio.self,
            PostCategory.self
        ])
        let config = ModelConfiguration(schema: schema, isStoredInMemoryOnly: true)
        let container = try! ModelContainer(for: schema, configurations: config)
        
        return container
    }
}

Container para la preview

extension ModelContainer {
    
    static var previewContainer: ModelContainer {
        let schema = Schema([
            Episodio.self,
            PostCategory.self
        ])
        let config = ModelConfiguration(schema: schema, isStoredInMemoryOnly: true)
        let container = try! ModelContainer(for: schema, configurations: config)
        
        return container
    }
}