使用DTAttributeTextContentView加载远程图像

时间:2017-10-14 05:11:18

标签: ios swift

我正在使用DTCoreText开发一个在线论坛的应用程序,以显示从BBCode解析为HTML的线程回复,其中包含UITableView中自定义单元格内的文本和图像。我使用界面构建器来构建我的原型单元格并使用outlet将其链接到我的自定义单元格类。文本正确显示但图像未加载并在单元格视图内留下空白空间。继承我的视图控制器和单元类代码

我的视图控制器:

//

import UIKit
import NVActivityIndicatorView

class ContentViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {

//MARK: Properties

var threadIdReceived: String = ""
var channelNow: String = ""
var isRated: Bool = false
var pageNow: Int = 1
var convertedText: String = ""
var op = OP(t: "",n: "",l: "",c: "",cH: "",a: "",d: "",gd: "",b: "",ge: "",ch: "")
var comments = [Replies]()
var replyCount = 1

@IBOutlet weak var contentTableView: UITableView!
@IBOutlet weak var pageButton: UIBarButtonItem!
@IBOutlet weak var goodCount: UIBarButtonItem!
@IBOutlet weak var badCount: UIBarButtonItem!
@IBOutlet weak var prevButton: UIBarButtonItem!
@IBOutlet weak var nextButton: UIBarButtonItem!

let backgroundIndicator = NVActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height),type: .ballPulseSync,padding: 175)

//HKGalden API (NOT included in GitHub repo)
var api = HKGaldenAPI()

override func viewDidLoad() {
    super.viewDidLoad()
    self.navigationController?.navigationBar.tintColor = UIColor.white
    self.navigationController?.navigationBar.isTranslucent = true
    contentTableView.delegate = self
    contentTableView.dataSource = self

    backgroundIndicator.startAnimating()
    self.view.addSubview(backgroundIndicator)

    self.prevButton.isEnabled = false

    self.pageButton.title = "第" + String(pageNow) + "頁"

    // Uncomment the following line to preserve selection between presentations
    // self.clearsSelectionOnViewWillAppear = false

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem

    contentTableView.isHidden = true

    api.fetchContent(postId: threadIdReceived, pageNo: String(pageNow), completion: {
        [weak self] op,comments,error in
        if (error == nil) {
            self?.op = op
            self?.comments = comments
            self?.title = op.title
            self?.goodCount.title = op.good
            self?.badCount.title = op.bad
            self?.contentTableView.reloadData()
            self?.backgroundIndicator.isHidden = true
            self?.contentTableView.isHidden = false
            self?.contentTableView.tableFooterView = UIView()
        }
    })
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return (comments.count) + 1
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "ContentTableViewCell", for: indexPath) as! ContentTableViewCell

    if(indexPath.row == 0) {
        cell.configureOP(opData: op)
    }
    else {
        cell.configureReply(comments: comments, indexPath: indexPath,pageNow: pageNow)
    }
    return cell
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

/*
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    // Return false if you do not want the specified item to be editable.
    return true
}
*/

/*
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
        // Delete the row from the data source
        tableView.deleteRows(at: [indexPath], with: .fade)
    } else if editingStyle == .insert {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }    
}
*/

/*
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {

}
*/

/*
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
    // Return false if you do not want the item to be re-orderable.
    return true
}
*/

/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.
}
*/


@IBAction func changePage(_ sender: UIBarButtonItem) {
    switch (sender.tag) {
    case 0:
        contentTableView.isHidden = true
        backgroundIndicator.isHidden = false
        self.pageNow -= 1
        self.pageButton.title = "第" + String(self.pageNow) + "頁"
        self.api.fetchContent(postId: threadIdReceived, pageNo: String(pageNow), completion: {
            [weak self] op,comments,error in
            if (error == nil) {
                self?.op = op
                self?.comments = comments
                self?.title = op.title
                self?.goodCount.title = op.good
                self?.badCount.title = op.bad
                self?.contentTableView.reloadData()
                self?.backgroundIndicator.isHidden = true
                self?.contentTableView.isHidden = false
                self?.contentTableView.tableFooterView = UIView()
            }
        })
    case 1:
        self.prevButton.isEnabled = true
        contentTableView.isHidden = true
        backgroundIndicator.isHidden = false
        self.pageNow += 1
        self.pageButton.title = "第" + String(self.pageNow) + "頁"
        self.api.fetchContent(postId: threadIdReceived, pageNo: String(pageNow), completion: {
            [weak self] op,comments,error in
            if (error == nil) {
                self?.op = op
                self?.comments = comments
                self?.title = op.title
                self?.goodCount.title = op.good
                self?.badCount.title = op.bad
                self?.contentTableView.reloadData()
                self?.backgroundIndicator.isHidden = true
                self?.contentTableView.isHidden = false
                self?.contentTableView.tableFooterView = UIView()
            }
        })
    default:
        print("nothing")
    }
}

//MARK: Private Functions
private func barTintColorChanger(channelId: String) {
    switch channelId {
    case "bw":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 72/255, green: 125/255, blue: 174/255, alpha: 1)
    case "et":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 152/255, green: 85/255, blue: 159/255, alpha: 1)
    case "ca":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 33/255, green: 136/255, blue: 101/255, alpha: 1)
    case "fn":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 33/255, green: 136/255, blue: 101/255, alpha: 1)
    case "gm":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 37/255, green: 124/255, blue: 201/255, alpha: 1)
    case "ap":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 41/255, green: 145/255, blue: 185/255, alpha: 1)
    case "it":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 94/255, green: 106/255, blue: 125/255, alpha: 1)
    case "mp":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 88/255, green: 100/255, blue: 174/255, alpha: 1)
    case "sp":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 152/255, green: 64/255, blue: 81/255, alpha: 1)
    case "lv":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 196/255, green: 53/255, blue: 94/255, alpha: 1)
    case "sy":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 127/255, green: 112/255, blue: 106/255, alpha: 1)
    case "ed":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 65/255, green: 143/255, blue: 66/255, alpha: 1)
    case "tm":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 190/255, green: 71/255, blue: 30/255, alpha: 1)
    case "tr":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 97/255, green: 118/255, blue: 83/255, alpha: 1)
    case "an":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 171/255, green: 80/255, blue: 159/255, alpha: 1)
    case "to":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 148/255, green: 95/255, blue: 50/255, alpha: 1)
    case "mu":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 88/255, green: 95/255, blue: 202/255, alpha: 1)
    case "vi":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 121/255, green: 78/255, blue: 126/255, alpha: 1)
    case "dc":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 56/255, green: 102/255, blue: 118/255, alpha: 1)
    case "st":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 128/255, green: 113/255, blue: 143/255, alpha: 1)
    case "ts":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 172/255, green: 48/255, blue: 66/255, alpha: 1)
    case "mb":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 124/255, green: 89/255, blue: 196/255, alpha: 1)
    case "ia":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 132/255, green: 169/255, blue: 64/255, alpha: 1)
    case "ac":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 150/255, green: 75/255, blue: 112/255, alpha: 1)
    case "ep":
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 152/255, green: 112/255, blue: 93/255, alpha: 1)
    default:
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 0/255, green: 0/255, blue: 0/255, alpha: 1)
    }
}
}

继续我的细胞课:

import UIKit
import Kingfisher
import DTCoreText

class ContentTableViewCell: UITableViewCell, DTAttributedTextContentViewDelegate, DTLazyImageViewDelegate {

//MARK: Properties


@IBOutlet weak var userNameLabel: UILabel!
@IBOutlet weak var userLevelLabel: UILabel!
@IBOutlet weak var userAvatarImageView: UIImageView!
@IBOutlet weak var replyCountLabel: UILabel!
@IBOutlet weak var dateLabel: UILabel!
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var contentTextView: DTAttributedTextContentView!

let attributedOptions: NSDictionary = [
    NSAttributedString.DocumentAttributeKey.documentType: NSAttributedString.DocumentType.html,
    NSAttributedString.DocumentAttributeKey.characterEncoding: String.Encoding.utf8,
    DTDefaultFontFamily: "Helvetica Neue",
    DTDefaultFontSize: 15,
    DTMaxImageSize: CGSize(width:280,height:450)
]

override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
    contentTextView.shouldDrawImages = false
    contentTextView.delegate = self as DTAttributedTextContentViewDelegate
}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)
    // Configure the view for the selected state
}


func attributedTextContentView(_ attributedTextContentView: DTAttributedTextContentView!, viewFor attachment: DTTextAttachment!, frame: CGRect) -> UIView! {
    if attachment is DTImageTextAttachment {
        let imageView = DTLazyImageView(frame: frame)
        imageView.contentView = contentTextView
        imageView.delegate = self as DTLazyImageViewDelegate
        //url for deferred loading
        imageView.url = attachment.contentURL
        imageView.shouldShowProgressiveDownload = true
        return imageView
    }
    return nil
}

func lazyImageView(_ lazyImageView: DTLazyImageView!, didChangeImageSize size: CGSize) {
    let url = lazyImageView.url
    let pred = NSPredicate(format: "contentURL == %@",url! as CVarArg)

    let array = self.contentTextView.layoutFrame.textAttachments(with: pred)

    for _ in (array?.enumerated())! {
        let element = DTTextAttachment()
        element.originalSize = size
        element.displaySize = size
    }
    contentTextView.layouter = nil
    contentTextView.relayoutText()
}

func configureOP(opData: OP) {
    userNameLabel.text = opData.name

    if(opData.gender == "male") {
        userNameLabel.textColor = UIColor(red:0.68, green:0.78, blue:0.81, alpha:1.0)
    }
    else {
        userNameLabel.textColor = UIColor(red:1.00, green:0.41, blue:0.38, alpha:1.0)
    }

    if(opData.level == "lv1") {
        userLevelLabel.text = "普通會然"
        userLevelLabel.backgroundColor = UIColor.darkGray
    }
    else if (opData.level == "lv2") {
        userLevelLabel.text = "迷の存在"
        userLevelLabel.backgroundColor = UIColor(red:0.55, green:0.00, blue:0.00, alpha:1.0)
    }
    else if (opData.level == "lv3") {
        userLevelLabel.text = "肉務腸"
        userLevelLabel.backgroundColor = UIColor(red:0.47, green:0.87, blue:0.47, alpha:1.0)
    }
    else if (opData.level == "lv4") {
        userLevelLabel.text = "唉屎"
        userLevelLabel.backgroundColor = UIColor(red:0.00, green:1.00, blue:1.00, alpha:1.0)
    }

    let avatarURL = URL(string: "https://hkgalden.com" + opData.avatar)
    if (opData.avatar == "") {
        userAvatarImageView.image = UIImage(named: "DefaultAvatar")
    }
    else {
        userAvatarImageView.kf.setImage(with: avatarURL)
    }

    //remove abundant </img> tag
    opData.contentHTML = opData.contentHTML.replacingOccurrences(of: "</img>", with: "")

    //print(opData.contentHTML)
    let contentData = opData.contentHTML.data(using: .utf8)
    let contentAttr = NSAttributedString.init(htmlData: contentData, options: attributedOptions as! [AnyHashable : Any], documentAttributes: nil)
    //print(contentAttr)
    contentTextView.attributedString = contentAttr

    replyCountLabel.text = "OP"
    dateLabel.text = opData.date
}

func configureReply(comments: [Replies],indexPath: IndexPath,pageNow: Int) {
    userNameLabel.text = comments[indexPath.row - 1].name

    if(comments[indexPath.row - 1].gender == "male") {
        userNameLabel.textColor = UIColor(red:0.68, green:0.78, blue:0.81, alpha:1.0)
    }
    else {
        userNameLabel.textColor = UIColor(red:1.00, green:0.41, blue:0.38, alpha:1.0)
    }

    if(comments[indexPath.row - 1].level == "lv1") {
        userLevelLabel.text = "普通會然"
        userLevelLabel.backgroundColor = UIColor.darkGray
    }
    else if (comments[indexPath.row - 1].level == "lv2") {
        userLevelLabel.text = "迷の存在"
        userLevelLabel.backgroundColor = UIColor(red:0.55, green:0.00, blue:0.00, alpha:1.0)
    }
    else if (comments[indexPath.row - 1].level == "lv3") {
        userLevelLabel.text = "肉務腸"
        userLevelLabel.backgroundColor = UIColor(red:0.47, green:0.87, blue:0.47, alpha:1.0)
    }
    else if (comments[indexPath.row - 1].level == "lv4") {
        userLevelLabel.text = "唉屎"
        userLevelLabel.backgroundColor = UIColor(red:0.00, green:1.00, blue:1.00, alpha:1.0)
    }

    let avatarURL = URL(string: "https://hkgalden.com" + comments[indexPath.row - 1].avatar)
    if (comments[indexPath.row - 1].avatar == "") {
        userAvatarImageView.image = UIImage(named: "DefaultAvatar")
    }
    else {
        userAvatarImageView.kf.setImage(with: avatarURL)
    }

    replyCountLabel.text = "#" + String(25 * (pageNow - 1) + indexPath.row)
    dateLabel.text = comments[indexPath.row - 1].date

    let contentData = comments[indexPath.row - 1].contentHTML.data(using: .utf8)
    let contentAttr = NSAttributedString.init(htmlData: contentData, options: attributedOptions as! [AnyHashable : Any], documentAttributes: nil)
    //print(contentAttr)
    contentTextView.attributedString = contentAttr
}
}

1 个答案:

答案 0 :(得分:0)

尝试此类别 - 它适用于我

extension UIImageView {

  public func imageFromUrl(url: URL?) {
    if let url = url {
      let task = URLSession.shared.dataTask(with: url) { data, response, error in
        guard let data = data, error == nil else { return }

        DispatchQueue.main.async { [weak self] in
            self?.image = UIImage(data: data)
        }
      }
      task.resume()
    }
  }

}