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 in Swift (some bugs may occur)

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

import UIKit
//import AVKit
//import WebKit
import SafariServices
//import Kingfisher



//object to collect data from api call
struct SearchData {
    var id: [Int]?
    var vidpic: [String]?
    var highpic: UIImage?
    var titleLabel: [String]?
    var description: [String]?
    var count: [String]?
    var channel: [String]?
    var vidURL: [String]?
    
    //init as empty to prevent "nil"
    init() {
        self.id = [0]
        self.vidpic = [""]
        self.highpic = UIImage.init()
        self.titleLabel = [""]
        self.description = [""]
        self.count = [""]
        self.channel = [""]
        self.vidURL = [""]
        
    }
    
    
}

//test prototype cell
//class LabelCell2: UITableViewCell{
//
//    @IBOutlet weak var secText: UITextView!
//    @IBOutlet weak var secChan: UILabel!
//    @IBOutlet weak var secVid: UIView!
//    @IBOutlet weak var secDate: UILabel!
//    @IBOutlet weak var secBtn: UIButton!
//    @IBOutlet weak var secUrl: UILabel!
//
//
//}


class ViewController: UIViewController ,UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate, SFSafariViewControllerDelegate{//}, UIViewControllerPreviewingDelegate {
    
//    func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
//        guard let select = view1.indexPathForRow(at: location), let cell = view1.cellForRow(at: select) else {
//            return nil
//        }
//
//        //let testVC = storyboard?.instantiateInitialViewController() as! SFSafariViewController
//        //testVC.delegate = self
//
//        //let vc = SFSafariViewController.init(url: URL.init(string: (parsed.vidURL?[select.section])!)!)
//        let vc = storyboard?.instantiateViewController(withIdentifier: "vidPlayer") as! VideoController
//        vc.delegate = self
//        vc.preferredContentSize = CGSize.init(width: 100, height: 200)
//        previewingContext.sourceRect = cell.frame
//        return vc
//
//    }
//
//    func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
////        let navVC = UINavigationController.init(rootViewController: viewControllerToCommit)
////        viewControllerToCommit.present(navVC, animated: true)
//        navigationController?.show(viewControllerToCommit, sender: self)
//    }
//
//    func seeViewController(_ controller: UIViewController, didSelect action: UIPreviewAction,for previewedController: UIViewController){
//
//    }
    
    //declare variables
    var parsed = SearchData()
    var maxResults: Int!
    var load = 0
    
    //view outlets
    @IBOutlet weak var search: UISearchBar!
    @IBOutlet weak var view1: UITableView!
    @IBOutlet weak var segControl: UISegmentedControl!
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        //assign delegates, datasource and register cell
        self.view1.dataSource = self
        self.view1.delegate = self
        self.view1.register(UITableViewCell.self, forCellReuseIdentifier: "custom")
        self.search.delegate = self
        //self.view1.rowHeight = 172
        self.search.placeholder = "Search YouTube"
        self.search.tintColor = UIColor.red
        self.segControl.tintColor = UIColor.red
        self.load = 0
//        if traitCollection.forceTouchCapability == .available {
//            registerForPreviewing(with: self, sourceView: self.view)
//        }
}
    
    func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
        //if text blank display alert
        if searchBar.text == nil || searchBar.text == "" {
            let alert = UIAlertController.init(title: "Search Text is Blank", message: "Please Enter Value", preferredStyle: .alert)
            alert.addAction(UIAlertAction.init(title: "Re-enter", style: .default))
            self.present(alert, animated: true)
        }else{
            
            //clear object with each call
            parsed = SearchData()
            
            //url components
            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"
            //segment for result amount
            switch segControl.selectedSegmentIndex {
            case 0: maxResults = 10
            case 1: maxResults = 25
            case 2: maxResults = 50
            default: maxResults = 5
            }
            //segment for videos or channels
            switch searchBar.selectedScopeButtonIndex {
            case 0: urlString = "\(string)/search?part=snippet&maxResults=\(maxResults ?? 5)&q=\(entered!)&type=video&videoCaption=closedCaption&key=\(key)"
            case 1: urlString = "\(string)/search?part=snippet&maxResults=\(maxResults ?? 5)&q=\(entered!)&type=channel&key=\(key)"
            default: urlString = "\(string)/activities?part=snippet,contentDetails&home=true"
            }
            let url = URL.init(string: urlString)
            //begin json parsing
            do{
                let data = try Data.init(contentsOf: url!)
                let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! [String: Any]
                //array of dictionaries
                let items = json["items"] as! Array<[String: Any]>
                //parse each index
                for x in 0 ..< maxResults {
                    
                    let id = items[x]["id"] as! [String: Any]
                    var vidId = ""
                    //determine video or channel listing and assign url
                    if searchBar.selectedScopeButtonIndex == 0 {
                        vidId = id["videoId"] as! String
                        parsed.vidURL?.insert("https://www.youtube.com/watch?v=\(vidId)", at: x)
                    }
                    if searchBar.selectedScopeButtonIndex == 1 {
                        vidId = id["channelId"] as! String
                        parsed.vidURL?.insert("https://www.youtube.com/channel/\(vidId)", at: x)
                    }
                    //collect index id, channel, date, title, description and picture
                    parsed.id?.insert(x, at: x)
                    let snippet = items[x]["snippet"] as! [String: Any]
                    parsed.channel?.insert(snippet["channelTitle"] as! String, at: x)
                    parsed.count?.insert(snippet["publishedAt"] as! String, at: x)
                    parsed.titleLabel?.insert(snippet["title"] as! String, at: x)
                    parsed.description?.insert(snippet["description"] as! String, at: x)
                    let thumb = snippet["thumbnails"] as! [String: Any]
                    let image = thumb["high"] as! [String: Any]
                    let link = image["url"] as! String
                    parsed.vidpic?.insert(link, at: x)
                    //print(thumb)
                }
                
            }catch {
                print("Errors from site retrieval")
            }
            //reload table on main thread
            DispatchQueue.main.async {
                self.view1.reloadData()
                self.view1.scrollToRow(at: IndexPath.init(row: 0, section: 0), at: .top, animated: true)
                //self.view1.reloadData()
            }
            
        }
    }
    
    //add title as section header
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        //make video title section header
        if parsed.count?.count == 0{
            return "Video Titles"
        }else{
            return parsed.titleLabel?[section].replacingOccurrences(of: "'", with:
                "\'").replacingOccurrences(of: "&quot", with: "\"").replacingOccurrences(of: "&amp", with: "&")
        }
        
    }
    
    //table conformance functions
    func numberOfSections(in tableView: UITableView) -> Int {
        //search results as number of section
        if parsed.count?.count == 0{
            return 0
        }else{
            return parsed.count!.count
        }
    }
    
    //when view loads show 1 cell else show the amount requested
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        //one cell per return
        if parsed.count?.count == 0{
            return 0
        }else{
            return 1
        }
    }
    
    //fixed height for cell
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 172.0
    }
    
    //add thumbnail and text to each cell for return results
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "plain", for: indexPath)
        //load image on the main thread
        //let ic = ImageCache.init(name: "pic")
        let test = DispatchQueue.init(label: "gcd", qos: .background, attributes: .concurrent, autoreleaseFrequency: .inherit, target: .global())
        test.async {
            if let url = URL.init(string: (self.parsed.vidpic?[indexPath.section])!){
                let data = try! Data(contentsOf: url)
                  DispatchQueue.main.async {
                    cell.imageView?.image = UIImage(data: data)
                            if self.load == 0{
                                self.view1.reloadData()
                                self.load = 1
                            }
                        
                    }
                
            }
        }
        
        
        
        //remove error ascii conversions from string
        cell.textLabel?.text = parsed.channel?[indexPath.section].replacingOccurrences(of: "'", with:
            "\'").replacingOccurrences(of: "&quot", with: "\"").replacingOccurrences(of: "&amp", with: "&")
        cell.textLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping
        cell.detailTextLabel?.text = parsed.count?[indexPath.section].replacingOccurrences(of: "'", with:
            "\'").replacingOccurrences(of: "&quot", with: "\"").replacingOccurrences(of: "&amp", with: "&")
        cell.detailTextLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping
        
        cell.layer.borderWidth = 3.0
        cell.layer.borderColor = UIColor.black.cgColor
        
        
        return cell
    }
    
    //display link when cell is selected
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        //open video in safari for row selected
        //let seen = UIApplication.shared.keyWindow
        if let url = URL.init(string: (parsed.vidURL?[indexPath.section])!){
            let vc = SFSafariViewController.init(url: url)
            vc.delegate = self
            vc.preferredContentSize = CGSize.init(width: 100, height: 200)
            vc.modalTransitionStyle = .crossDissolve
            //UIView.animate(withDuration: 1.5) {
                //vc.view.frame = self.view.bounds
                self.present(vc, animated: true)
            //}
            
            
        }

    }
    
    func saveImage(_ image: URL) -> UIImage{
        var pic = UIImage()
        URLSession.shared.dataTask(with: image) { (data, response, error) in
            DispatchQueue.main.async {
                pic =  UIImage.init(data: data!) ?? UIImage.init(named: "exe")!
            }
            }.resume()
        
        return pic
    }
    
}








No comments:

Post a Comment

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