如何检测 NSTextAttachment 上的触摸 [英] How to detect touch on NSTextAttachment

查看:21
本文介绍了如何检测 NSTextAttachment 上的触摸的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 iOS 上检测用户何时点击 NSTextAttachment 的最佳方法是什么?

What is the best way to detect when user taps on NSTextAttachment on iOS?

我认为其中一种方法是检查 carret 位置上的字符是否为 NSAttachmentCharacter,但它似乎不正确.

I think that one of the ways would be checking for the character on carret's position whether it is NSAttachmentCharacter, but it just doesn't seem right.

我也试过 UITextViewDelegate 方法:-(BOOL)textView:(UITextView *)textView shouldInteractWithTextAttachment:(NSTextAttachment *)textAttachment inRange:(NSRange)characterRange 但是当 textView.editable=YES

I've also tried UITextViewDelegate method: -(BOOL)textView:(UITextView *)textView shouldInteractWithTextAttachment:(NSTextAttachment *)textAttachment inRange:(NSRange)characterRange but it's not invoked when textView.editable=YES

推荐答案

委托方法确实有效,但仅当附件在图像属性中具有图像且可编辑 = 否!因此,如果您将图像从其他地方粘贴到属性字符串中,则数据似乎最终存储在 fileWrapper 中,下次将属性字符串放回 textView 时,图像属性为零,布局管理器或任何获取图像的内容来自文件包装器.

The delegate method does work but ONLY if the attachment has an image in the image attribute AND if editable = NO! So if you have an image pasted in to the attributedString from somewhere else it seems the data ends up being stored in the fileWrapper and next time you put the attributedString back into the textView the image attribute is nil and the layout manager or whatever gets the image from the fileWrapper.

文档中的某处确实提到 NSTextAttachment 中没有用于持久化图像属性的方法.

Somewhere in the documents it does mention that there are no methods in NSTextAttachment for persistence of the image attribute.

要测试这一点,请尝试从 Photo 应用程序复制一张照片并将其粘贴到您的 textView 中,现在如果您按住手指,您应该会看到默认菜单弹出.现在,如果你保存这个富文本,说到一个核心数据实体,然后检索它,图像属性将为 nil,但图像数据将在 attachment.fileWrapper.regularFileContents

To test this try copy a photo from the Photo app and paste it into your textView, now if you hold down your finger on it you should see the default menu pop up. Now if you save this rich text, say into a Core Data entity and then retrieve it the image attribute will be nil but the image data will be in attachment.fileWrapper.regularFileContents

这很痛苦,我很想知道工程师的意图.所以你似乎有两个选择.

Its a pain, and I would love to know the engineers intention. So you have two options it seems.

  1. 创建您自己的自定义 NSTextAttachment 并包含用于存档图像和其他设置的方法(请告诉我如何解决此问题)
  2. 每次在将字符串放回 textView 之前,您都会找到所有附件并重新创建图像属性,如下所示:

  1. Create your own custom NSTextAttachment and include methods for archiving the image and other settings (PLEASE SHOW ME HOW TOO WHEN YOU FIGURE THIS ONE OUT)
  2. Every time prior to putting your string back into textView you find all the attachments and recreated the image attribute like so:

attachment.image = [UIImage imageWithData:attachment.fileWrapper.regularFileContents];

attachment.image = [UIImage imageWithData:attachment.fileWrapper.regularFileContents];

请记住,这样做的副作用是使 fileWrapper 无效.我想调整图像大小,但也要保留原始图像,这样我就不会失去完整的分辨率.我认为这样做的唯一方法可能是继承 NSTextAttachment.

Bear in mind the side effect of doing this is invalidating the fileWrapper. I want to resize the image but also keep the original so I don't loose the full resolution. I think the only way of doing this might be to subclass NSTextAttachment.

我想出了如何创建自定义 NSTextAttachments - 这是给感兴趣的人的链接 http://ossh.com.au/design-and-technology/software-development/implementing-rich-text-with-images-on-os-x-and-ios/

I figured out how to create the custom NSTextAttachments - here is a link for those interested http://ossh.com.au/design-and-technology/software-development/implementing-rich-text-with-images-on-os-x-and-ios/

编辑 2:要在编辑模式下自定义菜单,请参阅以下 Apple 文档,问题是touchEnded"似乎从未被调用,因此您可能必须尝试使用​​ touchesBegan.不过要小心,不要干扰默认的编辑行为.

EDIT 2: To customise the menu when in Edit Mode see the following Apple documents, the issue is 'touchEnded' never seems to get called so you might have to try using touchesBegan. Careful you don't interfere with the default editing behaviour though.

https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/AddingCustomEditMenuItems/AddingCustomEditMenuItems.html

注意在下面的代码中需要在//选择管理注释后添加code来判断哪个字符被触摸了,检查它是否是特殊的文本附件字符和然后修改编辑菜单或执行一些其他操作.

Note that in the code below you would need to add code after // selection management comment to determine which character was touched, check if it is the special text attachment character and then modify the edit menu or take some other action.

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *theTouch = [touches anyObject];

    if ([theTouch tapCount] == 2  && [self becomeFirstResponder]) {

        // selection management code goes here...

        // bring up edit menu.
        UIMenuController *theMenu = [UIMenuController sharedMenuController];
        CGRect selectionRect = CGRectMake (currentSelection.x, currentSelection.y, SIDE, SIDE);
        [theMenu setTargetRect:selectionRect inView:self];
        [theMenu setMenuVisible:YES animated:YES];

    }
}

或者,您可以通过添加菜单项然后修改 canPerformAction 方法来添加自定义菜单.

Alternately you could add a custom menu by adding the menu item and then modifying the canPerformAction method.

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    LOG(@"canPerformAction: called");

    if (action == @selector(viewImage)) {
       // Check the selected character is the special text attachment character

       return YES;
    }
   return NO;
}

这里有一些附加代码,但有点繁琐.第二种方法只是在检测到附件时禁用默认编辑菜单.

Here is some addition code but its a bit fussy. Second method just disables the default edit menu if an attachment is detected.

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    FLOG(@"touchesBegan:withEvent: called");

    if (self.selectedRange.location != NSNotFound) {
        FLOG(@" selected location is %d", self.selectedRange.location);

        int ch;

        if (self.selectedRange.location >= self.textStorage.length) {
            // Get the character at the location
            ch = [[[self textStorage] string] characterAtIndex:self.selectedRange.location-1];
        } else {
            // Get the character at the location
            ch = [[[self textStorage] string] characterAtIndex:self.selectedRange.location];
        }

        if (ch == NSAttachmentCharacter) {
            FLOG(@" selected character is %d, a TextAttachment", ch);
        } else {
            FLOG(@" selected character is %d", ch);
        }
    }

}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    FLOG(@"canPerformAction: called");

        FLOG(@" selected location is %d", self.selectedRange.location);
        FLOG(@" TextAttachment character is %d", NSAttachmentCharacter);

        if (self.selectedRange.location != NSNotFound) {

            int ch;

            if (self.selectedRange.location >= self.textStorage.length) {
                // Get the character at the location
                ch = [[[self textStorage] string] characterAtIndex:self.selectedRange.location-1];
            } else {
                // Get the character at the location
                ch = [[[self textStorage] string] characterAtIndex:self.selectedRange.location];
            }

            if (ch == NSAttachmentCharacter) {
                FLOG(@" selected character is %d, a TextAttachment", ch);
                return NO;
            } else {
                FLOG(@" selected character is %d", ch);
            }

            // Check for an attachment
            NSTextAttachment *attachment = [[self textStorage] attribute:NSAttachmentAttributeName atIndex:self.selectedRange.location effectiveRange:NULL];
            if (attachment) {
                FLOG(@" attachment attribute retrieved at location %d", self.selectedRange.location);
                return NO;
            }
            else
                FLOG(@" no attachment at location %d", self.selectedRange.location);
        }
    return [super canPerformAction:action withSender:sender];
}

这篇关于如何检测 NSTextAttachment 上的触摸的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆