diff --git a/JSQMessagesDemo/DemoMessagesViewController.m b/JSQMessagesDemo/DemoMessagesViewController.m index b59f326c0..a242d2fde 100644 --- a/JSQMessagesDemo/DemoMessagesViewController.m +++ b/JSQMessagesDemo/DemoMessagesViewController.m @@ -36,6 +36,8 @@ - (void)viewDidLoad { [super viewDidLoad]; + [JSQMessagesCollectionViewCell registerMenuAction:@selector(delete:)]; + self.title = @"JSQMessages"; /** @@ -502,7 +504,25 @@ - (UICollectionViewCell *)collectionView:(JSQMessagesCollectionView *)collection return cell; } +#pragma mark - UICollectionView Delegate +- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender +{ + if (action == @selector(delete:)) { + return YES; + } + + return [super collectionView:collectionView canPerformAction:action forItemAtIndexPath:indexPath withSender:sender]; +} + +- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender +{ + if (action == @selector(delete:)) { + NSLog(@"delegate action %@", NSStringFromSelector(action)); + } else { + [super collectionView:collectionView performAction:action forItemAtIndexPath:indexPath withSender:sender]; + } +} #pragma mark - JSQMessages collection view flow layout delegate diff --git a/JSQMessagesViewController/Views/JSQMessagesCollectionView.m b/JSQMessagesViewController/Views/JSQMessagesCollectionView.m index ba7acc447..e01d2db71 100644 --- a/JSQMessagesViewController/Views/JSQMessagesCollectionView.m +++ b/JSQMessagesViewController/Views/JSQMessagesCollectionView.m @@ -165,4 +165,17 @@ - (void)messagesCollectionViewCellDidTapCell:(JSQMessagesCollectionViewCell *)ce touchLocation:position]; } +- (void)messagesCollectionViewCell:(JSQMessagesCollectionViewCell *)cell didPerformAction:(SEL)action withSender:(id)sender +{ + NSIndexPath *indexPath = [self indexPathForCell:cell]; + if (indexPath == nil) { + return; + } + + [self.delegate collectionView:self + performAction:action + forItemAtIndexPath:indexPath + withSender:sender]; +} + @end diff --git a/JSQMessagesViewController/Views/JSQMessagesCollectionViewCell.h b/JSQMessagesViewController/Views/JSQMessagesCollectionViewCell.h index d5f4ef831..35280f504 100644 --- a/JSQMessagesViewController/Views/JSQMessagesCollectionViewCell.h +++ b/JSQMessagesViewController/Views/JSQMessagesCollectionViewCell.h @@ -60,6 +60,19 @@ */ - (void)messagesCollectionViewCellDidTapCell:(JSQMessagesCollectionViewCell *)cell atPosition:(CGPoint)position; +/** + * Tells the delegate that an actions has been selected from the menu of this cell. + * + * @param cell The cell that displayed the menu. + * @param action The action that has been performed. + * @param sender The object that initiated the action. + * + * @discussion This method is automatically called for any registered actions. + * + * @see `JSQMessagesCollectionViewCell` + */ +- (void)messagesCollectionViewCell:(JSQMessagesCollectionViewCell *)cell didPerformAction:(SEL)action withSender:(id)sender; + @end @@ -180,4 +193,12 @@ */ + (NSString *)mediaCellReuseIdentifier; +/** + * Registeres an action to be available in the cell's menu. + * + * @discussion Non-Standard actions still need to be added to the `UIMenuController` + * manually. + */ ++ (void)registerMenuAction:(SEL)action; + @end diff --git a/JSQMessagesViewController/Views/JSQMessagesCollectionViewCell.m b/JSQMessagesViewController/Views/JSQMessagesCollectionViewCell.m index 69976a8d7..d07823d30 100644 --- a/JSQMessagesViewController/Views/JSQMessagesCollectionViewCell.m +++ b/JSQMessagesViewController/Views/JSQMessagesCollectionViewCell.m @@ -66,11 +66,21 @@ - (void)jsq_updateConstraint:(NSLayoutConstraint *)constraint withConstant:(CGFl @end +static NSMutableArray *jsqMessagesCollectionViewCellActions = nil; + @implementation JSQMessagesCollectionViewCell #pragma mark - Class methods ++ (void)initialize +{ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + jsqMessagesCollectionViewCellActions = [[NSMutableArray alloc] init]; + }); +} + + (UINib *)nib { return [UINib nibWithNibName:NSStringFromClass([self class]) bundle:[NSBundle bundleForClass:[self class]]]; @@ -86,6 +96,11 @@ + (NSString *)mediaCellReuseIdentifier return [NSString stringWithFormat:@"%@_JSQMedia", NSStringFromClass([self class])]; } ++ (void)registerMenuAction:(SEL)action +{ + [jsqMessagesCollectionViewCellActions addObject:NSStringFromSelector(action)]; +} + #pragma mark - Initialization - (void)awakeFromNib @@ -216,6 +231,37 @@ - (void)setBounds:(CGRect)bounds } } +#pragma mark - Menu actions + +- (BOOL)respondsToSelector:(SEL)aSelector +{ + if ([jsqMessagesCollectionViewCellActions containsObject:NSStringFromSelector(aSelector)]) { + return YES; + } else { + return [super respondsToSelector:aSelector]; + } +} + +- (void)forwardInvocation:(NSInvocation *)anInvocation +{ + if ([jsqMessagesCollectionViewCellActions containsObject:NSStringFromSelector(anInvocation.selector)]) { + id sender; + [anInvocation getArgument:&sender atIndex:0]; + [self.delegate messagesCollectionViewCell:self didPerformAction:anInvocation.selector withSender:sender]; + } else { + [super forwardInvocation:anInvocation]; + } +} + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector +{ + if ([jsqMessagesCollectionViewCellActions containsObject:NSStringFromSelector(aSelector)]) { + return [NSMethodSignature signatureWithObjCTypes: "v@:@"]; + } else { + return [super methodSignatureForSelector:aSelector]; + } +} + #pragma mark - Setters - (void)setBackgroundColor:(UIColor *)backgroundColor