NSAttributedString initWithData和NSHTMLTextDocumentType如果不在主线程上则崩溃

时间:2015-03-07 14:31:55

标签: ios cocoa cocoa-touch nsattributedstring nsoperationqueue

调用

NSAttributedString * as = [[NSAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUTF8StringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)} documentAttributes:nil error:nil];

在主线程之外,导致崩溃

1   0x194b861fc <redacted>
2   0x19801d31c <redacted>
3   0x198010eb4 _os_once
4   0x19801aa2c pthread_once
5   0x195a0858c <redacted>
6   0x195a07c78 WebKitInitialize
7   0x18bb38918 <redacted>
8   0x10020cdf0 _dispatch_client_callout
9   0x10020dcfc dispatch_once_f
10  0x1977f8bd0 <redacted>
11  0x1978009ac <redacted>
12  0x19780bdb8 <redacted>
13  0x1940b259c _NSReadAttributedStringFromURLOrData
14  0x1940b0eb4 <redacted>
15  0x1001041a0 -[MPMPostTextBrickCell attributedTextWithHTMLString:]
16  0x100103d3c __39-[MPMPostTextBrickCell setupWithBrick:]_block_invoke
17  0x187fb3508 <redacted>
18  0x187f04c94 <redacted>
19  0x187ef461c <redacted>
20  0x187fb626c <redacted>
21  0x10020cdf0 _dispatch_client_callout
22  0x100217854 _dispatch_queue_drain
23  0x100210120 _dispatch_queue_invoke
24  0x10021975c _dispatch_root_queue_drain
25  0x10021af18 _dispatch_worker_thread3
26  0x1980192e4 _pthread_wqthread
27  0x198018fa8 start_wqthread

当我没有指定属性低于其工作时

NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,

我需要在后台线程上解析字符串,但这使得它无法实现:(

2 个答案:

答案 0 :(得分:18)

文档非常明确。

  

不应从后台线程调用HTML导入程序(即,选项字典包含NSDocumentTypeDocumentAttribute,其值为NSHTMLTextDocumentType)。它将尝试与主线程同步,失败和超时。从主线程调用它可以工作(但如果HTML包含对外部资源的引用,仍然可以超时,这应该不惜一切代价避免)。 HTML导入机制用于实现降价(即文本样式,颜色等),而不是用于常规HTML导入。

只能在主线程上使用HTML导入器(NSHTMLTextDocumentType)。

(来源:Apple's documentation

答案 1 :(得分:2)

回答这个问题可能为时已晚,但可能有助于其他人。

实际上 NSAttributedString NSHTMLTextDocumentType 必须在主队列或全局队列上运行异步

您可以在后台线程中使用它,但必须在全局或主队列上调度包含 NSAttributedString 的初始化程序的代码块。例如:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { () -> Void in




            print("Started on \(NSThread.currentThread())")

            let encodedData = "<font color=\"red\">Hello</font>".dataUsingEncoding(NSUTF8StringEncoding)!
            let attributedOptions : [String: AnyObject] = [
                NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                NSCharacterEncodingDocumentAttribute: NSUTF8StringEncoding
            ]


            let attributedString = (try? NSAttributedString(data: encodedData, options: attributedOptions, documentAttributes: nil) ?? NSAttributedString(string: ""))



            print("Finished")

        }