Buttons in NSTableView to open file - objective-c

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.

Related

Sending multiple UITextField fields to a UITextView on a second ViewController (using a segue)

Firstly, Im new to Objective-C and i'm currently following several tutorials. Apologies if this is an obvious solution. I did use the search for several hours and couldn't find a solution.
I have no problem understanding how to send a data from a single UITextField to a UITextView in a new view controller.
MY QUESTION IS: I want to populate the UITextView on the second view controller with all the users information they entered into the UITextField when they press the button.
IMAGE OF LAYOUT
The code I used to populate the UITextView with 'Name' is:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier]isEqualToString:#"mySegue"]) //will return true so will start segue
{
ViewControllerTwo *ViewControllerTwo = [segue destinationViewController];
ViewControllerTwo.Name = sendName.text;
}
}
I'm sure to send the rest of the form over is simple but right now I just can't think of a solution.
Create more properties for the information in ViewControllerTwo.h. For example if you wanted to add the users age.
#property (nonatomic, strong) int age;
Set the value of the age in your prepareForSegue Method from the text the user enters into the field.
ViewControllerTwo.age = [ageTextField.text intValue];
In ViewControllerTwo.m build a string with all these properties and set the UITextView text equal to entire string.
NSString *userInformation = [[NSString stringWithFormat:#"%# \n %d", name, age];
Set your UITextView.text property equal to userInformation

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.

Syntax error: IBOutletCollection

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.

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:

How to programmatically change label in UIView created in a nib file?

I have trouble changing the text in a label programmatically.
When I run the following code, NSLog does display "Setting myLabel to = Hello World!", but the label on the screen is not changed.
UIViewOverlay *overlayWindow;
overlayWindow = [[[NSBundle mainBundle] loadNibNamed:#"UIViewOverlay" owner:self options:nil] objectAtIndex:0];
[self addSubview:overlayWindow];
[overlayWindow setMyLabel:#"Hello World!"];
My NIB file has a 300x300 window with some labels and buttons.
There is a label, which is connected to myLabel in the outlet. The UIView does display, just that the text cannot be changed programmatically.
UIViewOverlay.h
#import <UIKit/UIKit.h>
#interface UIViewOverlay : UIView {
IBOutlet UILabel *myLabel;
}
- (void)setMyLabel:(NSString *) label;
#end
UIViewOverlay.m
#import "UIViewOverlay.h"
#implementation UIViewOverlay
- (void)setMyLabel:(NSString *) label {
myLabel.text = label; // THIS LINE IS NOT WORKING! :-(
NSLog(#"Setting myLabel to = %#", label); // This line is working.
}
#end
Thanks in advance..
You are using an incorrect accessor name for your method to set the label string.
In cocoa, setFoo is the method by which an instance variable called foo is assigned. This isn't just a convention, many areas of functionality depend on it, for example the use of properties, key value coding etc.
In your code, your label is called myLabel. Your method to set the text of that label is called setMyLabel. Either this is causing your outlet to not be connected when the nib is loaded, as the runtime may be trying to use that method to assign the label to your instance variable in the first place, or all of the above has no effect and you have just not connected your outlet.
Make sure you have an object in your code for the label, like this example:
IBOutlet UILabel* aLabel;
And in interface builder (you may have already done this): Connect the aLabel (or whatever name you use) outlet to the actual label. This can be done by control clicking and dragging from the File’s Owner object, in the document window, to the label, in the view. A small, gray window will appear with at least two options, one will be the aLabel defined earlier, and the other will be the view (this is a default outlet required for viewcontrollers, it will have a dash to indicate it is already connected to something). Click on the aLabel option to select it. (I'll be honest, without my mac in front of me I copied most of this paragraph's instructions from this link.)
You have an object called aLabel that you can now treat like any other variable. If you want to change the text value, try this:
aLable.text = #"some text";
Maybe you did not make the connection. Can you try the following?
#import "UIViewOverlay.h"
#implementation UIViewOverlay
- (void)showMyLabel:(NSString *) label {
NSLog(#"My current label contents (myLabel) = %#", myLabel.text); // ** changed to myLabel.text
}
#end
If you aren't able to print the original value, then you aren't connected.
I hope that helps.