27_Blog Reader
这个App是用来读取 Official Google Blog 的内容,然后显示出来。
用了新建工程时用了 Master-Detail Application 这个模板。用了Core Data用来存储内容,不过每次启动App还是会删除内容,然后重新下载最新的20条。所以如果没有网络的时候打开不显示内容。
在原工程的基础上,我在Core Data中增加了date这项,为了排列时按照时间排列。获取的内容中有published和updated两个时间,用published好一些。这里只简单的转了String而不是Date类型。
//
// MasterViewController.swift
// Blog Reader
//
// Created by zcdll on 16/1/24.
// Copyright © 2016年 ZC. All rights reserved.
// import UIKit
import CoreData class MasterViewController: UITableViewController, NSFetchedResultsControllerDelegate { var detailViewController: DetailViewController? = nil
var managedObjectContext: NSManagedObjectContext? = nil override func viewDidLoad() {
super.viewDidLoad() let appDel: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate let context: NSManagedObjectContext = appDel.managedObjectContext let url = NSURL(string: "https://www.googleapis.com/blogger/v3/blogs/10861780/posts?key=AIzaSyCxL3Iltcd-oLc-dFUtdDG9TTuJGWilsYw")! let session = NSURLSession.sharedSession() let task = session.dataTaskWithURL(url) { (data, response, error) -> Void in if error != nil { print(error) } else { if let data = data { //print(NSString(data: data, encoding: NSUTF8StringEncoding)) do { let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary if jsonResult.count > 0 { if let items = jsonResult["items"] as? NSArray { let request = NSFetchRequest(entityName: "BlogItems") request.returnsObjectsAsFaults = false do { let results = try context.executeFetchRequest(request) if results.count > 0 { for result in results { context.deleteObject(result as! NSManagedObject) do { try context.save() } catch {} } } } catch { print("Context fetched failed") } for item in items { if let title = item["title"] as? String { if let content = item["content"] as? String { if let date = item["published"] as? String { let updatedDate = date.componentsSeparatedByString("-08:00")[0] print(updatedDate) //print(title)
//print(content) let newPost: NSManagedObject = NSEntityDescription.insertNewObjectForEntityForName("BlogItems", inManagedObjectContext: context) newPost.setValue(title, forKey: "title")
newPost.setValue(content, forKey: "content")
newPost.setValue(updatedDate, forKey: "date") } } } //print(items)
} } } } catch {} } } } task.resume() // Do any additional setup after loading the view, typically from a nib.
if let split = self.splitViewController {
let controllers = split.viewControllers
self.detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController
}
} override func viewWillAppear(animated: Bool) {
self.clearsSelectionOnViewWillAppear = self.splitViewController!.collapsed
super.viewWillAppear(animated)
} override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
} // MARK: - Segues override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showDetail" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let object = self.fetchedResultsController.objectAtIndexPath(indexPath)
let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController
controller.detailItem = object
controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
controller.navigationItem.leftItemsSupplementBackButton = true
}
}
} // MARK: - Table View override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
} override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let sectionInfo = self.fetchedResultsController.sections![section]
return sectionInfo.numberOfObjects
} override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
self.configureCell(cell, atIndexPath: indexPath)
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
} override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
let context = self.fetchedResultsController.managedObjectContext
context.deleteObject(self.fetchedResultsController.objectAtIndexPath(indexPath) as! NSManagedObject) do {
try context.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
//print("Unresolved error \(error), \(error.userInfo)")
abort()
}
}
} func configureCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) {
let object = self.fetchedResultsController.objectAtIndexPath(indexPath)
cell.textLabel!.text = object.valueForKey("title")!.description
} // MARK: - Fetched results controller var fetchedResultsController: NSFetchedResultsController {
if _fetchedResultsController != nil {
return _fetchedResultsController!
} let fetchRequest = NSFetchRequest()
// Edit the entity name as appropriate.
let entity = NSEntityDescription.entityForName("BlogItems", inManagedObjectContext: self.managedObjectContext!)
fetchRequest.entity = entity // Set the batch size to a suitable number.
fetchRequest.fetchBatchSize = 20 // Edit the sort key as appropriate.
let sortDescriptor = NSSortDescriptor(key: "date", ascending: false) fetchRequest.sortDescriptors = [sortDescriptor] // Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext!, sectionNameKeyPath: nil, cacheName: "Master")
aFetchedResultsController.delegate = self
_fetchedResultsController = aFetchedResultsController do {
try _fetchedResultsController!.performFetch()
} catch {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
//print("Unresolved error \(error), \(error.userInfo)")
abort()
} return _fetchedResultsController!
}
var _fetchedResultsController: NSFetchedResultsController? = nil func controllerWillChangeContent(controller: NSFetchedResultsController) {
self.tableView.beginUpdates()
} func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
switch type {
case .Insert:
self.tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
case .Delete:
self.tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade)
default:
return
}
} func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch type {
case .Insert:
tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
case .Delete:
tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
case .Update:
self.configureCell(tableView.cellForRowAtIndexPath(indexPath!)!, atIndexPath: indexPath!)
case .Move:
tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
}
} func controllerDidChangeContent(controller: NSFetchedResultsController) {
self.tableView.endUpdates()
} /*
// Implementing the above methods to update the table view in response to individual changes may have performance implications if a large number of changes are made simultaneously. If this proves to be an issue, you can instead just implement controllerDidChangeContent: which notifies the delegate that all section and object changes have been processed. func controllerDidChangeContent(controller: NSFetchedResultsController) {
// In the simplest, most efficient, case, reload the table view.
self.tableView.reloadData()
}
*/ }
//
// DetailViewController.swift
// Blog Reader
//
// Created by zcdll on 16/1/24.
// Copyright © 2016年 ZC. All rights reserved.
// import UIKit class DetailViewController: UIViewController { @IBOutlet weak var webview: UIWebView! var detailItem: AnyObject? {
didSet {
// Update the view.
self.configureView()
}
} func configureView() {
// Update the user interface for the detail item.
if let detail = self.detailItem {
if let postWebView = self.webview { postWebView.loadHTMLString(detail.valueForKey("content")!.description, baseURL: NSURL(string: "https://googleblog.blogspot.com/")) }
}
} override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.configureView()
} override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
} }
27_Blog Reader的更多相关文章
- InputStream、InputStreamReader和Reader的关系
InputStream:得到的是字节输入流,InputStream.read("filename")之后,得到字节流 Reader:读取的是字符流 InputStreamReade ...
- Distribution1:Distribution Reader
在transactional replication中,在publication中执行了一个更新,例如:update table set col=? Where ?,如果table中含有大量的数据行, ...
- Reader与InputStream两个类中的read()的区别
InputStream类的read()方法是从流里面取出一个字节,他的函数原型是 int read(); ,Reader类的read()方法则是从流里面取出一个字符(一个char),他的函数原型也是 ...
- Ubuntu 12.04安装Adobe Reader
原本从Adobe 官方网站下载了 Adobe Reader, 是个rpm包,先用agt-get 装了rpm(sudo apt-get install rpm), 一安装(rpm -ivh AdobeR ...
- Adobe Reader/Acrobat修改页面底色为豆沙绿
Adobe Acrobat_Pro_8修改PDF页面底色为豆沙绿保护视力(同样适用于Adobe Reader) http://jingyan.baidu.com/article/9989c746189 ...
- multithreading - Reader/Writer Locks in C++
You Only Need To Note This: only 1 single thread can acquire an upgrade_lock at one time. others are ...
- AttributeError: '_csv.reader' object has no attribute 'next'
我在使用pyhon3.4运行以下代码时报错:AttributeError: '_csv.reader' object has no attribute 'next' import csv import ...
- SWF READER 破解日志。
网上传闻swf reader是破解最厉害的神器,可以内存抓取+doSWF反编译.所以去官网下了一个: SWF_Reader_2.3 不出所料,demo版本没有反编译的功能.网上搜到一个哥们尝试了下: ...
- Scalaz(16)- Monad:依赖注入-Dependency Injection By Reader Monad
在上一篇讨论里我们简单的介绍了一下Cake Pattern和Reader Monad是如何实现依赖注入的.主要还是从方法上示范了如何用Cake Pattern和Reader在编程过程中解析依赖和注入依 ...
随机推荐
- html 中的name,id ,value,class,list 作用与区别
name: 单独一个网页中,一个控件是否设置name不会影响这个网页功能的实现.当我们需要把这个控件 所关联的数据传递到数据库时,就必须设置name属性,否则这个值是没办法传到服务器保存的: id: ...
- JAVA 语 言 如 何 进 行 异 常 处 理 , 关 键 字 : throws,throw,try,catch,final
throws是获取异常throw是抛出异常try是将会发生异常的语句括起来,从而进行异常的处理,catch是如果有异常就会执行他里面的语句,而finally不论是否有异常都会进行执行的语句.
- (C++编程规范第17条)避免使用”魔数“
1.摘要: 程序设计并非魔数,所以不要故弄玄虚:要避免在代码中使用诸如42和3.14159这样的文字常量.它们本身没有提供任何说明,并且因为增加了难于检测的重复而使维护更加复杂.可以用符号名称和表达式 ...
- qt学习:信号,槽
[C.GUI.Qt.4编程(第二版)](加)布兰切特,(英)萨默菲尔德.扫描版[学习库www.xuexi111.com].pdf 信号和槽是Qt编程的基础,它可以让各种对象联系在一起. 1. 使用co ...
- Spring——AOP(面向切面编程)@AspectJ注解方式
一.什么是AOP? AOP: (Aspect Oriented Programming)即面向切面编程. 试想这样的场景:项目中需要在业务方法执行完打印日志记录.最笨的办法就是在每个方法核心业务执行完 ...
- [Usaco2009 Feb]Revamping Trails 堆优化 Dijkstra
.. 这题一眼就看出就是一个二维DP dp[i][j]表示到点i使用了j次免费边的最短距离 MD 卡SPFA.. 遂写dij. AC #include <iostream> #includ ...
- [互联网面试笔试汇总C/C++-9] 实现赋值运算符函数-剑指offer
题目:如下为类型CMyString的声明,请为该类型添加赋值运算符函数. class CMyString { public: CMyString(char* pData = NULL); CMyStr ...
- Streams Studio配置Build options
Defining build options You can change the build options of the internal builder for building an SPL ...
- 十大最值得注意的MySQL变量
MySQL数据库中的变量非常多,下文为您整理出了十大最值得注意的MySQL变量,希望对您学习MySQL数据库能够有一些帮助. AD: MySQL变量很多,其中有一些MySQL变量非常值得我们注意,下面 ...
- UVALive 6709 - Mosaic 二维线段树
题目链接 给一个n*n的方格, 每个方格有值. 每次询问, 给出三个数x, y, l, 求出以x, y为中心的边长为l的正方形内的最大值与最小值, 输出(maxx+minn)/2, 并将x, y这个格 ...