为啥 textView:shouldInteractWithTextAttachment:inRange: 永远不会在 UITextView 委托上被调用?

Posted

技术标签:

【中文标题】为啥 textView:shouldInteractWithTextAttachment:inRange: 永远不会在 UITextView 委托上被调用?【英文标题】:Why is textView:shouldInteractWithTextAttachment:inRange: never getting called on UITextView delegate?为什么 textView:shouldInteractWithTextAttachment:inRange: 永远不会在 UITextView 委托上被调用? 【发布时间】:2013-10-23 09:28:18 【问题描述】:

有人使用这个委托方法吗?我收到回调

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView

但不是这个。该文档似乎对它的用途有点模棱两可

- (BOOL)textView:(UITextView *)textView shouldInteractWithTextAttachment:(NSTextAttachment *)textAttachment inRange:(NSRange)characterRange

根据网络上的文档,这是它的用途:

讨论 如果用户点击或长按文本附件并且其图像属性不为零,则文本视图调用此方法。此方法的实现是可选的。除了显示与文本内联的文本附件外,您还可以使用此方法触发操作。

这里是 Xcode 5 文档:

询问代理指定的文本视图是否应该在给定的文本范围内显示提供的文本附件。 当数据检测器在其文本容器中识别出文本附件字符时,文本视图调用此方法。此方法的实现是可选的。除了显示与给定范围内的文本内联的文本附件外,您还可以使用此方法触发替代操作。

编辑:

嗯,好的,我找到了问题所在。如果我从 ios 粘贴图像,则它可以工作,但是如果图像是从 OS X 粘贴的,则它不会。尽管图像似乎在文本视图中正确显示,但在两个平台上使用的实际附件格式似乎并不完全相同。仔细检查后,iOS 上的 NSTextAttachment 类似乎与 OS X 上的不同。

如果有人可以在这里阐明跨平台兼容性,请这样做。

此外,如果我在 iOS 上粘贴图像后保存属性字符串,然后检索它并在 UITextView 中显示它,则不再可能与附件交互。如果内容为 nil,则在存储图像时,图像实际上被放置在内容中。因此,也许我将不得不遍历所有附件以检查哪些数据存储在哪里,特别是要找出 OS X 和 iOS 平台之间的行为差​​异。

进一步编辑: 仅当附件图像不为零时才调用该方法,并且尽管显示了图像,但实际图像属性实际上可以为零,我真傻!无论如何,修复似乎是检查属性字符串中的所有附件并将它们的图像属性设置为某些东西,通常是 fileWrapper 的内容。默认的 NSTextAttachment 行为似乎是在归档时将图像存储在 fileWrapper 中,但在未归档时它不会执行相反的操作。无论如何,我想在附件中保留原始图像,但根据设备显示原始图像的适当缩放版本!

【问题讨论】:

【参考方案1】:

最主要的是文本视图的editable 属性必须为NO,它的selectable 属性必须为YES。这些是调用此委托方法的唯一情况。如果您收到shouldBeginEditing,那么您的文本字段是可编辑的,这正是它不能编辑的。

【讨论】:

谢谢,但我认为这不是问题,请参阅我上面的附加编辑重新设置图像属性。似乎取消归档字符串不会设置附件图像属性。 也许吧,但这不是你问的。你问shouldInteractWithTextAttachment 是否真的被调用了。是的,我一直都在使用它,并且我正确地告诉了您调用它的特殊情况 - 我推断了为什么在您的情况下没有调用它(文本视图的 editable 是 YES)。文本附件的存档和恢复是一个完全不同的问题。 谢谢,Matt,非常感谢您的回复,您应该在第一个回答中说“是的,我一直都在使用它”。无论如何,您的回答足以让我更深入地研究为什么,即使按照您的建议进行设置,我仍然没有收到回调。事实证明,未设置图像属性的默认取消归档行为导致了我的问题。再次感谢您抽出宝贵时间。【参考方案2】:

这是我在从归档数据中恢复 UITextView 的属性字符串时确保设置 NSTextAttachments 图像属性的方法(在这种情况下,每当用户从核心数据存储中选择记录时)。

我将UITextView 设置为textStorage 的代表,并在didProcessEditing 中查找可能已添加的任何附件,然后检查其图像属性是否已设置。我还在图像上设置缩放因子,以确保图像适合设备缩放。

这样我不会丢失图像的原始分辨率,如果用户想要更详细地查看它,我会提供从弹出菜单中在图像浏览器窗口中打开它的选项。

希望这对其他人有所帮助。

编辑: 在此处查看有关 NSTextView 和 UITextView 的更多详细信息http://ossh.com.au/design-and-technology/software-development/

- (void)textStorage:(NSTextStorage *)textStorage didProcessEditing:(NSTextStorageEditActions)editedMask range:(NSRange)editedRange changeInLength:(NSInteger)delta 
    //FLOG(@"textStorage:didProcessEditing:range:changeInLength: called");

    [textStorage enumerateAttributesInRange:editedRange options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired usingBlock:
     ^(NSDictionary *attributes, NSRange range, BOOL *stop) 

         // Iterate over each attribute and look for a Font Size
         [attributes enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) 
             if ([[key description] isEqualToString:NSAttachmentAttributeName]) 
                 NSTextAttachment *attachment = obj;

                 //Reset the image attribute and scale for the device size if necessary
                 [self resetAttachmentImage:attachment];
             

         ];
     ];

- (void)resetAttachmentImage:(NSTextAttachment*)attachment 
    UIImage *image = [attachment image];
    float factor = 2;

    if (image == nil) 
        if (attachment.fileWrapper == nil || !attachment.fileWrapper.isRegularFile) 
            attachment.image = [UIImage imageNamed:@"unknown_attachment.png"];
            return;
        
        //Usually retrieved from store
        image = [UIImage imageWithData:attachment.fileWrapper.regularFileContents];
     else 
        // Convert any pasted image
        image = [UIImage imageWithData:UIImagePNGRepresentation(image)];
    

    float imgWidth = image.size.width;

    // If its wider than the view scale it to fit
    if (imgWidth > _viewWidth) 
        factor = imgWidth / _viewWidth + 0.5;

        attachment.image = [UIImage imageWithData:UIImagePNGRepresentation(image) scale:factor];
     else 
        attachment.image = [UIImage imageWithData:UIImagePNGRepresentation(image) scale:_scale];
    


【讨论】:

以上是关于为啥 textView:shouldInteractWithTextAttachment:inRange: 永远不会在 UITextView 委托上被调用?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?

为啥需要softmax函数?为啥不简单归一化?

为啥 g++ 需要 libstdc++.a?为啥不是默认值?

为啥或为啥不在 C++ 中使用 memset? [关闭]

为啥临时变量需要更改数组元素以及为啥需要在最后取消设置?

为啥 CAP 定理中的 RDBMS 分区不能容忍,为啥它可用?