【问题标题】:SVG NSTextAttachment text encoding issueSVG NSTextAttachment 文本编码问题
【发布时间】:2015-10-19 22:26:51
【问题描述】:

为了能够将 SVG 图像用于从 HTML 创建的属性字符串,我愿意

func createAttributedString(string: String) -> NSMutableAttributedString {
    let data = string.dataUsingEncoding(NSUTF8StringEncoding)

    let options = [NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType,
                   NSCharacterEncodingDocumentAttribute: NSUTF8StringEncoding]

    let attributedString = (try! NSMutableAttributedString(
                                    data: data!,
                                    options: options as! [String : AnyObject],
                                    documentAttributes: nil))
    var svgImageAttributes: [NSTextAttachment] = []
    var svgImageRanges: [NSRange] = []
    attributedString.enumerateAttribute("NSAttachment", inRange: NSMakeRange(0, attributedString.length), options: []) { (attribute, range, stop) -> Void in


        if let attribute = attribute as? NSTextAttachment, fileType = attribute.fileType where fileType == "public.svg-image"{
            svgImageAttributes.append(attribute)
            svgImageRanges.append(range)
        }

    }
    let array = Array(zip(svgImageAttributes, svgImageRanges))

    for i in array {
        let (attachment, range) = i
        if let imageData = attachment.fileWrapper?.serializedRepresentation {
            var chapterTextAttachment:ChapterImageTextAttachment!
            if let preferedImageWidth = self.preferedImageWidth{
                chapterTextAttachment = ChapterImageTextAttachment(data: imageData, ofType: attachment.fileType, desiredWidth: preferedImageWidth)

            } else {
                chapterTextAttachment = ChapterImageTextAttachment(data: imageData, ofType: attachment.fileType)
            }
            let string = NSMutableAttributedString(string: attributedString.string.substringWithRange(attributedString.string.rangeFromNSRange(range)!), attributes: ["NSAttachment": chapterTextAttachment])
            let paragraphStyle = NSMutableParagraphStyle()
            paragraphStyle.alignment = .Center
            string.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: range)
            attributedString.replaceCharactersInRange(range, withAttributedString: string)
        }
    }
    return attributedString
}

ChapterImageTextAttachment

class ChapterImageTextAttachment: NSTextAttachment {
    let width:CGFloat
    var size: CGSize! {
        set{
            self.bounds = CGRectMake(0,0,newValue.width, newValue.height)
        }

        get{
            return self.bounds.size
        }
    }


    init(data contentData: NSData?, ofType uti: String?, desiredWidth:CGFloat = 320) {
        self.width = desiredWidth
        super.init(data: contentData, ofType: uti)
        if let contentData = contentData {
            let string = String(data: contentData, encoding: NSASCIIStringEncoding)!
            let svgrender = SVGRenderer(string: self.fixSVGString(string))

            let image = svgrender.asImageWithSize(CGSizeMake(self.width,  1000), andScale: UIScreen.mainScreen().scale)
            self.image = image
            self.size = image.size

        }
    }

    override func attachmentBoundsForTextContainer(textContainer: NSTextContainer?, proposedLineFragment lineFrag: CGRect, glyphPosition position: CGPoint, characterIndex charIndex: Int) -> CGRect {
        return CGRectInset(self.bounds, 0, 20)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func fixSVGString(string:String) -> String {
        var result: String?
        if string.hasPrefix("rtfd"){
            let startIndex = string.rangeOfString("<?xml")?.startIndex
            let stopIndex = string.rangeOfString("</svg>")?.endIndex

            result = string.substringWithRange(startIndex! ..< stopIndex!)

        } else {
            result = string
        }
        return result!
    }
}

它可以工作,但有一个缺陷:非 ASCII 字符被破坏。

最重要的是,HTML 和 SVG 都是 UTF-8 编码的,但在附件类中,我必须将 SVG 字符串实例化为 ASCII

let string = String(data: contentData, encoding: NSASCIIStringEncoding)!

否则它将为零。

fixSVGString(_:) 删除了一些已添加的富文本信息。

如何对 SVG 图像强制执行 UTF-8 编码?

【问题讨论】:

    标签: ios swift cocoa-touch svg nsattributedstring


    【解决方案1】:

    如果 String 返回 nil,则意味着它无法使用 UTF-8 编码进行转换。 ASCII“有效”的事实可能只是意味着它按原样获取字节,因此任何非 ASCII 字符都是先前编码所具有的任何字节值,而这些在以后会被误解。

    因此,很简单,您要转换的数据不是 UTF-8,也不是 ASCII。您正在寻找“rtfd”的事实意味着包装数据可能是 RTF 格式,它将有自己的字符集。 RTF 规范可能有一个 \ansi 指令(我认为是 Code Page 1252)、\mac(Mac OS Roman)或 \pc(Code Page 437)来指定内容的字符集。默认值为 \ansi。字符集有些混乱。

    尝试使用 NSWindowsCP1252StringEncoding,而不是 NSASCIIStringEncoding。或者使用参数为 437 的 CFStringConvertWindowsCodepageToEncoding() 并查看生成的编码是否效果更好。

    如果您一开始没有 NSTextAttachment,我会从数据中创建一个 NSAttributedString(使用 NSRTFDTextDocumentType 作为文档类型),然后看看您是否可以在其中找到 NSTextAttachment,并以这种方式获取数据通过内容属性。

    但是你确实有一个 NSTextAttachment...所以也许它就像获取 NSTextAttachment 的“内容”属性而不是 fileWrapper 的 serializedRepresentation 一样简单。还是只返回一个链接?

    【讨论】:

    • rtfd\0\0\0\0\u{03}\0\0\0\u{04}\0\0\0\u{02}\0\0\0..\u{13}\0\0\0__@PreferredName@__\u{17}\0\0\0__@UTF8PreferredName@__\u{01}\0\0\0.ºƒ\0\0\u{17}\0\0\0\u{17}\0\0\0&amp;\0\0\0\u{01}\0\0\0\0\0\0€\u{17}t\0\0“\u{0F}
    • 哦。这看起来像是来自 NSFileWrapper 的私有数据格式——参见 blog.simonrodriguez.fr/articles/…。因此,直接解析它可能不是最好的主意。 fileWrapper 的 regularFileContents 属性怎么样?您想要的数据应该可以直接从 NSTextAttachment 或 NSFileWrapper 某处获得。
    猜你喜欢
    • 2012-01-03
    • 2011-09-17
    • 2011-04-30
    • 2016-08-02
    • 2010-10-30
    • 2011-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多