如何从NSAttributedString中获取图像数据?

13

我有一个NSTextView。我将图像粘贴到其中并进行查看。当我获取文本视图的NSAttributedString的NSTextAttachment时,它的文件包装器为nil。如何获取粘贴到文本视图中的图像数据?

我正在使用NSAttributedString的类别来获取文本附件。如果可能,我希望不必写入磁盘。

- (NSArray *)allAttachments
{
    NSError *error = NULL;
    NSMutableArray *theAttachments = [NSMutableArray array];
    NSRange theStringRange = NSMakeRange(0, [self length]);
    if (theStringRange.length > 0)
    {
        NSUInteger N = 0;
        do
        {
            NSRange theEffectiveRange;
            NSDictionary *theAttributes = [self attributesAtIndex:N longestEffectiveRange:&theEffectiveRange inRange:theStringRange];
            NSTextAttachment *theAttachment = [theAttributes objectForKey:NSAttachmentAttributeName];
            if (theAttachment != NULL){
                NSLog(@"filewrapper: %@", theAttachment.fileWrapper);
                [theAttachments addObject:theAttachment];
            }
            N = theEffectiveRange.location + theEffectiveRange.length;
        }
        while (N < theStringRange.length);
    }
    return(theAttachments);
}

你能否添加代码,显示你正在做什么,如何尝试访问图像数据等。如果没有这些信息,试图帮助你的人只会猜测。 - CRD
3个回答

12
  1. 枚举附件。[NSTextStorage enumerateAttribute:...]
  2. 获取附件的文件包装器。
  3. 将内容写入URL。

[textStorage enumerateAttribute:NSAttachmentAttributeName
                        inRange:NSMakeRange(0, textStorage.length)
                        options:0
                     usingBlock:^(id value, NSRange range, BOOL *stop)
 {
     NSTextAttachment* attachment = (NSTextAttachment*)value;
     NSFileWrapper* attachmentWrapper = attachment.fileWrapper;
     [attachmentWrapper writeToURL:outputURL options:NSFileWrapperWritingAtomic originalContentsURL:nil error:nil];
     (*stop) = YES; // stop so we only write the first attachment
 }];

这段示例代码只会将第一个附件写入outputURL。


现在我的文件包装器已经设置好了。我接受了这个答案,因为如果你可以写入磁盘的话,它是有效的。 - joels

3
您可以从附件单元格中获取包含的NSImage。
最简示例:
// assuming we have a NSTextStorage* textStorage object ready to go, 
// and that we know it contains an attachment at some_index
// (in real code we would probably enumerate attachments).

NSRange range;
NSDictionary* textStorageAttrDict = [textStorage attributesAtIndex:some_index
                                             longestEffectiveRange:&range 
                                                           inRange:NSMakeRange(0,textStorage.length)];

NSTextAttachment* textAttachment = [textStorageAttributesDictionary objectForKey:@"NSAttachment"];
NSTextAttachmentCell* textAttachmentCell = textAttachment.attachmentCell;
NSImage* attachmentImage = textAttachmentCell.image;

编辑:

仅限于OS X(AppKit版本)


attachmentCell 属性在 NSTextAttachment 类中似乎不存在,除非我漏掉了什么。 - Craig Otis
@Craig Otis 看起来这只存在于 OS X 版本中,而不是 iOS 版本(UIKit)。 - Emerald Weapon

3

@EmeraldWeapon的答案适用于Objective-C,但在Swift中会有问题,因为在Swift中attachmentCell不是一个NSTextAttachmentCell,而是一个NSTextAttachmentCellProtocol?(它不提供.image)- 因此在访问.image之前,您需要将其强制转换为具体实例:

func firstImage(textStorage: NSTextStorage) -> NSImage? {
    for idx in 0 ..< textStorage.string.count {
        if
            let attr = textStorage.attribute(NSAttributedString.Key.attachment, at: idx, effectiveRange: nil),
            let attachment = attr as? NSTextAttachment,
            let cell = attachment.attachmentCell as? NSTextAttachmentCell,
            let image = cell.image {

            return image
        }
    }
    return nil
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接