如何从 NSAttributedString 获取图像数据

Posted

技术标签:

【中文标题】如何从 NSAttributedString 获取图像数据【英文标题】:How do you get the image data from NSAttributedString 【发布时间】:2014-04-20 18:33:59 【问题描述】:

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

我正在使用 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);

【问题讨论】:

您能否添加代码以准确显示您在做什么、您如何尝试访问图像数据等。如果没有这些信息,人们试图帮助您的只是猜测。 【参考方案1】:
    枚举附件。 [NSTextStorage enumerateAttribute:...] 获取附件的文件包装器。

    写入一个 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。

【讨论】:

现在我的文件包装器正在设置中。我接受了这个答案,因为如果您可以写入磁盘,它就可以工作。【参考方案2】:

您可以从附件单元格中获取包含的 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 它似乎只存在于 OS X 版本,而不是 ios 版本(UIKit)。【参考方案3】:

@EmeraldWeapon 的 answer 对 Objective-C 有好处,但在 Swift 中就不行了,因为在 Swift 中,attachmentCell 不是NSTextAttachmentCell,而是NSTextAttachmentCellProtocol?(这不是 em> 提供 .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

【讨论】:

以上是关于如何从 NSAttributedString 获取图像数据的主要内容,如果未能解决你的问题,请参考以下文章

你如何使用 NSAttributedString?

将 NSColor 从 NSAttributedString 转换为 UIColor

UICollectionView 从 NSAttributedString 图像滚动滞后/断断续续

从html创建nsattributedstring时ios7字体大小发生变化

你如何使用NSAttributedString?

如何在 SwiftUI 中使用 NSAttributedString 和 ScrollView?