【发布时间】:2017-01-18 13:57:52
【问题描述】:
我正在使用 URLSessionDataTask 从 API 下载 XML 文件。
XML 如下所示:
<?xml version="1.0" encoding="UTF-8" ?>
<ResultList id="12345678-0" platforms="A;B;C;D;E">
<Book id="1111111111" author="Author A" title="Title A" price="9.95" ... />
<Book id="1111111112" author="Author B" title="Title B" price="2.00" ... />
<Book id="1111111113" author="Author C" title="Title C" price="5.00" ... />
<ResultInfo bookcount="3" />
</ResultList>
有时 XML 可能包含数千本书。
我正在使用 Libxml2 中的 SAX 解析器解析 XML。在解析时,我创建了一个对象 Book 并从 XML 中设置值,如下所示:
private func startElementSAX(_ ctx: UnsafeMutableRawPointer?, name: UnsafePointer<xmlChar>?, prefix: UnsafePointer<xmlChar>?, URI: UnsafePointer<xmlChar>?, nb_namespaces: CInt, namespaces: UnsafeMutablePointer<UnsafePointer<xmlChar>?>?, nb_attributes: CInt, nb_defaulted: CInt, attributes: UnsafeMutablePointer<UnsafePointer<xmlChar>?>?) {
let elementName = String(cString: name!)
switch elementName {
case "Book":
let book = buildBook(nb_attributes: nb_attributes, attributes: attributes)
parser.delegate?.onBook(book: book)
default:
break
}
}
func buildBook(nb_attributes: CInt, attributes: UnsafeMutablePointer<UnsafePointer<xmlChar>?>?) -> Book {
let fields = 5 /* (localname/prefix/URI/value/end) */
let book = Book()
for i in 0..<Int(nb_attributes) {
if let localname = attributes?[i * fields + 0],
//let prefix = attributes?[i * fields + 1],
//let URI = attributes?[i * fields + 2],
let value_start = attributes?[i * fields + 3]//,
/*let value_end = attributes?[i * fields + 4]*/ {
let localnameString = String(cString: localname)
let string_start = String(cString: value_start)
//let string_end = String(cString: value_end)
if let end = string_start.characters.index(of: "\"") {
let value = string_start.substring(to: end)
book.setValue(value, forKey: localnameString)
} else {
book.setValue(string_start, forKey: localnameString)
}
}
}
return book
}
在 UITableViewController 中,onBook(book: Book) 委托方法将书籍对象附加到数组并更新 UITableView。到目前为止一切顺利。
现在的问题是,它占用了设备的太多 RAM,所以我的设备变慢了。 XML 中有大约 500 本书,需要 >500 MB 的 RAM。我不知道为什么。当我在 Instruments 中查找 RAM 时,我会在 _HeapBufferStorage<_StringBufferIVars, UInt16> 类别中看到所有分配的内存
有多个大于 100 KB 的条目
在 Event History 中列出了 buildBook() 方法
当我将 Foundation 的 XMLParser 与构造函数 XMLParser(contentsOf: URL) 一起使用时,它首先下载整个 XML 然后解析它,我的 RAM 使用率正常。不管书多少。但我想尽快在 UITableView 中展示这些书籍。我只想要 Android 的 XMLPullParser for iOS 之类的东西。
【问题讨论】:
-
SAX 解析器解析 XML 数据需要占用很小的内存,要不要尝试其他解析器?
-
我想到了来自 LibXML2 的 XMLTextReader interface,因为它是“继任者”。但是你知道我是否可以在下载 XML 文件时使用它吗?