Re: Difficulties with recovering NSAttributedString attachments from saved RTFD
Re: Difficulties with recovering NSAttributedString attachments from saved RTFD
- Subject: Re: Difficulties with recovering NSAttributedString attachments from saved RTFD
- From: Jeff Younker via Cocoa-dev <email@hidden>
- Date: Thu, 28 Nov 2019 03:02:49 +0100
So, I replaced...
*let* recoveredString = NSMutableAttributedString(rtfd: savedRtfd,
documentAttributes: *nil*)!
...with...
*let* fw = FileWrapper(serializedRepresentation: savedRtfd)!
*let* filePath = URL(fileURLWithPath: "/tmp/bar")
*do* {
*try* fw.write(
to: filePath,
options: [FileWrapper.WritingOptions.atomic],
originalContentsURL: *nil*)
} *catch* {
print("Error info: \(error)")
XCTFail()
}
*let* recoveredString = NSMutableAttributedString(rtfdFileWrapper:
fw, documentAttributes: *nil*)!
The RTFD gets unpacked into /tmp/bar/..., and I can see the file with the
appropriate contents:
> cat /tmp/bar/Attachment.txt
foobar
>
*Bad News*
recoveredAttachment.contents is still nil.
*Good News*
Going through the attachment's file wrapper works:
let recoveredContents = recoveredAttachment.fileWrapper?.
regularFileContents
XCTAssertEqual(String(data: recoveredContents!, encoding: .utf8),
"foobar")
*Even Better News*
Going through the attachment's file wrapper works when using the original
code. (!!)
*Conclusion*
NSTextAttachment.contents seems to be broken, deeply misleading, or (most
likely) some other magic is required to get it to read its contents.
Thank you for pointing me in the right direction Gary.
-jeff
On Wed, Nov 27, 2019 at 8:35 PM Gary L. Wade <email@hidden>
wrote:
> You want to use a file wrapper rather than data and specify the document
> type in the attributes as RTFD.
> --
> Gary L. Wade
> http://www.garywade.com/
>
> On Nov 27, 2019, at 10:18 AM, Jeff Younker via Cocoa-dev <
> email@hidden> wrote:
>
> I am having some difficulty with saving NSAttributedStrings as RTFD and
> then recovering
> them with attachments intact. I generate a string containing an attachment
> and turn that into
> RTFD. When I turn that RTFD back into an NSAttributedString, I get the
> .string back, and I
> get an attachment, but the attachment's .contents is empty.
>
> This is the smallest example I can come up with:
>
> func testSaveAndRestoreAttachment() {
> // Build up the string "deadbeef<attachment foobar>deadbeef"
> let originalContent = "foobar".data(using: .utf8)
> let originalAttachment = NSTextAttachment(
> data: originalContent, ofType: "public.plain-text")
> let originalString = NSMutableAttributedString(string: "deadbeef")
> originalString.append(NSMutableAttributedString(attachment:
> originalAttachment))
> originalString.append(NSMutableAttributedString(string: "deadbeef")
>
> // save string as RTFD (note that generated RTFD contains "foobar"
> inside.)
> let savedRtfd = originalString.rtfd(from:
> NSRange(0..<originalString.length))!
>
> // Recover string
> let recoveredString = NSAttributedString(rtfd: savedRtfd,
> documentAttributes: nil)!
> // Implementation of attachments() can be found below.
> let recoveredAttachments = attachments(from: recoveredString)
> // There *is* an attachment!
> let recoveredAttachment = recoveredAttachments[0]
> // Want to get Data("foobar") but actually get nil :(
> XCTAssertNotNil(recoveredAttachment.contents)
> }
>
> When I print out the RTFD I can see the document includes the attachment
> "foobar".
>
> I'm assuming that I need to pass some additional information when I
> call NSAttributedString(rtfd:,
> documentAttributes:)
> but I'm at a loss here.
>
> Am I missing something simple? Perhaps a magical setting to be passed in
> documentAttributes?
>
> -jeff
>
>
>
> ** This is the attachments() function used above:
>
> func attachments(from s: NSAttributedString) -> Array<NSTextAttachment> {
> var attachments: Array<NSTextAttachment> = []
> s.enumerateAttribute(.attachment, in: NSRange(0..<s.length)) {
> value, range, stop in
> guard let a = value else {
> return
> }
> attachments.append(a as! NSTextAttachment)
> }
> return attachments
> }
>
>
>
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden