How to handle a button click from NSCollectionView

2019-04-28 04:10发布

I have a NSCollectionView (OS X, not iOS) bound to my model. Each collection view item has a button and a label. I'm handling the click actions and I have the sender and event arguments but I unable to distinguish one button from the others. Most other questions not dealing with Collection Views say to use the tag property, but this isn't exposed on the Interface Builder's bindings tab. There is an Argument and Argument2 bindings, but they dont seems to correspond to the tag property in the objc code and I don't know how to otherwise access these Arguments.

-(void)image_click:(id)sender forEvent:(NSEvent *)event
{
    NSButton *btn = sender;
    NSLog(@"image clicked, %ld", (long)btn.tag);   //image clicked, 0
}

How do I differentiate between buttons in Objective-C code inside the click actions of a bunch of buttons in a collection view?

5条回答
Summer. ? 凉城
2楼-- · 2019-04-28 04:24

I would do it like this (because the button you want to press should be coupled with the corresponding model, therefore the represented object):

  1. Add a method to the model of your collectionViewItem (e.g. buttonClicked)
  2. Bind the Button Target to Collection View Item
  3. While binding set model key path to: representedObject
  4. While binding set selectorname to: methodname you chose earlier (e.g. buttonClicked)
  5. Add protocol to your model, if you must tell delegate
查看更多
劳资没心,怎么记你
3楼-- · 2019-04-28 04:25

use this in cellForItemAtIndexPath method

   [[cell myButton] addTarget:self action:@selector(myClickEvent:event:) forControlEvents:UIControlEventTouchUpInside];


   -(IBAction)myClickEvent:(id)sender event:(id)event {

          NSSet *touches = [event allTouches];

          UITouch *touch = [touches anyObject];

          CGPoint currentTouchPosition = [touch locationInView:_myCollectionArray];

          NSIndexPath *indexPath = [_myCollectionArray indexPathForItemAtPoint: currentTouchPosition];

   }
查看更多
欢心
4楼-- · 2019-04-28 04:26

Add a Model in your project named MyModel and declare property uniqueID in MyModel.h

@interface MyModel:NSObject  
@property (retain) NSString* unqiueID;  
@end  

MyModel.m

@implementation MyModel  
@synthesize uniqueID=_uniqueID;
@end

In AppDelegate.m create some model objects and add them into an array

In IB add an ArrayController and bind it to the array declare in AppDelegate

In IB select CollectionView and bind its Content property to ArrayController and set its ControllerKey property to arrangedObjects

In your Template View Use NSButton's Target and Argument bindings to send unique arguments to the selector specified

Your Arguments binding should look like this
Bind to: Controller View Item
Model Key Path: representedObject.uniqueID
Selector Name: buttonClicked:

and Target bindings
Bind to: App Delegate
Model Key Path: self
Selector Name: buttonClicked:

The steps are explained in detail in the following tutorial
https://developer.apple.com/library/mac/documentation/cocoa/Conceptual/CollectionViews/Introduction/Introduction.html#//apple_ref/doc/uid/TP40009030
Hope this helps

查看更多
Rolldiameter
5楼-- · 2019-04-28 04:34

As per this "//image clicked, 0" i think you are getting 0 for each and every button click,am i correct?

If so, you can have a outlet to the button in collectioViewItem and overide -(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil to set/increment the tag of each instance of the button.

查看更多
等我变得足够好
6楼-- · 2019-04-28 04:38

I'm assuming you want to determine the model object being represented by the button in the view. I was able to determine the model object by looping over the buttons in the collection view. I couldn't use the selection index or any other similar attribute, but in the end, the model can be determined.

Assuming your NSArrayController already has your array, then do the following:

Bindings:

The Collection View only needs one binding

Bind to:         <NSArrayController instance>
Controller Key:  arrangedObjects
Model Key Path:  <blank>

Controller:

You should hook up the controller to the content view

property (weak) IBOutlet NSCollectionView *collectionView;

Finally, the controller receiving the button click message should implement this IBAction:

- (IBAction) collectionViewClick:(id)sender
{  
  id objectInClickedView = nil;

  for( int i = 0; i < [[self.collectionView content] count]; i++ ) {
    NSCollectionViewItem *viewItem = [self.collectionView itemAtIndex:i];

    if( [sender isDescendantOf:[viewItem view]] ) {
      objectInClickedView = [[self.collectionView content] objectAtIndex:i];
    }
  }
}

Which will assign the object to objectInClickedView. If you're actually interested on the view or viewItem, you can modify the code.

查看更多
登录 后发表回答