Syntax error: IBOutletCollection - objective-c

I am trying to declare an IBOutletCollection.
What I want to do is to manage multiple buttons in a way that I don't have to declare them one per one.
#import <Foundation/Foundation.h>
#interface WindowManager : NSObject
{
#private
IBOutlet NSTextField* textField;
IBOutletCollection (NSButton) NSArray* buttonsArray;
}
#property (nonatomic , retain) IBOutletCollection (NSButton) NSArray *buttonsArray;
- (void) awakeFromNib;
#end
I get these errors:
type name requires a specifier or qualifier
expected ; at end of declaration
And I don't understand the reason.
I want to have this situation: when the .xib file is loaded, I have all the button in a NSArray so that I am able to manage them.Everytime a button is pressed I want to know which button was pressed.
Is that possibile? The problem is that I find only iPhone guides, I found an example similar to this code on an iPhone guide, saying this thing works.

I would recommend using an IBAction instead:
-(IBAction)button_Clicked:(id)sender;
The reason is that the button that was pressed is the 'sender' of the press event. This way you will always know what button was actually pressed. If you want to make it even more identifiable, you can set the 'Tag' property for the buttons, so that your implementation file would look like this:
-(IBAction)button_Clicked:(id)sender {
switch([sender tag]) {
case 1:
// do stuff
break;
//etc.....
default:
break;
}
}
You can assign any number of controls to use the action. I hope this helps.

Related

Buttons in NSTableView to open file

I have an NStableView that is populated with an NSMutableArray that is built from a SQL data base... all good.
One cell displays a path to a locally stored pdf. I'd like to have that cell or text open up the pdf with Preview when clicked. The cell can be a button or just text- that's not really important (I'll do whatever is easiest) so long as it opens up Preview with the pdf. I know I can implement the following to call Preview
[[NSWorkspace sharedWorkspace] openFile:theUrl withApplication:#"Preview"];
The part I'm not sure of is how to make a cell call that action... That is, how do I turn a cell into a button where the contents of the cell (the path) is passed to the action as "theUrl"
Thanks in advance...
Create a subclass of NSTableCellView and add the following:
In your interface:
#property (nonatomic, strong) NSURL *url;
#property (nonatomic, weak) IBOutlet NSButton *urlButton;
In your implementation:
- (void)setURL:(NSURL *)url {
_url = url;
_urlButton.title = url.absoluteString ?: #"Missing url";
}
- (IBAction)didPressURLButton {
[[NSWorkspace sharedWorkspace] openFile:_url withApplication:#"Preview"];
}
In your storyboard/nib:
Design your NSTableView and NSTableCellView
Assign the above subclass to NSTableCellView and don't forget to set its identifier to something unique and connect its IBOutlet and IBAction
In your NSTableViewDataSource/Delegate:
Create a table cell with makeViewWithIdentifer: and pass in the identifier you assigned above.
Call setURL: on your tablecell for that row
This is more thorough than required, but once you know how to do it this way, you should be able to add and expand it to whatever other functionality you want to add.

Trying to get an NSPanel from one class to be viewed in a different class?

I've got:
MyWindowController.h
MyWindowController.m
HistoryController.h
HistoryController.m
In MyWindowController.h, there is:
IBOutlet NSPanel* viewInvoice;
And later on:
- (IBAction)viewInvoice:(NSNumber *)invoiceNumber;
I would like to make use of this panel throughout my program.
In my HistoryController.m, there is:
- (IBAction)viewSelectedInvoice:(id)sender{
id viewInvoiceObject = [[MyWindowController alloc] init];
[viewInvoiceObject viewInvoice:[NSNumber numberWithInt:1]];
[viewInvoiceObject release];
}
Now I can successfully access that method (some NSLog calls verify this), but I'm not at all able to actually make the NSPanel appear. Here's some of the code from there:
- (IBAction)viewInvoice:(NSNumber *)invoiceNumber {
[viewSelectedInvoicePanel makeKeyAndOrderFront:viewSelectedInvoicePanel];
}
I'm able to make the panel pop up if I link the button in my History view to the FirstResponder action "viewInvoice", however it seems like I won't be able to send through a parameter (namely the invoice number).
Edit your HistoryController to have your custom NSPanel as a Property:
#property (nonatomic, retain) IBOutlet NSPanel *viewInvoice;
Then, create an IBAction on your HistoryController to call your custom NSPanel function:
-(IBAction)viewInvoice:(id)sender {
[self.viewInvoice viewInvoice:self.some_property_with_invoice_number];
}
And link your button to the viewInvoice method (inside the HistoryController class. Also, you should change the property object type from NSPanel to whatever you named your class.

Referencing an array of IBOutlet 's (NSButton)

I am making an application where there are 32 Check Box, and a NSTextField.
If the user clicks on the NSTextField the buttons shall assume the value that describes the binary rappresentation of this number.
No problem receiving the "clicked" action on the NSTextField, but for the buttons I have declared an array of 32 NSButtons:
#import <Foundation/Foundation.h>
#interface Handler : NSObject
{
#private
IBOutlet NSTextField* textField;
IBOutlet NSButton* bits[32]; // here are the buttons
}
- (void)awakeFromNib;
- (void) setTextField : (int) value;
- (int) getTextField;
#end
But when I try to link a Check Box with the IBOutlet "bits", I can't do it for each member.
So I can only make that array of 32 pointers to NSButton to one box.
I also show an image:
This is a problem for me, do I have to manually declare 32 different outlets with 32 different names?
You do not have to use 32 different IBOutlet references. You can declare an IBOutletCollection:
#property (retain, nonatomic) IBOutletCollection(NSButton) NSArray *buttons;
Use this to link them all up. Keep in mind that the order of the buttons is non-deterministic at runtime, meaning, you cannot guarantee that the buttons will be in any specific order when the app is running.
This is probably a good example of using an NSMatrix object.
You can add one button to your interface and then with the button selected in Xcode 4 go to Editor > Embed In > Matrix. Then you can option drag on a corner of the button to expand it into a matrix.
NSMatrix allows you to retrieve the cell values by searching for a given tag or by column/row coordinates.
HOW TO:
1) Embedding the NSButton object:
2) Option-Drag any of the button corners to expand the matrix:
I expanded it into a matrix.But graphically it looks like a single button.
This is what I get:

TextField will NOT resign first responder with UIModalPresentationFormSheet view

I've created a button on one viewController that loads another view modally using the UIModalPresentationFormSheet presentation style. On this loaded view, I have two textFields, and I'm forcing the first textField to be first responder so that the keyboard will appear immediately with the new view. I've set up the textFields to have an action method that is hooked up to "Did End on Exit" event. However, whenever I hit "return" on the keyboard for either textField, the keyboard fails to go away (Here is my code):
// addCustomPage method that is called when button from original view is touched
- (IBAction) addCustomPage:(id)sender
{
NSLog(#"Adding Custom Page");
if (!self.customPageViewController)
{
self.customPageViewController =
[[CustomPageViewController alloc] initWithNibName:#"CustomPageViewController" bundle: nil];
}
customPageViewController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:customPageViewController animated:YES];
// force keyboard to appear with loaded page on the first textField
[customPageViewController.firstTextField becomeFirstResponder];
}
#interface CustomPageViewController : UIViewController
#property (strong, nonatomic) IBOutlet UITextField *firstTextField;
#property (strong, nonatomic) IBOutlet UITextField *secondTextField;
- (IBAction)keyboardEndOnExit:(id)sender; // DID END ON EXIT EVENT
#end
//in CustomPageViewController.m
-(IBAction)keyboardEndOnExit:(id)sender
{
[sender resignFirstResponder];
}
This is a fairly straight forward problem, and I have no problem normally dismissing keyboards using this technique with basic views and textFields. I'm not sure if using a view in this presentation format, or set up makes things different. Thanks!
You have confirmed that you keyboardEndOnExit method is actually being called?
You could also take a more direct approach by calling [yourTextView resignFirstResponder] when a specific action is take by the user, such as a key pressed etc. I would still check if that method is ever being called using breakpoints or a log.
Have a look at this question. Pretty sure it is the same problem caused by UIModalPresentationFormSheet.

Populate text in one textfield from text in another

Working on an experiment on the iPad. Tried some variations on how to do this, but I can't seem to get it to work correctly...
I tap a UIButton on my MainViewController and a TextEntryModule is added to the view. TextEntryModule is its own class (for multiple instantiation) and it contains a UITextView called TextEntry (this all works at the moment).
I tap on the TextEntry UITextView and it brings up the keyboard and another view (located in MainViewController) with a UITextView called TextPreview. (this also works at the moment).
The part I'm having trouble with is synching the two UITextViews. The idea being that when I type into TextEntry, the text in TextPreview will also be updated.
Outlets are linked properly for the text fields, but I think I'm missing something "obvious":
TextEntryModule *tm = (AnnotationModule *)currentModule;
TextPreview.text = tm.TextEntry.text
Thanks in advance!
UITextView: delegate.
- (void)textViewDidChange:(UITextView *)textView
Then assign it the value of the other textview in this method.
Edit
#interface MainViewController <UITextViewDelegate> {
...
}
...
#end
Then you implement this method in the implementation file of MainViewController
#implementation MainViewController
//More code
- (void)textViewDidChange:(UITextView *)textView {
TextEntryModule *tm = (AnnotationModule *)currentModule;
TextPreview.text = tm.TextEntry.text
}
#end
Then you will have to set the TextEntryModule object's delegate to self since the controller now conform to the protocol and can "act" upon this notification.
You need to become a UITextFieldDelegate and monitor when text changes in the one field and then update the other field. Take a look at the documentation on it.