Una aplicación para probar las librerías UIKit y AVFoundation con iOS

BaseViewController.swift

//
//  BaseViewController.swift
//  UIKit component handling
//

import UIKit

class BaseViewController: UIViewController {
    let componentName:String
    
    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
    }
    
    init(_ componentName: String) {
        self.componentName = componentName
        super.init(nibName: nil, bundle: nil)
        self.navigationItem.prompt = componentName
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func appDelegate() -> AppDelegate? {
        guard let app = UIApplication.shared.delegate as? AppDelegate else { return nil }
        return app
    }
}

RootViewController.swift

//
//  ViewController.swift
//  UIKit component handling
//

import UIKit

class RootViewController: UITableViewController, UISearchBarDelegate {
    @IBOutlet var searchBar: UISearchBar!
    
    let componentList : [BaseViewController] = [
        LabelVC("UILabel"),
        ImageViewVC("UIImageView"),
        ToolBarVC("UIToolBar"),
        FirstNavigationBarVC("Navigation Bar"),
        PlayMusicalNotesVC("AVAudioPlayer"),
        WebServiceSchoolsVC("JSON web service"),
        ScrollViewVC("UIScrollView")
        /* ... */
    ]
    
    var filteredData : [BaseViewController]! = nil
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.filteredData = self.componentList
        
        self.searchBar.delegate = self
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.filteredData.count
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "cell")
        
        cell.textLabel?.text = self.filteredData[indexPath.row].componentName
        
        return cell
    }
    
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        
        self.navigationController?.pushViewController(self.filteredData[indexPath.row], animated: true)
    }

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        self.filteredData = searchText.isEmpty ? self.componentList : self.componentList.filter({$0.componentName.contains(searchText)})
        
        tableView.reloadData()
    }
}

AppDelegate.swift

//
//  AppDelegate.swift
//  UIKit component handling
//

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    var effectView: UIView!
    var window: UIWindow?
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        return true
    }
    
    func applicationWillResignActive(_ application: UIApplication) {
        makeEffectView()
    }
    
    func applicationDidEnterBackground(_ application: UIApplication) {
    }
    
    func applicationWillEnterForeground(_ application: UIApplication) {
    }
    
    func applicationDidBecomeActive(_ application: UIApplication) {
        removeEffectView()
    }
    
    func applicationWillTerminate(_ application: UIApplication) {
    }
}

extension AppDelegate {
    
    private func makeEffectView() {
        effectView = UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffect.Style.light))
        effectView.frame = CGRect(x:0, y:0, width:UIScreen.main.bounds.size.width, height:UIScreen.main.bounds.size.height)
        self.window?.addSubview(effectView)
    }
    
    private func removeEffectView() {
        if effectView != nil {
            self.effectView.removeFromSuperview()
        }
    }
    
    // Add UIAlertController on UIViewController
    func showMessage(vc: UIViewController, title: String, message: String, actionTitle: String, actionStyle: UIAlertAction.Style) {
        // Create a UIAlertController.
        let alert: UIAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        
        // Add an Action of OK.
        alert.addAction(UIAlertAction(title: actionTitle, style: actionStyle, handler: { action in print("Action OK!") }))
        
        // Activate UIAlert.
        vc.present(alert, animated: true, completion: nil)
    }
}

LabelVC.swift

//
//  LabelVC.swift
//  UIKit component handling
//

import UIKit

class LabelVC: BaseViewController {

    lazy var label: UILabel = {
        // Define the size of the label.
        let width: CGFloat = 300
        let height: CGFloat = 100
        
        // Define coordinates to be placed.
        // (center of screen)
        let posX: CGFloat = self.view.bounds.width/2 - width/2
        let posY: CGFloat = self.view.bounds.height/2 - height/2
        
        // Label Create.
        let label: UILabel = UILabel(frame: CGRect(x: posX, y: posY, width: width, height: height))
        
        // Define background color.
        label.backgroundColor = .orange
        
        // Define text color.
        label.textColor = .white
        
        // Define text font.
        label.font = .systemFont(ofSize: 20, weight: .regular)
        
        // Define text of label.
        label.text = "Hello! :)"
        
        // Define count of line.
        // '0' is infinity
        label.numberOfLines = 0
        
        // Round UILabel frame.
        label.layer.masksToBounds = true
        
        // Radius of rounded corner.
        label.layer.cornerRadius = 20.0
        
        // Define shadow color.
        label.shadowColor = .gray
        
        // Define text Alignment.
        // options: .left, .right, .center, .justified, .natural
        label.textAlignment = .center
        
        return label
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Add UILabel to view.
        self.view.addSubview(self.label)
    }
}

ImageViewVC.swift

//
//  ImageViewVC.swift
//  UIKit component handling
//

import UIKit

class ImageViewVC: BaseViewController {
    
    lazy var imageView: UIImageView = {
        // Set the size of UIImageView.
        let width: CGFloat = self.view.bounds.width/2
        let height: CGFloat = 150
        
        // Set x, y of UIImageView.
        let posX: CGFloat = (self.view.bounds.width - width)/2
        let posY: CGFloat = (self.view.bounds.height - height)/2
        
        // Create UIImageView.
        let imageView = UIImageView(frame: CGRect(x: posX, y: posY, width: width, height: height))
        
        // Create UIImage.
        let myImage = UIImage(named: "apple.png")!
        
        // Set the image to UIImageView.
        imageView.image = myImage
        
        return imageView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Add UIImageView to view
        self.view.addSubview(self.imageView)
    }
}

ToolBarVC.swift

//
//  ToolBarVC.swift
//  UIKit component handling
//

import UIKit

class ToolBarVC: BaseViewController {

    private let toolBarHeight: CGFloat = 44
    
    lazy var toolBar: UIToolbar = {
        // Decide the size of the toolbar.
        let tb = UIToolbar(frame: CGRect(x: 0, y: self.view.bounds.size.height - toolBarHeight, width: self.view.bounds.size.width, height: 40.0))
        
        // Determine the position of the toolbar.
        tb.layer.position = CGPoint(x: self.view.bounds.width/2, y: self.view.bounds.height-20.0)
        
        // Decide the color of the toolbar.
        tb.barStyle = .blackTranslucent
        tb.tintColor = .white
        tb.backgroundColor = .black
        
        return tb
    }()
    
    lazy var barButtonGreen: UIBarButtonItem = {
        // Generate button 1.
        return UIBarButtonItem(title: "Green", style:.plain, target: self, action: #selector(onClickBarButton))
    }()
    
    lazy var barButtonBlue: UIBarButtonItem = {
        // Generate button 2.
        return UIBarButtonItem(title: "Blue", style:.plain, target: self, action: #selector(onClickBarButton))
    }()
    
    lazy var barButtonRed: UIBarButtonItem = {
        // Generate button 3.
        return UIBarButtonItem(title: "Red", style:.plain, target: self, action: #selector(onClickBarButton))
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Place the button in the tool bar.
        self.toolBar.items = [self.barButtonGreen, self.barButtonBlue, self.barButtonRed]
        
        // Add UIToolBar on view
        self.view.addSubview(self.toolBar)
    }
    
    // Called when UIBarButtonItem is pressed.
    @objc private func onClickBarButton(sender: UIBarButtonItem) {
        switch sender.title {
            case "Green": self.view.backgroundColor = .green
            case "Blue": self.view.backgroundColor = .blue
            case "Red": self.view.backgroundColor = .red
            default: return
        }
    }
}

Navigation Bar

FirstNavigationBarVC.swift

//
//  FirstNavigationBarVC.swift
//  UIKit component handling
//

import UIKit

class FirstNavigationBarVC: BaseViewController {
    
    lazy var button: UIButton = {
        // Create Button
        let b = UIButton(frame: CGRect(x: 0, y: 0, width: 250, height: 50))
        b.backgroundColor = .orange
        b.layer.masksToBounds = true
        b.setTitle("Go to second view", for: .normal)
        b.layer.cornerRadius = 20.0
        b.layer.position = CGPoint(x: self.view.bounds.width/2, y:200)
        b.addTarget(self, action: #selector(goToNextView), for: .touchDown)
        
        return b
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Define the background color of View.
        self.view.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
        
        // Add button on view
        self.view.addSubview(self.button)
        
        // Create a BarButtonItem.
        let barButton_1 = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(goToPreviousView))
        
        let barButton_2 = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(goToNextView))
        let barButton_3 = UIBarButtonItem(barButtonSystemItem: .fastForward, target: self, action: #selector(goToNextView))
        
        // Set the title.
        self.navigationItem.title = "First View"

        // Place it on the left side of Bar.
        self.navigationItem.setLeftBarButton(barButton_1, animated: true)
        
        // Place multiple on the right side of Bar.
        self.navigationItem.setRightBarButtonItems([barButton_2, barButton_3], animated: true)
    }
    
    // Called when the left bar button is pressed
    @objc private func goToPreviousView(sender: UIBarButtonItem) {
        self.navigationController?.popViewController(animated: true)
    }
    
    // Called when the right bar buttons and the button on the screen are pressed
    @objc private func goToNextView(sender: UIButton) {
        let secondViewController = SecondNavigationBarVC("Second view")
        self.navigationController?.pushViewController(secondViewController, animated: true)
    }
}

SecondNavigationBarVC.swift

//
//  SecondNavigationBarVC.swift
//  UIKit component handling
//

import UIKit

class SecondNavigationBarVC: BaseViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Define the background color of View.
        self.view.backgroundColor = UIColor.green
    }
}

PlayMusicalNotesVC.swift

//
//  PlaySoundVC.swift
//  UIKit component handling
//

import UIKit
import AVFoundation

class PlayMusicalNotesVC: BaseViewController {
    
    var audioPlayer : AVAudioPlayer!
    
    let sounds = ["do", "re", "mi", "fa", "sol", "la", "si", "do2"]
    
    lazy var stackView: UIStackView = {

        let stackView = UIStackView()
        
        stackView.frame = CGRect(x: 0, y: 98, width: self.view.bounds.width, height: self.view.bounds.height - 98)
        stackView.axis = .vertical
        stackView.distribution = .fillEqually
        
        for sound in sounds {
            let button = UIButton()
            
            // Set the background color of the button.
            button.backgroundColor = .white
            button.layer.borderWidth = 1
            button.layer.borderColor = UIColor.black.cgColor
            
            // Set the title (normal).
            button.setTitle(sound, for: .normal)
            button.setTitleColor(.black, for: .normal)
            
            // Set the title (highlighted).
            button.setTitle(sound, for: .highlighted)
            button.setTitleColor(.red, for: .highlighted)
            
            // Add an event.
            button.addTarget(self, action: #selector(onClick), for: .touchDown)
            
            stackView.addArrangedSubview(button)
        }
            
        return stackView
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Add UIStackView to view.
        self.view.addSubview(self.stackView)
    }
    
    // Button event.
    @objc private func onClick(_ sender: UIButton) {

        if let soundURL : URL = Bundle.main.url(forResource: sender.currentTitle, withExtension: "mp3") {
            print(soundURL)
            do {
                audioPlayer = try AVAudioPlayer(contentsOf: soundURL)
                audioPlayer.play()
            } catch {
                print(error)
            }
        }
    }
}

WebServiceSchoolsVC

//
//  WebServiceSchoolsVC.swift
//  UIKit component handling
//

import UIKit

class Ciclo : Codable {
    var denominacion:String = ""
    var denominacion_val:String = ""
}

class WebServiceSchoolsVC: BaseViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
    
    // Define the array to use in the Table.
    var ciclos: [Ciclo] = []
    var ciclosFiltrados: [Ciclo] = []
    
    // Define the url to download the data
    let url = URL(string: "https://fernandoruizrico.com:8001/api/getListadoCiclos")
    
    lazy var searchBar: UISearchBar = {
        // Create a search bar.
        let searchBar = UISearchBar()
        searchBar.delegate = self
        searchBar.frame = CGRect(x: 0, y: 98, width: self.view.bounds.width, height: 100)
        
        // Add a shadow.
        searchBar.layer.shadowColor = UIColor.black.cgColor
        searchBar.layer.shadowOpacity = 0.5
        searchBar.layer.masksToBounds = false
        
        // Disable the bookmark button.
        searchBar.showsBookmarkButton = false
        
        // Set bar style to Default.
        searchBar.searchBarStyle = .default
        
        // Set descriptive text.
        searchBar.placeholder = "Buscar"
        
        // Set the color of the cursor and cancel button.
        searchBar.tintColor = .red
        
        // The search result display button is not displayed.
        searchBar.showsSearchResultsButton = false
        
        return searchBar
    }()
    
    lazy var tableView: UITableView = {

        let tableView = UITableView()
        
        tableView.frame = CGRect(x: 0, y: 200, width: self.view.bounds.width, height: self.view.bounds.height)
        
        // Register the Cell name.
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
        
        // Set the DataSource.
        tableView.dataSource = self
        
        // Set Delegate.
        tableView.delegate = self
        
        return tableView
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()

        URLSession.shared.dataTask(with: url!) { (data, response, error) in
            do {
                // Decode data
                self.ciclos = try JSONDecoder().decode([Ciclo].self, from: data!)
                self.ciclosFiltrados = self.ciclos
                
                DispatchQueue.main.async {
                    // Add UITableView on view
                    self.view.addSubview(self.searchBar)
                    self.view.addSubview(self.tableView)
                }
            } catch let error {
                print("Error: \(error)")
            }
        }.resume()
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return ciclosFiltrados.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        
        cell.textLabel?.text = self.ciclosFiltrados[indexPath.row].denominacion
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        
        // Create a UIAlertController.
        let alert: UIAlertController = UIAlertController(title: "Ciclo", message: self.ciclosFiltrados[indexPath.row].denominacion+"\n"+self.ciclosFiltrados[indexPath.row].denominacion_val, preferredStyle: .alert)
        
        // Add an Action of OK.
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        
        present(alert, animated: true, completion: nil)
    }
    
    // Called whenever text is changed
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        self.ciclosFiltrados = searchText.isEmpty ? self.ciclos : self.ciclos.filter({$0.denominacion.contains(searchText)})
        self.tableView.reloadData()
    }
}

ScrollViewVC.swift

//
//  ScrollViewVC.swift
//  UIKit component handling
//

import UIKit

class ScrollViewVC: BaseViewController {
    
    lazy var scrollView: UIScrollView = {
        let scrollView: UIScrollView = UIScrollView()
        
        // Generate ScrollView.
        scrollView.frame = self.view.frame
        
        // Disable ScrollView bounces
        scrollView.bounces = false
        
        // Set the image in UIImage.
        let image = UIImage(named: "vertical.jpeg")!
        
        // Create a UIImageView.
        let imageView = UIImageView()
        
        // Set myImage to the image of imageView.
        imageView.image = image
        
        // Set the value of frame size
        imageView.frame.size = image.size
        
        // Set the aspect ratio of the image.
        imageView.contentMode = .scaleAspectFill
        
        // Add imageView to ScrollView.
        scrollView.addSubview(imageView)
        
        // Set contentSize to ScrollView.
        scrollView.contentSize = imageView.frame.size
        
        return scrollView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Add UIScrollView on view
        self.view.addSubview(self.scrollView)
    }
}