Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialJorge Alvarez
9,330 PointsBlog Reader In Swift
Extracting and representing the json data works with the url provided by treehouse but I do not understand why it does not work with my schools newspaper website so just check out my code and maybe you can help me?
so heres the code!
MasterViewController.swift
import UIKit
class MasterViewController: UITableViewController {
var blogPosts = [BlogPost]()
override func awakeFromNib() {
super.awakeFromNib()
}
override func viewDidLoad() {
super.viewDidLoad()
let blogURL = NSURL(string: "http://whsappleleaf.com/?json=get_recent_posts")
let jsonData = NSData(contentsOfURL: blogURL)
var error: NSError?
let dataDictionary = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &error) as NSDictionary
let blogPostArray: Array<NSDictionary> = dataDictionary.objectForKey("posts") as Array
for bpDictionary:NSDictionary in blogPostArray {
var blogPost = BlogPost(title: bpDictionary["title"] as String)
blogPost.author = bpDictionary["author"] as String
blogPost.thumbnail = bpDictionary["thumbnail"] as String
blogPost.date = bpDictionary["date"] as String
blogPost.url = NSURL(string: bpDictionary["url"] as String)
blogPosts.append(blogPost)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// #pragma mark - Segues
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showDetail" {
let indexPath = self.tableView.indexPathForSelectedRow()
let blogPost = blogPosts[indexPath!.row]
(segue.destinationViewController as DetailViewController).blogPostUrl = blogPost.url
(segue.destinationViewController as DetailViewController).blogPostTitle = blogPost.title
}
}
// #pragma mark - Table View
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]
if blogPost.thumbnail.isEmpty {
let image = UIImage(named: "apple_leaf.png")
cell.imageView?.image = image
} else {
let imageData = NSData(contentsOfURL: blogPost.thumbnailURL())
let image = UIImage(data: imageData)
cell.imageView?.image = image
}
cell.textLabel?.text = blogPost.title
cell.detailTextLabel?.text = "\(blogPost.author) - \(blogPost.formattedDate())"
return cell
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
}
DetailViewController.swift
import UIKit
class DetailViewController: UIViewController {
@IBOutlet var webView : UIWebView! = nil
var blogPostUrl:NSURL = NSURL()
var blogPostTitle = ""
func configureView() {
// Update the user interface for the detail item.
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.title = blogPostTitle
webView.loadRequest(NSURLRequest(URL: blogPostUrl))
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
BlogPost.swift
import UIKit
class BlogPost: NSObject {
var title: String
var author: String = ""
var thumbnail: String = ""
var date: String = ""
var url: NSURL = NSURL()
init(title: String) {
self.title = title
super.init()
}
func thumbnailURL() -> NSURL {
return NSURL.URLWithString(thumbnail)
}
func formattedDate() -> String {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let tempDate = dateFormatter.dateFromString(date)
dateFormatter.dateFormat = "EE MMM, dd"
return dateFormatter.stringFromDate(tempDate!)
}
}
This is the error I am getting
libswiftCore.dylib`swift_dynamicCastObjCClassUnconditional:
0x201ffa0: pushl %ebp
0x201ffa1: movl %esp, %ebp
0x201ffa3: pushl %edi
0x201ffa4: pushl %esi
0x201ffa5: subl $0x10, %esp
0x201ffa8: calll 0x201ffad ; swift_dynamicCastObjCClassUnconditional + 13
0x201ffad: popl %esi
0x201ffae: movl 0x8(%ebp), %edi
0x201ffb1: xorl %eax, %eax
0x201ffb3: testl %edi, %edi
0x201ffb5: je 0x201ffd6 ; swift_dynamicCastObjCClassUnconditional + 54
0x201ffb7: movl 0xc(%ebp), %eax
0x201ffba: movl 0x5587f(%esi), %ecx
0x201ffc0: movl %eax, 0x8(%esp)
0x201ffc4: movl %ecx, 0x4(%esp)
0x201ffc8: movl %edi, (%esp)
0x201ffcb: calll 0x2022c6a ; symbol stub for: objc_msgSend
0x201ffd0: testb %al, %al
0x201ffd2: movl %edi, %eax
0x201ffd4: je 0x201ffdd ; swift_dynamicCastObjCClassUnconditional + 61
0x201ffd6: addl $0x10, %esp
0x201ffd9: popl %esi
0x201ffda: popl %edi
0x201ffdb: popl %ebp
0x201ffdc: retl
0x201ffdd: leal 0xbe05(%esi), %eax
0x201ffe3: movl 0x490a3(%esi), %ecx
0x201ffe9: movl %eax, 0x8(%ecx)
0x201ffec: movl $0x0, 0xc(%ecx)
0x201fff3: int3
0x201fff4: nopw %cs:(%eax,%eax)
Jorge Alvarez
9,330 PointsWalter Somerville
So you think it might be because of NSJSONSerialization returning optionals I think you might be right because as I was debugging I realized that _owner = (AnyObject?)nil and that could be a problem
I just got out of school that is why I took so long to reply
3 Answers
Ravi Shankar
Courses Plus Student 7,823 PointsThe author information is of type dictionary and in the code you are trying to convert a dictionary to string.
blogPost.author = bpDictionary["author"] as String
Try to retrieve the dictionary first then use firstname and lastname to populate the author name. Try println(bpDictionary["author"]) to get some idea on the content.
Hope this helps
Jorge Alvarez
9,330 Pointswhen you say that the author is of type dictionary you mean the author information that is retrieved as json if so are you suggesting to further break down that dictionary to then set it as a string?
Ravi Shankar
Courses Plus Student 7,823 PointsYes if further breakdown the dictionary, you will find string attributes with name as first name and last name.
Jorge Alvarez
9,330 PointsAlright man I will give it a try
Walter Somerville
20,698 PointsWalter Somerville
20,698 PointsI may be wrong, but could it have something to do with NSJSONSerialization returning optionals? I could be wrong about that, but since the casting you do should take care of the "anyobject" return type, it's the only thing I saw that might be a problem.