准备工作
推荐使用 CocoaPods 安装 Ono 这个三方,这样可以省下很多配置的麻烦。
pod 'Ono'
如果手动导入的话按照以下步骤就好了
-
下载Ono主分支文件 Ono 下载 ,将下面三个文件导入到工程中:
-
swift要新建一个桥接文件
工程名-Bridging-Header.h
,创建文件后还要设置一下:
在桥接文件中引入头文件
#import "Ono.h"
-
因为Oon这个库是基于
libxml2
所以工程中要导入这个库(好像不知道什么时候开始 库的后缀从.dylib
变成了.tbd
)
在 Build Settings下,Header Search Paths 中添加
$(SDKROOT)/usr/include/libxml2
在 Build Settings下,Other Linker Flags 中添加
-lxml2
-
因为iOS9之后强制使用https所以要在info.plist中加入下面代码来使程序允许使用http
<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>
小说列表
在Main.storyboard 中选中创建好工程后自带的ViewController,上方工具条 Editor -> Embed In -> Navigation Controller 给ViewController添加一个UINavigationController
在ViewController中添加一个UITableView并设置好代理(或者干脆把ViewController删除掉使用UITableViewController),并添加一个空白的cell,设置好identifier,最终效果如下图。
在ViewController.swift 添加属性
var books = [Book]()
在ViewController.swift 的 viewDidLoad() 中添加如下代码
// 抓取网站的数据
let data = NSData(contentsOfURL: NSURL(string: "http://m.ybdu.com/quanben/1")!)
// 将gbk编码的data转换成UTF-8的字符串
let str = NSString(data: data!, encoding: CFStringConvertEncodingToNSStringEncoding(0x0632))
// 创建 document
let document = try? ONOXMLDocument(string: str as! String, encoding: NSUTF8StringEncoding)
// 解包
if let document = document {
// 根据CSS规则检索节点并使用闭包遍历所有检索结果
document.enumerateElementsWithCSS(".list p", usingBlock: { (element: ONOXMLElement!, _, _) -> Void in
let bookElement = element.children.first as! ONOXMLElement
let bookHref = (bookElement["href"] as! String).stringByReplacingOccurrencesOfString("/xiazai", withString: "")
self.books.append(Book(uri: bookHref, name: bookElement.stringValue(), author: nil))
})
self.tableView.reloadData()
}
Model类 Book
Book类中暂时只用到了两个属性uri
和 name
class Book: NSObject {
var uri: String! // 小说 uri
var name: String! // 小说名称
var author: String? // 小说作者
required init(uri: String!, name: String!, author: String?) {
self.uri = uri
self.name = name
self.author = author
super.init() // 因为Book类继承了NSObject所以要在子类独有的属性初始化之后调用父类的初始化方法
}
convenience init(uri: String, name: String!, author: String?) {
self.init(uri: uri, name: name, author: author)
}
}
UITableView代理方法
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.books.count
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 44
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell")
cell!.textLabel?.text = self.books[indexPath.row].name
return cell!
}
运行效果
分析网站节点
CSS?XPath?都是什么鬼... 具体他们是啥你让我说我也说不清楚我大概也就了解到我们可以根据这个两个东西获取到HTML中指定节点的属性和内容等。使用谷歌浏览器输入下图网址框中的地址,按照指示操作就能获取到我们想要的东西了。简单吧!~~~
copy出来的东西大概是这个样子的:body > div.list > p:nth-child(2)
多copy几次,对照标签的属性和copy出来的内容就明白了,可以看一下Ono的Demo里面有一个Test写了各种标签的对照。
标签中的属性class="xxx"
可以转换成 .xxx
标签中的属性id="xxx"
可以转换成 #xxx
下面的情况可以转换成.list p
,这样根据这个规则就可以把div下所有的p标签解析出来了
<div class="list">
<p></>
</div>
NSError哪去了?
查看Ono的头文件,初始化一个ONOXMLDocument
对象,使用下面的类方法。注意OC代码中最后一个参数是一个NSError类型的变量,但是转换到了swift后这个NSError消失了!在外面多了一个throws,具体看下面的图
/**
Creates and returns an instance of ONOXMLDocument from an HTML string.
@param string The HTML string.
@param encoding The string encoding.
@param error The error error that occured while parsing the HTML, or `nil`.
@return An `ONOXMLDocument` with the contents of the specified HTML string.
*/
+ (instancetype)HTMLDocumentWithString:(NSString *)string
encoding:(NSStringEncoding)encoding
error:(NSError * __autoreleasing *)error;
引用了一个CSDN的帖子上的原文,具体看这个链接吧。
与Cocoa和Cocoa Touch框架间的交互
现在的问题是,你如何在Swift 2.0中处理爷爷级的NSError API呢?苹果公司已经在Swift 2.0中为统一代码行为作了大量工作,并且已经为未来写入>Swift的框架准备方法。Cocoa和Cocoa Touch中可以产生NSError实例的方法和函数有苹果公司的签名( signature),可以自动转换为Swift新的错误处理方式。
swift中变态的构造过程
源码
github: YYReader
master分支->tag 0.2