Translate To Preferred Language

Search Obioku's Thoughts

Please Read Today's Featured Post

Things I Would Like To Happen Soon

For all those who believe in speaking ideas into existence and prayer in the universe will return to a person.  I simply want to write a lis...

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: "&#39;", 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")
        var pic = try! ImageCache.init(name: "thumb", cacheDirectoryURL: URL(string: (self.parsed.vidpic?[indexPath.section])!))
        if let savedPic = pic.retrieveImageInMemoryCache(forKey: (self.parsed.vidpic?[indexPath.section])!){
            cell.imageView?.image
        }else {
            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: "&#39;", with:
            "\'").replacingOccurrences(of: "&quot", with: "\"").replacingOccurrences(of: "&amp", with: "&")
        cell.textLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping
        cell.detailTextLabel?.text = parsed.count?[indexPath.section].replacingOccurrences(of: "&#39;", 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 very much for viewing this entry and I hope you are able to return soon to continue to enjoy more of the site.
Please share your thoughts in the comment section.
Be blessed and enjoy life!