Ios 在UICollectionView中复制详图索引

Ios 在UICollectionView中复制详图索引,ios,ios5,ios6,uicollectionview,uicollectionviewcell,Ios,Ios5,Ios6,Uicollectionview,Uicollectionviewcell,我在每个单元格中都有一个UICollectionView和UIImageView,现在我想添加复制标注,如Photos.app中所示: 我在UICollectionViewDelegate中看到了此方法: - (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath { return YES; } 经过几分钟的额外研

我在每个单元格中都有一个UICollectionView和UIImageView,现在我想添加复制标注,如Photos.app中所示:

我在UICollectionViewDelegate中看到了此方法:

- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath {
    return YES;
}
经过几分钟的额外研究,我发现UIMenuController类,据我所知,我必须使用它来获得菜单,但无论如何,我认为必须有更简单的方法,然后创建UIGestureRecognitor,创建、定位我的UIMenu


我走对了吗?如何实现此功能?

这是完整的解决方案:

- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath {
        return YES;
    }

- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
        if ([NSStringFromSelector(action) isEqualToString:@"copy:"])
            return YES;
        else
            return NO;
    }

- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
        if ([NSStringFromSelector(action) isEqualToString:@"copy:"]) {
            UIPasteboard *pasteBoard = [UIPasteboard pasteboardWithName:UIPasteboardNameGeneral create:NO];
            pasteBoard.persistent = YES;
            NSData *capturedImageData = UIImagePNGRepresentation([_capturedPhotos objectAtIndex:indexPath.row]);
            [pasteBoard setData:capturedImageData forPasteboardType:(NSString *)kUTTypePNG];
        }
    }

在我的例子中,我只允许在我的CollectionView中使用复制功能,如果按下了复制,我将把单元格内的图像复制到粘贴板上。

是的,您走对了。您还可以使用此技术实现除剪切、复制和粘贴之外的自定义操作

注意:iOS 7.0改变了行为

  • 在UICollectionViewCell子类中,需要添加自定义操作方法,否则将不会显示任何内容

    // Cell.m
    #import "Cell.h"
    
    @implementation Cell
    
    - (id)initWithFrame:(CGRect)frame {
        self = [super initWithFrame:frame];
        if (self) {
            // custom logic
        }
        return self;
    }
    
    - (void)customAction:(id)sender {
        NSLog(@"Hello");
    
        if([self.delegate respondsToSelector:@selector(customAction:forCell:)]) {
            [self.delegate customAction:sender forCell:self];
        }
    }
    @end
    
  • 您需要创建一个委托协议,并在每个单元格上设置它,以回调维护UICollectionView的UIController。这是因为单元格不应该与模型无关,因为它只涉及显示内容

    // Cell.h
    #import <UIKit/UIKit.h>
    
    @class Cell; // Forward declare Custom Cell for the property
    
    @protocol MyMenuDelegate <NSObject>
    @optional
    - (void)customAction:(id)sender forCell:(Cell *)cell;
    @end
    
    @interface Cell : UICollectionViewCell
    
    @property (strong, nonatomic) UILabel* label;
    @property (weak, nonatomic) id<MyMenuDelegate> delegate;
    @end
    


  • 可能有点晚了,但我可能会为那些仍在搜索的人找到一个更好的解决方案:

    在UICollectionViewController的viewDidLoad中添加项目:

    UIMenuItem *menuItem = [[UIMenuItem alloc] initWithTitle:@"Title" action:@selector(action:)];
    [[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObject:menuItem]];
    
    - (void)action:(UIMenuController*)menuController {
    
    }
    
    添加以下委托方法:

    //This method is called instead of canPerformAction for each action (copy, cut and paste too)
    - (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
            if (action == @selector(action:)) {
                return YES;
            }
            return NO;
        }
        //Yes for showing menu in general
        - (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath {
            return YES;
        }
    
    子类UICollectionViewCell(如果尚未创建)。添加为项目指定的方法:

    UIMenuItem *menuItem = [[UIMenuItem alloc] initWithTitle:@"Title" action:@selector(action:)];
    [[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObject:menuItem]];
    
    - (void)action:(UIMenuController*)menuController {
    
    }
    
    这样你就不需要任何“成为第一反应者”或其他方法。所有操作都在一个地方,如果调用一个通用方法并将单元格本身作为参数,则可以轻松处理不同的单元格

    编辑:不知何故,uicollectionview需要此方法的存在(此方法不是为您的自定义操作调用的,我认为uicollectionview只是检查是否存在)


    在customAction中,发送方是UIMenuController。如何从中获取对单元格的引用?@drhr您找到解决方案了吗?看起来这个Stackoverflow对iOS 7很有帮助。需要在自定义单元格中调用:对于iOS 7,这是过度设计的。更简单的是:在@PaulSolt上查看完整代码的答案:解决了我的问题,我从三四天就开始尝试了!Insort,谢谢你节省了我的时间。是的,你只需要这三种方法。其他任何内容都是不必要的。谢谢,我在编写UIMenuItem*menuItem=[[UIMenuItem alloc]initWithTitle:@“编辑”操作:@selector(editPlate:)]时尝试了您的解决方案;但是,它要求我有一个方法editPlate,但我想使用performAction,这样我就可以知道单元格id。如何定位菜单项?@ThinkBonobo谢谢你的评论,但实际上这是我的编辑,他只是提高了英语;-)。我觉得这个答案特别有用。但是,我仍然必须创建一个引用回集合控制器的委托,以便刷新集合控制器。另外,请注意编辑。需要空的performAction类。
    - (void)action:(UIMenuController*)menuController {
    
    }
    
    - (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
    
    }