Re: Difficulties with recovering NSAttributedString attachments from saved RTFD

2019-11-27 Thread Jeff Younker via Cocoa-dev
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 
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 <
> cocoa-dev@lists.apple.com> 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 "deadbeefdeadbeef"
>  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..
>  // 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 {
>var attachments: Array = []
>s.enumerateAttribute(.attachment, in: NSRange(0..value, range, stop in
>guard let a = value else {
>   return
>}
>attachments.append(a as! NSTextAttachment)
>}
>return attachments
> }
>
>
>
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Difficulties with recovering NSAttributedString attachments from saved RTFD

2019-11-27 Thread Gary L. Wade via Cocoa-dev
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 
>  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 "deadbeefdeadbeef"
>  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.. 
>  // 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 {
>var attachments: Array = []
>s.enumerateAttribute(.attachment, in: NSRange(0..value, range, stop in
>guard let a = value else {
>   return
>}
>attachments.append(a as! NSTextAttachment)
>}
>return attachments
> }

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Difficulties with recovering NSAttributedString attachments from saved RTFD

2019-11-27 Thread Jeff Younker via Cocoa-dev
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 "deadbeefdeadbeef"
  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.. Array {
var attachments: Array = []
s.enumerateAttribute(.attachment, in: NSRange(0..https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com