Translate To Preferred Language

Search ObiokusThoughts

Please Read Today's Featured Post

Alliteration Ere Zeitgeist

Actually ask archaic adult Broadband boy baked bad batch Cold case cant consistently catch Dawn developed dusk do-over Enact emerge...

Template for YouTube API Request With Programmatic Storyboard And Cocoapods in Swift (some bugs may occur)

//
//  ViewController.swift
//  Tutorial7
//
//  Created by Obioku Bassey Obotette on 4/25/19.
//  Copyright © 2019 Obioku Bassey Obotette. All rights reserved.
//

import UIKit
import Alamofire
import Kingfisher
import SwiftyJSON
import Realm
import SafariServices



class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate, SFSafariViewControllerDelegate {

    //struct for youtube data
    struct ParseData {
        
        var id: [Int]?
        var vidpic: [URL]?
        var highpic: [UIImage]?
        var titleLabel: [String]?
        var description: [String]?
        var count: [String]?
        var channel: [String]?
        var vidURL: [URL]?
        
        //init as empty to prevent "nil"
        init() {
            self.id = [0]
            self.vidpic = [URL.init(string: "https://www.youtube.com")] as? [URL]
            self.highpic = [UIImage.init()]
            self.titleLabel = [""]
            self.description = [""]
            self.count = [""]
            self.channel = [""]
            self.vidURL = [URL.init(string: "https://www.youtube.com")] as? [URL]
            
        }
    }
    
    //declare variables
    var object = ParseData()
    let search = UISearchBar.init()
    let scope = UISegmentedControl()
    let segment = UISegmentedControl()
    let table = UITableView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Do any additional setup after loading the view.
        self.view.backgroundColor = UIColor.black
        //Search Bar Features
        search.delegate = self
        search.frame = CGRect.init(x: 0, y: 30, width: self.view.bounds.width, height: 60)
        search.searchBarStyle = .default
        search.returnKeyType = .search
        search.barTintColor = UIColor.red
        search.placeholder = "Search YouTube"
        search.isUserInteractionEnabled = true
        search.isMultipleTouchEnabled = true
        view.addSubview(search)
        
        //Scope and Segment Control Features
        scope.frame = CGRect.init(x: 0, y: 90, width: self.view.bounds.width, height: 30)
        scope.tintColor = UIColor.red
        scope.backgroundColor = UIColor.black
        scope.insertSegment(withTitle: "Videos", at: 0, animated: true)
        scope.insertSegment(withTitle: "Channels", at: 1, animated: true)
        scope.selectedSegmentIndex = 0
        scope.isUserInteractionEnabled = true
        scope.isMultipleTouchEnabled = true
        view.addSubview(scope)
        
        segment.frame = CGRect.init(x: 0, y: 120, width: self.view.bounds.width, height: 30)
        segment.tintColor = UIColor.red
        segment.backgroundColor = UIColor.black
        segment.insertSegment(withTitle: "10", at: 0, animated: true)
        segment.insertSegment(withTitle: "25", at: 1, animated: true)
        segment.selectedSegmentIndex = 0
        segment.isUserInteractionEnabled = true
        segment.isMultipleTouchEnabled = true
        view.addSubview(segment)
        
        //Table Features
        table.delegate = self
        table.dataSource = self
        table.frame = CGRect.init(x: 0, y: 150, width: self.view.bounds.width, height: self.view.bounds.height - 150)
        table.register(UITableViewCell.self, forCellReuseIdentifier: "cellID")
        table.register(UITableViewHeaderFooterView.self, forHeaderFooterViewReuseIdentifier: "headerID")
        table.isUserInteractionEnabled = true
        table.isScrollEnabled = true
        table.isSpringLoaded = true
        table.scrollsToTop = true
        table.flashScrollIndicators()
        table.backgroundColor = UIColor.black
        table.sectionIndexTrackingBackgroundColor = UIColor.red
        table.sectionIndexBackgroundColor = UIColor.red
        table.sectionIndexColor = UIColor.red
        table.separatorColor = UIColor.red
        view.addSubview(table)
        
        
        
    }
    
    //event for search entry
    func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
        //print("Search Bar clicked")
        if searchBar.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" {
            let alert = UIAlertController.init(title: "Blank Search Term", message: "Please Enter Value And Try Again", preferredStyle: .alert)
            let action = UIAlertAction.init(title: "Return", style: .cancel)
            alert.addAction(action)
            self.present(alert, animated: true)
        }else{
            //reset array properties with each search
            self.object = ParseData()
            DispatchQueue.main.async {
                self.table.reloadData()
            }
            var i = 0
            //url components
            var numResults = 0
            var urlString = ""
            let string = "https://www.googleapis.com/youtube/v3"
            let entered = searchBar.text?.replacingOccurrences(of: " ", with: "+")
            //let key = "API_KEY"
            let key = "API_KEY"
            
            //store amount of returns
            switch self.segment.selectedSegmentIndex {
            case 0: numResults = 10
            case 1: numResults = 25
            default:
                let alert = UIAlertController.init(title: "Return Amount Not Selected", message: "Please Chose 10 Or 25 And Try Again", preferredStyle: .alert)
                let action = UIAlertAction.init(title: "Return", style: .cancel)
                alert.addAction(action)
                self.present(alert, animated: true)
                
            }
            
            //retrieve segment choice
            switch self.scope.selectedSegmentIndex {
            case 0: urlString = "\(string)/search?part=snippet&maxResults=\(numResults ?? 5)&q=\(entered!)&type=video&videoCaption=closedCaption&key=\(key)"
            case 1: urlString = "\(string)/search?part=snippet&maxResults=\(numResults ?? 5)&q=\(entered!)&type=channel&key=\(key)"
            default:
                let alert = UIAlertController.init(title: "Search Format Not Selected", message: "Please Choose Video Or Channel And Try Again", preferredStyle: .alert)
                let action = UIAlertAction.init(title: "Return", style: .cancel)
                alert.addAction(action)
                self.present(alert, animated: true)
                
            }
            //return JSON with Alamofire
            if let url = URL.init(string: urlString) {
                AF.request(url).validate().responseJSON { (resp) in
                    //Parse with SwiftyJSON
                    let dictionary = JSON(resp.data!).dictionaryValue
                    //determine video or channel listing and assign url
                    for item in dictionary["items"]!.arrayValue {
                        if self.scope.selectedSegmentIndex  == 0 {
                            self.object.vidURL?.insert(URL(string: "https://www.youtube.com/watch?v=\(item["id"]["videoId"].stringValue)")!, at: i)
                        }
                        if self.scope.selectedSegmentIndex  == 1 {
                            self.object.vidURL?.insert(URL(string: "https://www.youtube.com/channel/\(item["id"]["channelId"].stringValue)")!, at: i)
                        }
                        
                        //collect index id, channel, date, title, description and picture
                        self.object.channel?.insert(item["snippet"]["channelTitle"].stringValue, at: i)
                        self.object.count?.insert(item["snippet"]["publishedAt"].stringValue, at: i)
                        self.object.titleLabel?.insert(item["snippet"]["title"].stringValue, at: i)
                        self.object.description?.insert(item["snippet"]["description"].stringValue, at: i)
                        guard let load = URL(string: item["snippet"]["thumbnails"]["high"]["url"].stringValue) else { return }
                        self.object.vidpic?.insert(load, at: i)
                        var thumbnail: UIImageView?
                        let datum = try! Data(contentsOf: load)
                        guard let fin = UIImage(data: datum) else { return }
                        thumbnail?.kf.setImage(with: load)
                        self.object.highpic?.insert(thumbnail?.image! ?? fin, at: i)
                        i += 1
                        
                        //reload returned results
                        DispatchQueue.main.async {
                            self.table.reloadData()
                        }
                    }
                  
                }
                
            }
            
            
            
        }
        
        //self.table.beginUpdates()
        //self.table.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false)
        //self.table.endUpdates()
        //self.table.setContentOffset(CGPoint.zero, animated: true)
        //self.table.scrollRectToVisible(CGRect.init(x: 0, y: 0, width: 1, height: 1), animated: true)
        
    }
    
    //one row per section
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }
    
    //table cell design
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cellID", for: indexPath)
        tableView.dequeueReusableHeaderFooterView(withIdentifier: "headerID")
        //add identifier text to cell labels and image to imageView
        print(indexPath.section)
        cell.textLabel?.text = self.object.channel?[indexPath.section].replacingOccurrences(of: "'", with:
            "\'").replacingOccurrences(of: "&quot", with: "\"").replacingOccurrences(of: "&amp", with: "&")
        cell.textLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping
        cell.detailTextLabel?.text = self.object.count?[indexPath.section].replacingOccurrences(of: "'", with:
            "\'").replacingOccurrences(of: "&quot", with: "\"").replacingOccurrences(of: "&amp", with: "&")
        cell.detailTextLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping
        cell.imageView?.image = self.object.highpic?[indexPath.section]
        return cell
    }
    
    //section header is title of video or channel
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return self.object.titleLabel?[section].replacingOccurrences(of: "'", with:
            "\'").replacingOccurrences(of: "&quot", with: "\"").replacingOccurrences(of: "&amp", with: "&")
    }
    
    //fixed row height
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 170.0
    }
    
    //fized section header height
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 25.0
    }
    
    //give section header red color
    func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
        view.tintColor = UIColor.red
        //view.backgroundColor = UIColor.red

    }
    
    //reverse cell colors
    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        //cell.textLabel?.text = "Cell in section \(indexPath.section) and row \(indexPath.row)"
        cell.backgroundColor = UIColor.black
        cell.textLabel?.textColor = UIColor.white
    }
    
    //number of section depends on returned results
    func numberOfSections(in tableView: UITableView) -> Int {
        
        return self.object.count!.count - 1 ?? 0
    }
    
    //row selected displays video in new view using safari
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let vc = SFSafariViewController.init(url: (self.object.vidURL?[indexPath.section])!)
        vc.delegate = self
        vc.preferredContentSize = CGSize.init(width: 100, height: 200)
        vc.modalTransitionStyle = .crossDissolve
        self.present(vc, animated: true)
    }
    
    
    
}





No comments:

Post a Comment

Thank you for reading.
Please share your thoughts.
Be blessed and enjoy life!