I am trying to access an NSMatrix object called "matrix" from my code. The object is generated in a NIB, but I keep having problems to access the object that was generated in the interface builder.
If my NSDocument has an NSMatrix *matrix, what should I do in the interface builder to link these two? And preferably, to use the initial layout from IB?
Thanks!
I think you are trying to create an outlet to the matrix. Just create a property in your .h file between the #interface and #end keywords:
#property (nonatomic) IBOutlet NSMatrix* myMatrix;
and then hold down the ctrl key and drag from 'File Owner' to the matrix object in IB. Make sure you
#synthesize myMatrix;
in your .m file between the #implementation and #end keywords and you should be able to access all of the properties via dot notation or message calls using:
self.myMatrix.somePropertyHere
I hope that helps!
Related
I have a plain blue cube object in IB called AppController. Here is the header file:
//AppController.h
#import <Cocoa/Cocoa.h>
#interface AppController : NSObject <NSCoding>
#property (weak) IBOutlet NSView *view;
#property (assign) int numberOfPresses;
- (IBAction)buttonPressed:(id)sender;
#end
As you can see it has an outlet to the view, a property called numberOfPresses, and and action tied to a button in IB.
Here is the implementation file
//AppController.m
#import "AppController.h"
#implementation AppController
-(void)awakeFromNib {
NSLog(#" number of presses = %d", _numberOfPresses);
}
- (IBAction)buttonPressed:(id)sender {
_numberOfPresses++;
NSLog(#" number of presses = %d", _numberOfPresses);
}
#pragma mark - Coding Protocol
-(void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeInt:_numberOfPresses forKey:#"numberOfPresses"];
}
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self) {
_numberOfPresses = [aDecoder decodeIntForKey:#"numberOfPresses"];
}
return self;
}
#end
As you can see, when the user presses on the button, the numberOfPresses is incremented. As I quit the app and fire it up again I would like
the numberOfPresses to be remembered.
The view outlet to stil be pointing to a valid view.
Now I always get 0 for numberOfPresses, and if I try to force the archiving using NSKeyedArchiver and NSKeyedUnarchiver from AppDelegate then I end up with view = null.
This problem is a general problem of archiving plain blue cube objects from IB. But I have not found an explanation of this on the Internet, although it should be a quite common problem. I must be missing or misunderstanding something.
Requirement #2 should be easy. If you do nothing, then the AppController should be loaded with its view created. In a sense it is "pre-archived" for you.
That means the real problem is how to restore the number of presses.
For something that simple, NSUserDefaults is a likely candidate. Update the defaults on a press and retrieve it during awakeFromNib.
Custom archiving and unarchiving is generally better for complete custom objects that are created dynamically, rather than ones loaded from IB.
(If it was a complicated network of objects you needed to restore, I'd be talking about CoreData instead.)
What I was after was a GENERAL solution that I could implement in ANY project and that ONLY uses NSCoding. (If anyone has a simpler solution, I would very much like to hear it). I ended up with a solution that works, by introducing two objects: a Hub, and a RootObject. The idea can be summarized in three points:
The idea is to free all objects that you want to archive from having any presence in the IB.
Introduce a Hub object which is responsible for all IB connections. The Hub is a blue cube in IB and has an outlet to AppDelegate. The AppDelegate has an outlet to the Hub.
Introduce a RootObject whose purpose is to propagate archiving to all objects that you want to archive. The RootObject is owned by the AppDelegate. The AppDelegate is responsible for initiating the archiving and unarchiving, and the RootObject is the mediator.
I'm learning iPhone Dev and I'm stuck on something. I'm writing a simple calculator program, but when I try to connect one of the buttons on the calculator to the File Owner in Interface Builder I do not get any options:
.h file
#interface CalculatorViewController : UIViewController
{
CalculatorBrain *brain;
IBOutlet UILabel *label;
}
- (IBAction)digitPressed:(UIButton *)sender;
- (IBAction)operandPressed:(UIButton *)sender;
#end
.m file
#import "CalculatorViewController.h"
#implementation CalculatorViewController
- (IBAction)digitPressed:(UIButton *)sender
{
//not implemented yet
}
- (IBAction)operandPressed:(UIButton *)sender
{
//not implemented yet
}
#end
As far as I understand when I'm working with my CalculatorViewController.xib in interface builder if I try to connect a button to the file's owner I should have two options:
1. digitPressed
2. operandPressed
However, I do not get any options. Any ideas what I'm doing wrong?
Thanks.
Check that file's owner is set to CalculatorViewController
In IB, click the button, then click the option on the far right (connections, I think it is called)
Find the action called touchUpInside. Drag from the circle next to this to your files owner, the two actions will pop up then.
Are you dragging from the button to the owner or the other way around?
If you want to refer to an object in a nib from code, then you define an IBOutlet and drag from the owner to the object.
If you want to refer to code from an object in a nib file, then you define an IBAction and drag from the object to the owner.
I encountered a similar issue.
The problem was that I renamed the ViewController.
The XIB file has the name of the view controller inside of it.
when it doesn't match the actual name of the UI View Controller class interface builder will act funny.
To fix it, open the XIB file as source code (right click it and use Open As source code)
it's an XML file. find the name of the old controller and then change it to the correct name.
I found it in the XML under:
<dictionary class="NSMutableDictionary" key="flattenedProperties">
<string key="-1.CustomClassName">xxxxxxViewController</string>
I created three IBOutlets in a .h but when I go to Interface Builder and go to Referencing Outlets or right click on the object that I want to connect to one of the outlets. It just doesn't display the outlets I made. How do I find and connect the images in IB to these. My goal is to make custom buttons, I have the images out in IB and have set the highlighted state. And I want the images to auto switch to the highlighted state when touchupInside is triggered.
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController {
IBOutlet UIButton *brown
IBOutlet UIButton *red
IBOutlet UIButton *blue
}
-(void)brownPressed
-(void)redPressed
-(void)bluePressed
#end
If the code you posted is accurate, you are missing 6 semicolons. Interface Builder won't be able to properly parse the header file without them and so it won't show any IBOutlets.
Try changing the code to the following:
#interface FirstViewController : UIViewController {
IBOutlet UIButton *brown;
IBOutlet UIButton *red;
IBOutlet UIButton *blue;
}
-(void)brownPressed;
-(void)redPressed;
-(void)bluePressed;
#end
This answer is in reference to Xcode 4
If you changed the name of the .xib manually, don't forget to check these IB setting in the right pane:
Identity and Type: File Name
should be:
newName.xib
Custom Class : Class
should be:
newName
...
I was also experiencing this problem - after changing the .xib filename manually. I have no idea why renaming by refactoring was grayed out but that was my first attempted solution to rename. I then made some IBOutlets, but dragging to the File's Owner didn't give me any options to connect to it.
I right clicked on File's Owner and noticed some warnings telling me there was no IBOutlet by the name of the variable it tried to reference.
Basically, since I changed the .xib filename manually, at least one of the above configurations did not automatically follow (makes sense since I did a manual operation).
This happens to me try connecting the touch up inside connection of the button to files owner and then it will show up
Is it possible to access the NSControl on a NSWindow using tag?
I used the code below but it warned
NSWindow may not response to viewWithTag
NSButton *a=(NSButton * )[self.window
viewWithTag:tag];
Welcome any comment
Thanks
interdev
Unlike UIWindow in Cocoa Touch, NSWindow does not inherit from NSView, and thus does not implement that method. You probably want to get the contentView of the window, and then look up the tag on that.
Create an NSView in your .h file called 'view'.
In IB, highlight the View under the Window and connect it to the 'File's Owner' view from step 1.
Then you can use viewWithTag.
file.h
#property (strong, nonatomic) IBOutlet NSView * view;
file.m
[(NSTextField*)[self.view viewWithTag:(1)] setStringValue: #"MyStringName"];
In the Implementation Overview section of the NSPersistentDocument Core Data Tutorial it says:
…
One issue with creating the new top-level object in the nib file is that when you use bindings an object retains other objects to which it is bound. This means that bindings must be broken to ensure there are no retain cycles when a document is closed. Moreover, since the nib file the new controller owns contains top level objects and the controller’s class does not inherit from NSWindowController, you need to release the top level objects when the window is closed.
Why not just have the controller inherit from NSWindowController? Is there a reason this would not work? Or was this just a matter of style?
As commented below, I did get this to work with an NSWindowController subclass, and it does seem to save quite a bit of code.
Here is my subclass header:
#import <Cocoa/Cocoa.h>
#interface NewAccountSheetController : NSWindowController {
#private
BOOL isValidForInsert;
NSManagedObjectContext * managedObjectContext;
NSObjectController * objectController;
NSObjectController * targetController;
}
#property (setter=setValidForInsert:) BOOL isValidForInsert;
#property (nonatomic, retain) IBOutlet NSManagedObjectContext * managedObjectContext;
#property (nonatomic, retain) IBOutlet NSObjectController * objectController;
#property (nonatomic, retain) IBOutlet NSObjectController * targetController;
- (void)beginSheetForWindow:(NSWindow *)window;
- (IBAction)endSheet:(id)sender;
#end
And here is the implementation in a Pastebin.
I have no good idea how to describe the required bindings, etc. but if you're familiar with the above tutorial they should be straightforward to extrapolate… I think. :-)
In the example, its talking about controlling a sheet instead of a window. A sheet is technically a window component and not a window itself so it can't use a NSWindowController subclass as a controller. A window controller does not know how to handle a window owned by another window.
The text above is just reminding you that although the sheet controller looks very much like a window controller it is not one and that you have to manually handle releasing that is handled automatically by the window controller.