7

我正在使用 a在单元格长按UIMenuItem中执行自定义操作。UICollectionView这与 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

4 回答 4

8

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

// 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];
}
于 2013-10-07T18:34:24.030 回答
1

我在 UICollectionView 上添加了一个 searchBar,UIMenuController 的结果是 MIA。经过两天的反复试验,我想终于找到了一种让它工作的方法。

问题(在 iOS7 上运行):

  1. UICollectionViewController上的UILongPressGestureRecognizer被调用
  2. MenuController 显示
  3. 添加了一个UISearchBar并在 collectionView 重新加载其数据时:没有更多的菜单控制器

认为使它起作用的技巧是从 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];
}
于 2013-10-04T14:14:23.427 回答
1

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

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

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

于 2013-10-03T20:16:55.543 回答
0

正如 nicolas 所提到的,相关代码如下。注意:这会导致集合 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;
}
于 2013-09-24T05:24:32.050 回答