Skip to content

Instantly share code, notes, and snippets.

@daryadariaa
Last active September 9, 2019 10:30
Show Gist options
  • Save daryadariaa/ed166992784239385b83704620e66de3 to your computer and use it in GitHub Desktop.
Save daryadariaa/ed166992784239385b83704620e66de3 to your computer and use it in GitHub Desktop.
import UIKit
protocol ChangedTitleDelegate {
func titleChanged(title: String)
}
class DetailViewController: UIViewController {
var delegate : ChangedTitleDelegate?
var itemTitle = ""
var itemDescription = ""
let attributes : [NSAttributedString.Key: Any] = [
.font: UIFont.systemFont(ofSize: 23),
.foregroundColor: UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.5),
]
var attributedTitle: NSAttributedString {
return NSAttributedString(string: itemDescription.convertHtml().string, attributes: attributes)
}
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
delegate?.titleChanged(title: itemTitle)
setupNavBar()
tableView.rowHeight = UITableView.automaticDimension
}
func setupNavBar() {
title = itemTitle
navigationItem.largeTitleDisplayMode = .always
}
}
// MARK: - Extensions
extension DetailViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.attributedText = attributedTitle
cell.textLabel?.numberOfLines = 0
return cell
}
}
extension String {
func convertHtml() -> NSAttributedString {
guard let data = data(using: .utf8) else { return NSAttributedString() }
do {
return try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)
} catch { return NSAttributedString() }
}
}
import UIKit
import CoreData
class NewsViewController: UIViewController {
private var items = [Item]()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var isLoading = false
@IBOutlet weak var segmentedControl: UISegmentedControl!
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 120.0
fetchData()
tableView.reloadData()
}
// MARK: - Fetching data
private func fetchData() {
let parser = FeedParser()
let queue = DispatchQueue.global(qos: .background)
let newsURL = url(category: self.segmentedControl.selectedSegmentIndex)
isLoading = true
queue.async {
parser.parseFeed(url: newsURL) { (rssItems) in
for item in rssItems {
let newItem = Item(context: self.context)
newItem.title = item.title
newItem.fdescription = item.description
newItem.category = item.category
self.items.append(newItem)
}
self.saveItems()
DispatchQueue.main.async {
self.isLoading = false
self.tableView.reloadData()
}
}
}
}
@IBAction func switchTableViewAction(_ sender: UISegmentedControl) {
fetchData()
tableView.reloadData()
}
private func url(category: Int) -> String {
let urlString: String
switch category {
case 0: urlString = "http://feeds.reuters.com/reuters/businessNews"
case 1: urlString = "http://feeds.reuters.com/reuters/entertainment"
default: urlString = ""
}
return urlString
}
// MARK: - Model manipulation methods
func saveItems() {
do { try context.save() }
catch { print("Error saving items: \(error)") }
}
func loadItems() {
let request : NSFetchRequest<Item> = Item.fetchRequest()
do { items = try context.fetch(request) }
catch { print("Error fetching data from context: \(error)") }
}
}
// MARK: - Extensions
extension NewsViewController: UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
switch segmentedControl.selectedSegmentIndex {
case 0: return 1
case 1: return 2
default: return 1
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isLoading {
return 1
} else {
return items.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if isLoading {
let cell = tableView.dequeueReusableCell(withIdentifier:
"LoadingCell", for: indexPath)
let spinner = cell.viewWithTag(100) as!
UIActivityIndicatorView
spinner.startAnimating()
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! NewsTableViewCell
let item = items[indexPath.item]
cell.item = item
return cell
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = items[indexPath.row]
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "DetailViewController") as! DetailViewController
vc.itemTitle = item.title!
vc.itemDescription = item.fdescription!
navigationController?.pushViewController(vc, animated: true)
tableView.deselectRow(at: indexPath, animated: true)
}
}
class MainTableViewController: UITableViewController, ChangedTitleDelegate {
var timer = Timer()
var timeString = ""
var titleLabel : String?
override func viewDidLoad() {
super.viewDidLoad()
timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(timeNowString), userInfo: nil, repeats: true)
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
switch indexPath.row {
case 0:
cell.textLabel?.text = "My Name"
cell.detailTextLabel?.text = "Daria"
case 1:
cell.textLabel?.text = "Date and time"
cell.detailTextLabel?.text = timeNowString() as String
case 2:
cell.textLabel?.text = titleLabel
cell.detailTextLabel?.text = ""
default:
break
}
return cell
}
@objc func timeNowString() -> NSString {
let date = NSDate()
let formatter = DateFormatter()
formatter.locale = NSLocale(localeIdentifier:"en_US") as Locale
formatter.dateFormat = "MM/dd/yyyy, HH:mm:ss"
let timeString = formatter.string(from: date as Date)
return timeString as NSString
}
func titleChanged(title: String) {
titleLabel = title
}
}
import Foundation
import UIKit
import CoreData
struct RSSItem {
var title : String
var link : String
var description : String
var category : String
var pubDate : String
}
class FeedParser: NSObject, XMLParserDelegate
{
private var rssItems: [RSSItem] = []
private var currentElement = ""
private var currentTitle: String = "" {
didSet {
currentTitle = currentTitle.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
}
}
private var currentLink: String = "" {
didSet {
currentLink = currentLink.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
}
}
private var currentDescription: String = "" {
didSet {
currentDescription = currentDescription.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
}
}
private var currentCategory: String = "" {
didSet {
currentCategory = currentCategory.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
}
}
private var currentPubDate: String = "" {
didSet {
currentPubDate = currentPubDate.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
}
}
private var parserCompletionHandler: (([RSSItem]) -> Void)?
func parseFeed(url: String, completionHandler: (([RSSItem]) -> Void)?)
{
self.parserCompletionHandler = completionHandler
let request = URLRequest(url: URL(string: url)!)
let urlSession = URLSession.shared
let task = urlSession.dataTask(with: request) { (data, response, error) in
guard let data = data else {
if let error = error {
print("Failure! \(error.localizedDescription)")
} else {
print("Success! \(response!)")
}
return
}
let parser = XMLParser(data: data)
parser.delegate = self
parser.parse()
}
task.resume()
}
// MARK: - XML Parser Delegate
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:])
{
currentElement = elementName
if currentElement == "item" {
currentTitle = ""
currentLink = ""
currentDescription = ""
currentCategory = ""
currentPubDate = ""
}
}
func parser(_ parser: XMLParser, foundCharacters string: String)
{
switch currentElement {
case "title" : currentTitle += string
case "link" : currentLink += string
case "description" : currentDescription += string
case "category" : currentCategory += string
case "pubDate" : currentPubDate += string
default: break
}
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?)
{
if elementName == "item" {
let rssItem = RSSItem(title: currentTitle, link: currentLink, description: currentDescription, category: currentCategory, pubDate: currentPubDate)
self.rssItems.append(rssItem)
}
}
func parserDidEndDocument(_ parser: XMLParser) {
parserCompletionHandler?(rssItems)
}
func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error)
{
print("Failure! \(parseError.localizedDescription)")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment