I show an error message when I parse XML - ios

I am new to Swift programming. I have 2 classes to parse RSS and show the datas. It's named ParseRSSFeed and DetailVC. But I can't see the datas in TableView when I want to parse.
But if I call methods of XMLParserDelegate in DetailVC, it works. Probably I did a mistake while calling the methods from another class.
My code is as below.
What did I overlook?
ParseRSSFeeds class to parse XML
import UIKit
class ParseRSSFeeds: XMLParser, XMLParserDelegate{
var parser = XMLParser()
var news = NSMutableArray()
var elements = NSMutableDictionary()
var element = NSString()
var header = NSMutableString()
var link = NSMutableString()
var desc = NSMutableString()
var date = NSMutableString()
func parseFromUrl(){
news = []
parser = XMLParser(contentsOf: NSURL(string: "https://www.wired.com/feed/rss")! as URL)!
parser.delegate = self
parser.parse()
}
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
element = elementName as NSString
if (elementName as NSString) .isEqual(to: "item") {
elements = NSMutableDictionary()
elements = [:]
header = NSMutableString()
header = ""
link = NSMutableString()
link = ""
desc = NSMutableString()
desc = ""
date = NSMutableString()
date = ""
}
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
if element .isEqual(to: "title"){
header.append(string)
}else if element .isEqual(to: "link"){
link.append(string)
}else if element .isEqual(to: "description"){
desc.append(string)
}else if element .isEqual(to: "pubDate") {
date.append(string)
}
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
if (elementName as NSString) .isEqual(to: "item") {
if !header .isEqual(nil) {
elements.setObject(header, forKey: "title" as NSCopying)
}
if !link .isEqual(nil) {
elements.setObject(link, forKey: "link" as NSCopying)
}
if !desc .isEqual(nil) {
elements.setObject(desc, forKey: "description" as NSCopying)
}
if !date .isEqual(nil) {
elements.setObject(date, forKey: "pubDate" as NSCopying)
}
news.add(elements)
}
}
}
DetailVC (It includes table view to show RSS feeds.)
import UIKit
class DetailVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tblNews: UITableView!
let parser = ParseRSSFeeds()
override func viewDidLoad() {
super.viewDidLoad()
ParseRSSFeeds().parseFromUrl()
tblNews.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return parser.news.count - parser.news.count + 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tblNews.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if cell .isEqual(NSNull.self) {
cell = Bundle.main.loadNibNamed("cell", owner: self, options: nil)?[0] as! UITableViewCell
}
cell.textLabel?.text = (parser.news.object(at: indexPath.row) as AnyObject).value!(forKey: "title") as? String
cell.detailTextLabel?.text = (parser.news.object(at: indexPath.row) as AnyObject).value!(forKey: "description") as? String
return cell
}
}

You have two ParseRSSFeeds instances, the parser property and the one you create in viewDidLoad. So, viewDidLoad is creating a second instance of ParseRSSFeeds, requesting and parsing the response, and then discarding those results, leaving the separate parser property untouched.
You should instead have viewDidLoad reference the parser property rather than creating new instance of ParseRSSFeeds:
override func viewDidLoad() {
super.viewDidLoad()
parser.parseFromUrl()
...
}

Related

XML parsing in swift not working, no errors

I am trying to parse a xml file direct from a URL the code has no errors, and the app opens fine but the tableview is empty. here is the link and the code I have used, if I can get some guidance it would be greatly appreciated.
I initially built this through a tutorial (just learning the ropes)
import UIKit
class firecallViewController: UIViewController, NSXMLParserDelegate{
#IBOutlet var tbData: UITableView?
var parser = NSXMLParser()
var posts = NSMutableArray()
var elements = NSMutableDictionary()
var element = NSString()
var title1 = NSMutableString()
var date = NSMutableString()
override func viewDidLoad()
{
super.viewDidLoad()
self.beginParsing()
}
func beginParsing()
{
posts = []
parser = NSXMLParser(contentsOfURL:(NSURL(string:"https://example.com/bushfirealert/bushfireAlert.xml"))!)!
parser.delegate = self
parser.parse()
tbData!.reloadData()
}
//XMLParser Methods
func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String])
{
element = elementName
if (elementName as NSString).isEqualToString("item")
{
elements = NSMutableDictionary()
elements = [:]
title1 = NSMutableString()
title1 = ""
date = NSMutableString()
date = ""
}
}
func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?)
{
if (elementName as NSString).isEqualToString("item") {
if !title1.isEqual(nil) {
elements.setObject(title1, forKey: "title")
}
if !date.isEqual(nil) {
elements.setObject(date, forKey: "date")
}
posts.addObject(elements)
}
}
func parser(parser: NSXMLParser, foundCharacters string: String)
{
if element.isEqualToString("title") {
title1.appendString(string)
} else if element.isEqualToString("pubDate") {
date.appendString(string)
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return posts.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell")!
if(cell.isEqual(NSNull)) {
cell = NSBundle.mainBundle().loadNibNamed("Cell", owner: self, options: nil)[0] as! UITableViewCell;
}
cell.textLabel?.text = posts.objectAtIndex(indexPath.row).valueForKey("title") as! NSString as String
cell.detailTextLabel?.text = posts.objectAtIndex(indexPath.row).valueForKey("date") as! NSString as String
return cell as UITableViewCell
}
}
Updated answer
You told me in the comments that you don't have to use NSXMLParser.
In this case, I have an easy solution for your parsing: use CheatyXML, a very simple library.
First, follow the easy install intructions.
Then make a parser with your URL:
import CheatyXML
let feedUrl = NSURL(string: "https://example.com/bushfirealert/bushfireAlert.xml")!
let parser = XMLParser(contentsOfURL: feedUrl)
And safely unwrap all values as if you were subscripting dictionaries, and use the .string property to get the string fields contents.
Like this:
if let parser = parser,
channel = parser["channel"],
title = channel["title"].string,
link = channel["link"].string,
description = channel["description"].string,
docs = channel["docs"].string,
generator = channel["generator"].string {
print(title)
print(link)
print(description)
print(docs)
print(generator)
}
Result:
QFES Current Incidents
http://bneags01.desqld.internal/publicfeed/PublicRssFeed.aspx
QFES Current Incidents
http://www.rssboard.org/rss-specification
Argotic Syndication Framework
Now instead of my series of print you call a method of yours to populate your variables and then you reload the table view, and you're set.
Old answer
NSXMLParser works asynchronously, so when you reload your table in beginParsing(), the data is not parsed yet.
You need to reload the table when the parser has finished parsing.
Luckily, there's a callback for that.
Remove tbData!.reloadData() from beginParsing() and add this delegate method to your view controller instead:
func parserDidEndDocument(parser: NSXMLParser) {
tbData!.reloadData()
}

Passing data from TableViewController to parser

During my app development I've encountered a specific problem.
I've a database which contains following columns: Dossier_Title, Dossier_Name, Dossier_Category and Dossier_Description. The Description is uniqe for every Dossier.
First of all I'm calling my WebService which selects unique Dossier_Title and forms an xml page. After that app parse this page and forms a number of unique cells in table View. Also it forms an array which consists of Dossier_Title and Dossier_category.
Now I want to form a new tableView which would consist of Dossier_Name and Dossier_Description based on the Dossier_Category I've achieved on previous step. For this I want to call a new WebService and parse it using that Category as condition.
My question is: how can I pass Dossier_category to my second parser so I can use it as condition?
Here is my first parser code I assume the second one would be pretty much the same with addition of some new conditions
class DossierParser: NSObject, NSXMLParserDelegate {
var parser = NSXMLParser()
var feeds = NSMutableArray()
var elements = NSMutableDictionary()
var element = NSString()
var ftitle = NSMutableString()
var link = NSMutableString()
var fdescription = NSMutableString()
var fdate = NSMutableString()
var fcategory = NSMutableString()
// initilise parser
/*
func initWithURL(url :NSURL) -> AnyObject {
startParse(url)
return self
}
*/
init(URL: NSURL){
super.init()
startParse(URL)
}
func startParse(url :NSURL) {
feeds = []
parser = NSXMLParser(contentsOfURL: url)!
parser.delegate = self
parser.shouldProcessNamespaces = false
parser.shouldReportNamespacePrefixes = false
parser.shouldResolveExternalEntities = false
parser.parse()
}
func allFeeds() -> NSMutableArray {
return feeds
}
func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
self.element = elementName
if self.element == "News" {
elements = NSMutableDictionary()
elements = [:]
ftitle = NSMutableString()
ftitle = ""
fdescription = NSMutableString()
fdescription = ""
fdate = NSMutableString()
fdate = ""
fcategory = NSMutableString()
fcategory = ""
}
}
func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
if (elementName as NSString).isEqualToString("News") {
if ftitle != "" {
elements.setObject(ftitle, forKey: "DosNum")
}
if fcategory != "" {
elements.setObject(fcategory, forKey: "Dossier_number")
}
if fdate != "" {
elements.setObject(fdate, forKey: "Date_Text")
}
feeds.addObject(elements)
}
}
func parser(parser: NSXMLParser, foundCharacters string: String?) {
if element.isEqualToString("DosNum") {
ftitle.appendString(string!)
}else if element.isEqualToString("Date_Text") {
fdate.appendString(string!)
}else if element.isEqualToString("Dossier_number"){
fcategory.appendString(string!)
}
}
And here is my first TableView code.
var myFeed : NSArray = []
var url: NSURL = NSURL()
override func viewDidLoad() {
super.viewDidLoad()
// Cell height.
self.tableView.rowHeight = 70
self.tableView.dataSource = self
self.tableView.delegate = self
//url = NSURL(string: "https://www.kpmg.com/_layouts/feed.aspx?xsl=1&web=/RU/ru/IssuesAndInsights/RSSFeeds&page=207b36b2-20f7-407f-a9ec-a09f191fd84b&wp=9810a349-6086-489d-ad03-40c06f6669f6")!
//url = NSURL(string: "http://www.skysports.com/rss/0,20514,11661,00.xml")!
// url = NSURL(scheme: "https", host: "www.kpmg.com", path: "/_layouts/feed.aspx?xsl=1&web=/RU/ru/IssuesAndInsights/RSSFeeds&page=207b36b2-20f7-407f-a9ec-a09f191fd84b&wp=9810a349-6086-489d-ad03-40c06f6669f6")!
//(scheme: "http", host: "10.207.203.216", path: "/AppWebservice/Service1.asmx/getNewsData")!
url = NSURL(string: "http://10.207.206.74/AppWebservice/Service1.asmx/getUniqDossier")!
// Call custom function.
loadRss(url);
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationItem.title = ""
let backImg:UIImage! = UIImage(named: "backPicture.png")
self.navigationItem.backBarButtonItem =
UIBarButtonItem(image:backImg, style:.Plain, target:self, action:nil);
let navBgImage:UIImage = UIImage(named: "express.png")!
self.navigationController?.navigationBar.setBackgroundImage(navBgImage, forBarMetrics: .Default)
}
func loadRss(data: NSURL) {
let myParser = DossierParser(URL: data)
myFeed = myParser.feeds
tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "openPage" {
let indexPath: NSIndexPath = self.tableView.indexPathForSelectedRow!
let selectedFTitle: String = myFeed[indexPath.row].objectForKey("DosNum") as! String
let selectedFContent: String = myFeed[indexPath.row].objectForKey("Dossier_number") as! String
// Instance of our feedpageviewcontrolelr
let fpvc: FeedPageViewController = segue.destinationViewController as! FeedPageViewController
fpvc.selectedFeedTitle = selectedFTitle
fpvc.selectedFeedFeedContent = selectedFContent
}
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myFeed.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
let chevron = UIImage(named: "Next4.png")
cell.accessoryType = .DisclosureIndicator
cell.accessoryView = UIImageView(image: chevron!)
cell.textLabel?.textColor = UIColor.blackColor()
// Feeds dictionary.
var dict : NSDictionary! = myFeed.objectAtIndex(indexPath.row) as! NSDictionary
// Set cell properties.
cell.textLabel?.text = myFeed.objectAtIndex(indexPath.row).objectForKey("DosNum") as? String
cell.detailTextLabel?.text = myFeed.objectAtIndex(indexPath.row).objectForKey("Date_text") as? String
return cell
}
I would appreciate any sort of help. My guessing there should be easier way around it, but I don't know it, so if someone has suggestion it would be nice!
Thanks!
I believe you would want to retain an instance of fCategory and pass it to the second parser class via init.
The second parser class should have the following to allow for the fcategory to be passed in and stored locally for use by the parser.
let fcategory = NSMutableString()
let URL = NSURL
init(URL: NSURL, category: String){
super.init()
self.URL = URL
self.fcategory = category
self.startParse(URL, fcategory)
}

tableView RSS feed Swift 2.0

I'm trying to create a rss-feed app with a UITableView to show the RSS-content(title and description). The NSXMLparser works fine, it can get all the information from the website. However I seem to have a problem with getting the information into the UITableView and I can't seem to find where I did wrong!
I've set the UItableView's cell's reuseIdentifier to Cell.
The titlesTableView is connected as shown in the code as an IBOutlet.
I'm sorry for the long code, but I don't know where it went wrong.
import UIKit
class SecondViewController: UIViewController, NSXMLParserDelegate {
var xmlParser: NSXMLParser!
var entryTitle: String!
var entryDescription: String!
var entryLink: String!
var currentParsedElement:String! = String()
var entryDictionary: [String:String]! = Dictionary()
var entriesArray:[Dictionary<String, String>]! = Array()
#IBOutlet var titlesTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.titlesTableView.estimatedRowHeight = 40.0
let urlString = NSURL(string: "http://www.skeppsfast.se/aktuellt.feed?type=rss")
let rssUrlRequest:NSURLRequest = NSURLRequest(URL:urlString!)
let queue:NSOperationQueue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(rssUrlRequest, queue: queue) {
(response, data, error) -> Void in
self.xmlParser = NSXMLParser(data: data!)
self.xmlParser.delegate = self
self.xmlParser.parse()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: NSXMLParserDelegate
func parser(parser: NSXMLParser!,
didStartElement elementName: String!,
namespaceURI: String!,
qualifiedName: String!,
attributes attributeDict: [String : String]!){
if elementName == "title"{
entryTitle = String()
currentParsedElement = "title"
}
if elementName == "description"{
entryDescription = String()
currentParsedElement = "description"
}
if elementName == "link"{
entryLink = String()
currentParsedElement = "link"
}
}
func parser(parser: NSXMLParser!,
foundCharacters string: String!){
if currentParsedElement == "title"{
entryTitle = entryTitle + string
}
if currentParsedElement == "description"{
entryDescription = entryDescription + string
}
if currentParsedElement == "link"{
entryLink = entryLink + string
}
}
func parser(parser: NSXMLParser!,
didEndElement elementName: String!,
namespaceURI: String!,
qualifiedName qName: String!){
if elementName == "title"{
entryDictionary["title"] = entryTitle
}
if elementName == "link"{
entryDictionary["link"] = entryLink
}
if elementName == "description"{
entryDictionary["description"] = entryDescription
entriesArray.append(entryDictionary)
}
}
func parserDidEndDocument(parser: NSXMLParser!){
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.titlesTableView.reloadData()
})
}
// MARK: UITableViewDataSource
func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
var cell:UITableViewCell! = tableView.dequeueReusableCellWithIdentifier("Cell")as UITableViewCell!
if (nil == cell){
cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Cell")
}
cell!.textLabel?.text = entriesArray[indexPath.row]["title"]
cell!.textLabel?.numberOfLines = 0
cell!.detailTextLabel?.text = entriesArray[indexPath.row]["description"]
cell!.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
return cell
}
func tableView(tableView: UITableView,
numberOfRowsInSection section: Int) -> Int{
return entriesArray.count
}
}
Turns out I hadn't add the UITableViewDataSource protocol to the class (stupid me).
Should have been:
class SecondViewController: UIViewController, NSXMLParserDelegate, UITableViewDataSource {
My confidence just dropped a ton after this taking me about a day and a half to solve.

TableView shows blank cells while parsing XML

I worked on my XML feed reader with a TableViewControllerand it was working perfectly but as it's not flexible, I wanted to move to another ViewController which includes `TableView'. However, even though I think I made the connections right (creating IBOutlet from tableview, using the right objects in custom cell in CustomCell class etc), it shows blank cells.
You can find the code below. I am using CustomCell class to create my custom cell. What am I missing here?
class originalViewController: UIViewController,UITableViewDelegate, NSXMLParserDelegate, UIScrollViewDelegate{
#IBOutlet var tableView: UITableView!
var parser = NSXMLParser()
var feeds = NSMutableArray()
var elements = NSMutableDictionary()
var element = NSString()
var ftitle = NSMutableString?()
var link = NSMutableString?()
var fdescription = NSMutableString?()
var fIMG = NSMutableString?()
var fAuthor = NSMutableString?()
var fDate = NSMutableString?()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Cell")
feeds = []
var url = NSURL(string: "http://www.marketoloji.com/?feed=rss2")
parser = NSXMLParser(contentsOfURL: url)!
parser.delegate = self
parser.shouldProcessNamespaces = false
parser.shouldReportNamespacePrefixes = false
parser.shouldResolveExternalEntities = false
parser.parse()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "openPage" {
var indexPath: NSIndexPath = self.tableView.indexPathForSelectedRow()!
let wvc: WebViewController = segue.destinationViewController as WebViewController
var selectedURL: String = feeds[indexPath.row].objectForKey("link") as String
selectedURL = selectedURL.stringByReplacingOccurrencesOfString(" ", withString: "")
selectedURL = selectedURL.stringByReplacingOccurrencesOfString("\n", withString: "")
wvc.selectedLink = selectedURL
}
}
func parser(parser: NSXMLParser!, didStartElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!, attributes attributeDict: [NSObject : AnyObject]!) {
element = elementName
if (element as NSString).isEqualToString("item"){
elements = NSMutableDictionary.alloc()
elements = [:]
ftitle = ""
link = ""
fdescription = ""
fAuthor = ""
fDate = ""
fIMG = ""
} else if element.isEqualToString("enclosure") {
var imgLink = attributeDict["url"] as String
imgLink = imgLink.stringByReplacingOccurrencesOfString(" ", withString: "")
imgLink = imgLink.stringByReplacingOccurrencesOfString("\n", withString: "")
fIMG?.appendString(imgLink)
println(imgLink)
}
}
func parser(parser: NSXMLParser!, didEndElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!){
if (elementName as NSString).isEqualToString("item"){
if ftitle != nil {
elements.setObject(ftitle!, forKey: "title")
}
if link != nil {
elements.setObject(link!, forKey: "link")
}
if fdescription != nil {
elements.setObject(fdescription!, forKey: "description")
}
if fAuthor != nil {
elements.setObject(fAuthor!, forKey: "creator")
}
if fDate != nil {
elements.setObject(fDate!, forKey: "date")
}
if fIMG != nil {
elements.setObject(fIMG!, forKey: "imageLink")
}
feeds.addObject(elements)
}
}
func parser(parser: NSXMLParser!, foundCharacters string: String!) {
if element.isEqualToString("title") {
ftitle?.appendString(string)
} else if element.isEqualToString("link") {
link?.appendString(string)
} else if element.isEqualToString("description") {
fdescription?.appendString(string)
} else if element.isEqualToString("dc:creator") {
fAuthor?.appendString(string)
} else if element.isEqualToString("pubDate") {
fDate?.appendString(string)
}
}
func parserDidEndDocument(parser: NSXMLParser!) {
self.tableView.reloadData()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//let cell: CustomCell = tableView.dequeueReusableCellWithIdentifier("Cell") as CustomCell
let cell:CustomCell = self.tableView.dequeueReusableCellWithIdentifier("Cell") as CustomCell
cell.setCell(feeds.objectAtIndex(indexPath.row).objectForKey("title") as String, fDescription: feeds.objectAtIndex(indexPath.row).objectForKey("description") as String, fAuthor: feeds.objectAtIndex(indexPath.row).objectForKey("creator") as String, fDate: feeds.objectAtIndex(indexPath.row).objectForKey("date") as String, fImage: feeds.objectAtIndex(indexPath.row).objectForKey("imageLink") as String)
//cell.backgroundColor = UIColor.clearColor()
return cell
}
}
Figured out that I didnt connect the delegate and datasource of the table to the view controller, that was the main problem.

Pull To Refresh a table view in SWIFT

I am totally new to SWIFT and to developing in general. I am currently building an RSS news feed to hone my (very limited) skills. I am basically parsing an RSS feed from a random news channel and then storing the titles in a simple table view.
I am trying to implement UIPullToRefresh using SWIFT, and truth be told I am kinda stuck! I have written the following code. As you can see I have added the necessary code to my viewDidLoad method. At this point the refresh spinner works well but I am now wondering what code is needed in my "refresh function" to actually refresh my table view.
I know this may seem trivial to most of you guys, but i am fairly new to this and i have been pulling my hair for the last 12 hours ... so anything would probably help at this point.
Thanks for your help!
import UIKit
class BRTableViewController: UITableViewController, NSXMLParserDelegate {
var parser: NSXMLParser = NSXMLParser()
var blogPosts: [BlogPost] = []
var postTitle: String = String()
var postLink: String = String()
var postDate: String = String()
var eName: String = String()
override func viewDidLoad() {
super.viewDidLoad()
let url:NSURL = NSURL(string: "http://rt.com/rss/")!
parser = NSXMLParser(contentsOfURL: url)!
parser.delegate = self
parser.parse()
// pull to refresh the table view
refreshControl!.attributedTitle = NSAttributedString(string: "Pull to refresh")
refreshControl!.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)
tableView.addSubview(refreshControl!)
}
func refresh(sender:AnyObject){
let url:NSURL = NSURL(string: "http://rt.com/rss/")!
parser = NSXMLParser(contentsOfURL: url)!
parser.delegate = self
parser.parse()
}
// MARK: - NSXMLParserDelegate methods
func parser(parser: NSXMLParser!, didStartElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!, attributes attributeDict: [NSObject : AnyObject]!) {
eName = elementName
if elementName == "item" {
postTitle = String()
postLink = String()
postDate = String()
}
}
func parser(parser: NSXMLParser!, foundCharacters string: String!) {
let data = string.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
if (!data.isEmpty) {
if eName == "title" {
postTitle += data
} else if eName == "link" {
postLink += data
} else if eName == "pubDate" {
postDate += data
}
}
}
func parser(parser: NSXMLParser!, didEndElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!) {
if elementName == "item" {
let blogPost: BlogPost = BlogPost()
blogPost.postTitle = postTitle
blogPost.postLink = postLink
blogPost.postDate = postDate
blogPosts.append(blogPost)
}
}
override func parser(parser: NSXMLParser!, didEndElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!) {
if elementName == "item" {
self.tableView.reloadData();
self.refreshControl.endRefreshing();
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return blogPosts.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let blogPost: BlogPost = blogPosts[indexPath.row]
cell.textLabel.text = blogPost.postTitle
cell.detailTextLabel?.text = blogPost.postDate.substringToIndex(advance(blogPost.postDate.startIndex, 25))
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 50.0
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "viewpost" {
let selectedRow = tableView.indexPathForSelectedRow()?.row
let blogPost: BlogPost = blogPosts[selectedRow!]
let viewController = segue.destinationViewController as PostViewController
viewController.postLink = blogPost.postLink
}
}
}
I think this fix the issue:
func refresh(sender:AnyObject){
parser = NSXMLParser(contentsOfURL: url)!
parser.delegate = self
parser.parse()
}
This will re-parse the XML and update the blogPosts variable.
Remove the following line in viewDidLoad:
refreshControl = UIRefreshControl()
You should also override the parserDidEndDocument function to include this:
func parserDidEndDocument(parser: NSXMLParser!){
self.tableView.reloadData();
self.refreshControl?.endRefreshing();
}
This will refresh the table view once the parser is done.

Resources