0

In XIB file I have a collection view which contains a button. In awake from Nib i have defined several of buttons with different images. So the application basically looks like a finder, but does not perform any actions yet.

What I want to do now, is that when pressing each button a different file opens (I use filemanager method). I can do this easily in non-collection view type application, but when using collection view I am not sure how to attach different action to each button.

This is what I have, but that would open the same pdf.pdf for every button, when I want every button to open different pdf.

@implementation AppController
-(void) awakeFromNib {


MyButton *Button1 = [[MyButton alloc] init];
Button1.image = [NSImage imageNamed:@"img1"];


MyButton *Button2 = [[MyButton alloc] init];
Button2.image = [NSImage imageNamed:@"img2"];

MyButton *Button3 = [[MyButton alloc] init];
Button3.image = [NSImage imageNamed:@"img3"];

_modelArray = [[NSMutableArray alloc] init];
[controller addObject:Button1];
[controller addObject:Button2];
[controller addObject:Button3];}

- (IBAction)OpenCVFile:(id)sender {


NSFileManager *fileManagerCv = [[NSFileManager alloc] init];
NSString *filePath = @"Users/Tom/pdf.pdf";

if ([fileManagerCv fileExistsAtPath:filePath]) {
    NSLog(@"File exists");
    [[NSWorkspace sharedWorkspace]openFile:filePath withApplication:@"Finder"];}
else {
    NSLog(@"File does not exist");

}
}

Could anyone help? Any help would be appreciated.

1 Answers1

1

Using Bindings

First off, introduce a property to your model class that points back to the controller.

For example, a very simple model class would be:

@interface ModelData : NSObject

@property NSString *name;
@property id controller;

@end

@implementation ModelData
@end

Initialize your collection view's content:

// In the controller
ModelData *data1 = [ModelData new];
data1.name = @"Apple";
data1.controller = self;

ModelData *data2 = [ModelData new];
data2.name = @"Boy";
data2.controller = self;

[self.collectionView setContent:@[data1, data2]];

In interface builder, select the button in your prototype Collection View Item, navigate to the Bindings Inspector, create bindings for Argument and Target:

  • For Argument, set Bind to to Collection View Item, then set the Model Key Path to any property in your model class that you can use to uniquely identify the button (e.g. representedObject.name), and set the Selector Name to your action method's signature, say buttonClicked:.

  • For Target, set Bind to to Collection View Item, then set the Model Key Path to something that points to your controller class (where the action method is implemented), and set the Selector Name the same as above.

enter image description here enter image description here

After these two bindings are set up, your action method in the controller class will be called with the argument you designated when the button is clicked.

// In the controller
- (IBAction)buttonClicked:(id)anArg {
    NSLog(@"%@", anArg);
}
Renfei Song
  • 2,941
  • 2
  • 25
  • 30
  • For some reason, the represented object pdf.pdf does not get attached to the end of filePath and therefore NSLog is /Users/Tom/(null) – ShaunArchibald May 31 '15 at 11:54
  • Could that be, because I am using AwakeFromNib? – ShaunArchibald May 31 '15 at 12:14
  • @ShaunArchibald How did you populate your `NSCollectionView`? Did you use bindings? – Renfei Song May 31 '15 at 12:25
  • @RanfeiSong Yes I did. To me it seems like [ [button cell] setRepresentedObject:@"pdf.pdf"]; This does not work – ShaunArchibald May 31 '15 at 12:37
  • @ShaunArchibald So if I understand you right you are adding your buttons to _each_ of your collection view items (i.e. to the prototype item's view), from the interface builder? – Renfei Song May 31 '15 at 12:38
  • @ShaunArchibald I got it. Updated my answer. – Renfei Song May 31 '15 at 12:56
  • @RanfeiSong Thanks for the answer, it works! However, after pressing the button once in the ouput it shows as if I pressed it twice and it seems that xcode was unable to trace the file firstly, but then it did it again and it worked: 2015-05-31 23:09:32.622 Collection View with Buttons[16509:868627] File does not exist 2015-05-31 23:09:32.637 Collection View with Buttons[16509:868627] File exists – ShaunArchibald May 31 '15 at 20:12
  • 1
    @ShaunArchibald Hard to say what's going on - I set up the aforementioned bindings myself and the method gets called exactly one time every time I click the button. Maybe the other invalid call wasn't from the bindings? – Renfei Song Jun 01 '15 at 01:24
  • Do you also happen to know in this case how to make a button selected (blue border line lights up) with one mouse click and invoke action with a double click. Is that possible to do in the XIB file? – ShaunArchibald Jun 02 '15 at 15:42
  • @ShaunArchibald I am not sure I understand what you meant - what exactly is _selected_ for a button? I couldn't recall any cases where a normal button can have a blue outline. Also triggering an event with double-click isn't the Cocoa way of a button. It's certainly doable, but not likely in the interface builder. – Renfei Song Jun 02 '15 at 15:52
  • Pardon my language @RanfeiSong yea indeed I'm talking about a focus ring. In my case the button is not a normal button, because what I am basically creating is a finder window with buttons. Each button corresponds to a different file and each of those buttons have a preview picture attached to them. You can then select any of those "buttons" and by double clicking you can open the file that the "button" corresponds to (for example a pdf file). – ShaunArchibald Jun 02 '15 at 16:02
  • @ShaunArchibald I see. I would suggest you consider using the collection view's selection mechanism and render your subviews with a highlighted look when selected. Also buttons don't have a binding for double action. The easiest way I can think of now is to subclass it and override -mouseDown:. – Renfei Song Jun 02 '15 at 16:31