//
// 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 = "dev key"
let key = "dev 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: """, with: "\"").replacingOccurrences(of: "&", with: "&")
cell.textLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping
cell.detailTextLabel?.text = self.object.count?[indexPath.section].replacingOccurrences(of: "'", with:
"\'").replacingOccurrences(of: """, with: "\"").replacingOccurrences(of: "&", 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: """, with: "\"").replacingOccurrences(of: "&", 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 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!