我正在开发一个应用程序,该应用程序将从WordPress检索帖子,并允许用户单独查看每个帖子的详细信息。 WordPress API带回帖子内容,即帖子的HTML。 (注意:img标签引用的是上传图片的WordPress URL)
最初,我正在使用WebView并将检索到的内容直接加载到其中。效果很好;但是,图像似乎正在主线程上加载,因为这会导致出现滞后现象,有时会冻结UI,直到图像完成下载为止。建议我检查WordPress的Aztec编辑器库;但是,我不知道如何使用它(找不到太多文档)。
我当前的路线是解析HTML内容并创建词典列表([image或text]类型的键和content)。解析后,我通过动态添加Labels&Image视图(使我可以在后台下载图像)来构建帖子。尽管这看起来似乎过于复杂并且可能是错误的路线,但它运行良好(不过,将对任何其他解决方案开放!)目前,我唯一的问题是将HTML字符串转换为NSAttributedText的延迟。在将文本内容添加到字典之前,我将其从String转换为NSAttributedString。我注意到延迟了几秒钟,模拟器的CPU在几秒钟内上升了50-60%,然后下降了。无论如何,在这段时间内我可以在后台线程上执行此转换并显示加载动画吗?
如果您有任何更好的解决方案的想法或建议,请告诉我。非常感谢你!
代码:
let postCache = NSCache<NSString, AnyObject>()
var yPos = CGFloat(20)
let screenWidth = UIScreen.main.bounds.width
...
func parsePost() -> [[String:Any]]? {
if let postFromCache = postCache.object(forKey: postToView.id as NSString) as? [[String:Any]] {
return postFromCache
} else {
var content = [[String:Any]]()
do {
let doc: Document = try SwiftSoup.parse(postToView.postContent)
if let elements = try doc.body()?.children() {
for elem in elements {
if(elem.hasText()) {
do {
let html = try elem.html()
if let validHtmlString = html.htmlToAttributedString {
content.append(["text" : validHtmlString])
}
}
} else {
let imageElements = try elem.getElementsByTag("img")
if(imageElements.size() > 0) {
for image in imageElements {
var imageDictionary = [String:Any]()
let width = (image.getAttributes()?.get(key: "width"))!
let height = (image.getAttributes()?.get(key: "height"))!
let ratio = CGFloat(Float(height)!/Float(width)!)
imageDictionary["ratio"] = ratio
imageDictionary["image"] = (image.getAttributes()?.get(key: "src"))!
content.append(imageDictionary)
}
}
}
}
}
} catch {
print("error")
}
if(content.count > 0) {
postCache.setObject(content as AnyObject, forKey: postToView.id as NSString)
}
return content
}
}
func buildUi(content: [[String:Any]]) {
for dict in content {
if let attributedText = dict["text"] as? NSAttributedString {
let labelToAdd = UILabel()
labelToAdd.attributedText = attributedText
labelToAdd.numberOfLines = 0
labelToAdd.frame = CGRect(x:0, y:yPos, width: 200, height: 0)
labelToAdd.sizeToFit()
yPos += labelToAdd.frame.height + 5
self.scrollView.addSubview(labelToAdd)
} else if let imageName = dict["image"] as? String {
let ratio = dict["ratio"] as! CGFloat
let imageToAdd = UIImageView()
let url = URL(string: imageName)
Nuke.loadImage(with: url!, into: imageToAdd)
imageToAdd.frame = CGRect(x:0, y:yPos, width: screenWidth, height: screenWidth*ratio)
yPos += imageToAdd.frame.height + 5
self.scrollView.addSubview(imageToAdd)
}
}
self.scrollView.contentSize = CGSize(width: self.scrollView.contentSize.width, height: yPos)
}
extension String {
var htmlToAttributedString: NSAttributedString? {
guard let data = data(using: .utf8) else { return NSAttributedString() }
do {
return try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding:String.Encoding.utf8.rawValue], documentAttributes: nil)
} catch {
return NSAttributedString()
}
}
var htmlToString: String {
return htmlToAttributedString?.string ?? ""
}
}
(请原谅我提供的代码不太干净!我只是想确保在开始重构之前可以取得理想的结果。再次感谢!)