在UITextView中显示HTML文本在swift 4中发生崩溃?

在UITextView中显示HTML文本在swift 4中发生崩溃?,html,ios,swift,uitextview,swift4,Html,Ios,Swift,Uitextview,Swift4,我使用的是被剪掉的代码 在UITableViewCell cell.textViewMessage.attributedText = msg.htmlToAttributedString 第一次启动时没有崩溃,但在那之后,当我运行代码时出现了崩溃,之后就不再工作了 线程1:EXC\u错误访问(代码=1,地址=0x10) #编辑要在单元格中显示的HTML字符串 <p>Here\'s a short video tour. Press play to start.</p>

我使用的是被剪掉的代码

UITableViewCell

cell.textViewMessage.attributedText = msg.htmlToAttributedString
第一次启动时没有崩溃,但在那之后,当我运行代码时出现了崩溃,之后就不再工作了

线程1:EXC\u错误访问(代码=1,地址=0x10)

#编辑要在单元格中显示的HTML字符串

<p>Here\'s a short video tour.  Press play to start.</p><br><iframe class=\"ql-video\" frameborder=\"0\" allowfullscreen=\"true\" src=\"https://www.youtube.com\"></iframe><br>
这里是一个简短的视频教程。按play开始。



#编辑1-我正在操场上尝试运行此代码,它工作正常,但现在显示错误。请参见所附图片


看起来问题在于标记,并非每个标记都能显示在uitextview中。 您可以在uiwebview中更好地显示这些标记

我认为问题在于iframe标签

要显示iFrame,请改用uiwebview或wkwebview


谢谢

这是一个受回购启发的解决方案。基本上,我们删除了
iframe
标记,并将其替换为可点击的
img

let msg = "<p>Here\'s a short video tour. Press play to start.</p><br><iframe class=\"ql-video\" frameborder=\"0\" allowfullscreen=\"true\" src=\"https://www.youtube.com/embed/wJcOvdkI7mU\"></iframe><br>"

//Let's get the video id
let range = NSRange(location: 0, length: msg.utf16.count)
let regex = try! NSRegularExpression(pattern: "((?<=(v|V)/)|(?<=be/)|(?<=(\\?|\\&)v=)|(?<=embed/))([\\w-]++)")
guard let match = regex.firstMatch(in: msg, options: [], range: range) else {
    fatalError("Couldn't find the video ID")
}
let videoId: String = String(msg[Range(match.range, in: msg)!])

//Let's replace the the opening iframe tag
let regex2 = try! NSRegularExpression(pattern:
    "<[\\s]*iframe[\\s]+.*src=")

let str2 = regex2.stringByReplacingMatches(in: msg, options: [], range: range, withTemplate: "<a href=")

//And then replace the closing tag
let regex3 = try! NSRegularExpression(pattern:
    "><\\/iframe>")
let range2 = NSRange(location: 0, length: str2.utf16.count)
let str3 = regex3.stringByReplacingMatches(in: str2, options: [], range: range2, withTemplate: "><img src=\"https://img.youtube.com/vi/" + videoId + "/0.jpg\" alt=\"\" width=\"\(textView.frame.width)\" /></a>")         // You could adjust the width and height to your liking

//Set the text of the textView
textView.attributedText = str3.htmlToAttributedString
textView.delegate = self
如果未安装youtube应用程序,则视频将在Safari中播放

结果如下:


将选项更改为:

let options: [NSAttributedString.DocumentReadingOptionKey: Any] = [
                NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html,
                NSAttributedString.DocumentReadingOptionKey.characterEncoding: String.Encoding.utf8.rawValue
            ]

为UITextView尝试以下操作:

let string = "<h2>The bedding was hardly able to cover it.</h2>"
if !string.isEmpty{
    if let htmlData = string.data(using:String.Encoding.unicode) {
    do {
          let attributedText = try NSAttributedString(data: htmlData, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil)
           cell.textViewMessage.attributedText = attributedText
       } catch let e as NSError {
          print("Couldn't translate \(string): \(e.localizedDescription) ")
       }
 }
let string=“床上用品几乎无法盖住它。”
如果!string.isEmpty{
如果让htmlData=string.data(使用:string.Encoding.unicode){
做{
让attributedText=尝试NSAttributedString(数据:htmlData,选项:[NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType],DocumentAttribute:nil)
cell.textViewMessage.attributedText=attributedText
}把e当作错误来抓{
打印(“无法翻译\(字符串):\(e.localizedDescription)”)
}
}
为UILabel尝试以下操作,将html文本设置为带有html标记的UILabel:

extension String {
     var withoutHtmlTags: String {
            let a = self.replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil)

            return a.replacingOccurrences(of: "&[^;]+;", with: "", options: String.CompareOptions.regularExpression, range: nil)
        }
    }

let string = "<h2>The bedding was hardly able to cover it.</h2>"

textUIlabel.text = string.withoutHtmlTags
扩展字符串{
不带HtmlTags的变量:字符串{
设a=self.replacingOccurrences(of:“]+>”,with:,options:。正则表达式,范围:nil)
返回a.replacingOccurrences(of:&[^;]+;”,with:,选项:String.CompareOptions.regularExpression,范围:nil)
}
}
let string=“床上用品几乎无法盖住它。”
textuilab.text=string.without HtmlTags

此问题的原因是表视图,此错误将随机发生,并且很难再现,因为它更具体于设备内存和UI绘制过程,这可能导致在后台线程中执行该方法。在重新分配和取消分配表单元格时,表单元格可能会在深层调用此错误方法,而HTML导入器使用非线程安全的WebKit导入器,并且希望位于主线程上

如何重现此错误:使用UITest运行代码,它会更频繁地崩溃,因为单元测试会显著降低UI绘制过程的速度

解决方案:将HTML解码为字符串应该在主线程上,但在主线程的模型层中执行此操作,而不是在单元格创建过程中执行此操作。这也将使UI更加流畅


为何未在catch block中捕获崩溃:由于Objective-C异常处理基础架构使用的未处理语言异常,您的应用程序已崩溃。SWIFT就像Cocoa的N错误的漂亮包装器。SWIFT无法处理Objective-C异常,因此无法通过Objective-C代码处理异常框架中的错误不会由您的Swift错误处理程序引起。

控制台中有崩溃消息吗?没有。控制台中没有崩溃消息。xcode卡在代码上,用红线剪断。@Vishal16您可以在后台调用它吗?@QuocNguyen没有,我是从主线程中的
cellForRowAtIndexPath
方法调用它的。@Vishal16似乎有人对后台线程有问题。不是你。你能提供更多的崩溃信息吗?我已经知道了,但我需要在
UITextView
上执行它。你是否用
标记或视频URL来尝试它?请检查:他们使用了…我不熟悉这个标记。但是他们使用的是
UIWebView
,我的问题是使用
UITextView
?您的解决方案有效,但我正在寻找解决我的崩溃日志的答案。如果没有人帮助我,我将接受您的解决方案。@Vishal16从我的测试中,会出现错误消息,因为无法在
UITextField
中启用javascript,这是一个
UITextView
?我指的是一个textView。主要问题是我使用
try-catch
块包围该代码。仍然会发生崩溃。为什么?使用Swift 5.1使
NSMutableAttributedString
使用
NSAttributedString.DocumentType.html
,我需要将代码运行到主队列中。
DispatchQueue.main.async{如果让attributedString=try?NSAttributedString(数据:数据,选项:[.documentType:NSAttributedString.documentType.html],documentAttributes:nil){textView.attributedText=attributedString}}
let string = "<h2>The bedding was hardly able to cover it.</h2>"
if !string.isEmpty{
    if let htmlData = string.data(using:String.Encoding.unicode) {
    do {
          let attributedText = try NSAttributedString(data: htmlData, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil)
           cell.textViewMessage.attributedText = attributedText
       } catch let e as NSError {
          print("Couldn't translate \(string): \(e.localizedDescription) ")
       }
 }
extension String {
     var withoutHtmlTags: String {
            let a = self.replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil)

            return a.replacingOccurrences(of: "&[^;]+;", with: "", options: String.CompareOptions.regularExpression, range: nil)
        }
    }

let string = "<h2>The bedding was hardly able to cover it.</h2>"

textUIlabel.text = string.withoutHtmlTags