UIMenuController sharedMenuController - 用于uicollectionview的自定义menuitem不显示在ios 7中

时间:2013-09-20 00:13:49

标签: objective-c uicollectionview ios7 uimenucontroller

我正在使用UIMenuItemUICollectionView单元长按中执行自定义操作。 这与iOS 6完美配合,但现在我将我的应用程序转换为iOS 7和Xcode 5,但它无法正常工作。自定义项目未显示。

UIMenuItem *menuItem = [[UIMenuItem alloc] initWithTitle:@"Unfavorite"
                                                  action:@selector(unFavorite:)];
[[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObject:menuItem]];
[UIMenuController sharedMenuController].menuVisible = YES;

- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender;
{
    //do not show default itens like copy, paste....
    [self becomeFirstResponder];
    return NO;
}


- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
// The selector(s) should match your UIMenuItem selector
    if (action == @selector(unFavorite:)) {
         return YES;
    }
    return NO;
}

- (void)collectionView:(UICollectionView *)collectionView
     performAction:(SEL)action
forItemAtIndexPath:(NSIndexPath *)indexPath
        withSender:(id)sender {

}

 - (BOOL)collectionView:(UICollectionView *)collectionView
 shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath {

    myIndexPath = indexPath;
    return YES;
}

4 个答案:

答案 0 :(得分:8)

我不知道iOS 6,但在iOS 7中它非常简单。您只需要三个标准集合视图委托菜单处理方法,以及单元子类中的操作方法。没有必要与第一响应者或类似的东西一起玩。所以,例如(在这个例子中,Copy是一个标准项目,但是我已经添加到菜单中):

// collection view delegate:

- (BOOL)collectionView:(UICollectionView *)collectionView 
        shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath {
    UIMenuItem* mi = [[UIMenuItem alloc] initWithTitle:@"Capital" 
                      action:NSSelectorFromString(@"capital:")];
    [[UIMenuController sharedMenuController] setMenuItems:@[mi]];
    return YES;
}

- (BOOL)collectionView:(UICollectionView *)collectionView 
        canPerformAction:(SEL)action 
        forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
    return (action == NSSelectorFromString(@"copy:") || 
            action == NSSelectorFromString(@"capital:"));
}

- (void)collectionView:(UICollectionView *)collectionView 
        performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath 
        withSender:(id)sender {
    // in real life, would do something here
    NSString* state = (self.sectionData)[indexPath.section][indexPath.row];
    if (action == NSSelectorFromString(@"copy:"))
        NSLog(@"copying %@", state);
    else if (action == NSSelectorFromString(@"capital:"))
        NSLog(@"fetching the capital of %@", state);
}

// cell subclass:

-(void)capital:(id)sender {
    // find my collection view
    UIView* v = self;
    do {
        v = v.superview;
    } while (![v isKindOfClass:[UICollectionView class]]);
    UICollectionView* cv = (UICollectionView*) v;
    // ask it what index path we are
    NSIndexPath* ip = [cv indexPathForCell:self];
    // talk to its delegate
    if (cv.delegate && 
        [cv.delegate respondsToSelector:
             @selector(collectionView:performAction:forItemAtIndexPath:withSender:)])
        [cv.delegate collectionView:cv performAction:_cmd
             forItemAtIndexPath:ip withSender:sender];
}

答案 1 :(得分:1)

我使用类似StackOverflow问题中的图像和示例更新了我的iOS 7.0解决方案。

我使用ARC和委托的弱引用。似乎适用于iOS 6.0和iOS 7.0

https://stackoverflow.com/a/13618212/276626

答案 2 :(得分:1)

我在UICollectionView上添加了一个searchBar,其中UIMenuController的结果是MIA。经过两天的试用和错误我认为终于找到了一种方法让它发挥作用。

问题(在iOS7上运行):

    调用 UICollectionViewController 上的
  1. UILongPressGestureRecognizer
  2. MenuController显示
  3. 添加 UISearchBar ,并在collectionView重新加载其数据后立即:不再有菜单控制器
  4. 认为使其工作的诀窍是从searchBar中明确删除第一响应者状态

    - (void)longPressGestureDetected:(UILongPressGestureRecognizer *)gesture {
    if(gesture.state == UIGestureRecognizerStateBegan) {
        CGPoint touchPoint = [gesture locationInView:gesture.view];
        NSInteger index = [self.collectionView indexPathForItemAtPoint:touchPoint].item;
        if(index >= 0 && index < self.documents.count) {
            // dismiss searchBar
            [self.searchBar resignFirstResponder];
            [self becomeFirstResponder];
            // select the right document
            //[self.documentManager selectDocumentWithIndex:index];
            // show menu
            UIMenuController *menu = [UIMenuController sharedMenuController];
            menu.menuItems = [self defaultMenuItems];
            [menu setTargetRect:CGRectMake(touchPoint.x, touchPoint.y, 0, 0) inView:gesture.view];
            [gesture.view becomeFirstResponder];
            [menu update];
            [menu setMenuVisible:YES animated:YES];
        }
    }
    

    当然,控制器中也有这些响应者状态方法:

    - (BOOL)canBecomeFirstResponder { return YES; }
    - (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
        if(action == @selector(renameDocument:)) {
            return YES;
        } else {
            return NO;
        }
    }
    
    - (NSArray*)defaultMenuItems {
        // add menu items
        UIMenuItem *renameItem      = [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"Rename", @"Rename Menu Item")           action:@selector(renameDocument:)];
        return @[renameItem];
    }
    

答案 3 :(得分:0)

如尼古拉斯所述,相关的代码如下。注意:这会导致集合VC永远不会释放(意味着永远不会调用dealloc)。从长远来看,我们需要找到更好的解决方案,或者直到Apple修复此iOS 7.x错误。

在NibCell.h中

@protocol CellToVCDelegate <NSObject>

@optional

- (void)deleteActivity:(id)sender ;
- (void)shareActivity:(id)sender;

@end

@interface NibCell : UICollectionViewCell{

    id <CellToVCDelegate> delegate;
  }

@property (nonatomic, retain) id <CellToVCDelegate> delegate;

在NibCell.m

#pragma mark - Custom Action(s)
- (void)deleteActivity:(id)sender {
    NSLog(@"delete action! %@", sender);

    [self.delegate deleteActivity:sender];


}

- (void)shareActivity:(id)sender {
    NSLog(@"shareActivity action! %@", sender);
    [self.delegate shareActivity:sender];



}

在集合VC.h中

@interface VC : UIViewController <

                        CellToVCDelegate>
VC.m中的

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    NibCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cvCellIdentifier
                                                              forIndexPath:indexPath];

cell.delegate = self;
return cell;
}