Subclassing NSTextField to forward first responder can't find destination responder? - subclass

I'm subclassing NSTextField in order to have it make another field be first responder instead of itself. I had the field set to refuse first responder but then the window gets it and the user has to find the proper field intuitively, and that could lead to confusion.
My sub-class code contains this:
#import "MyTextField.h"
#import "MyController.h" //which declares: #property (assign) IBOutlet NSWindow *window;
#implementation MyTextField
- (BOOL) becomeFirstResponder
{
[_window makeFirstResponder:otherField];
return NO;
}
#end
The problem is Xcode doesn't find 'otherField' which is defined in my .xib, Xcode says it's 'undeclared' here.
Someday I will have the time to convert the project to Swift, and I will be less of a beginner, but please bear with my ignorance. Please help! How do I make 'otherField' findable in the sub-class code?

Related

How do you archive a plain blue cube object in osx?

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.

Showing Dialog from Xib file

I have a simple task.
There is a xib file named "Preferences.xib"
It contains Window named "Preferences Window", that contains some checkboxes, OK and Cancel.
I need to load this window within my code, and get Ok/Cancel results knowing what checkboxes were checked.
Can someone help me with example or send me to relevant link?
Thanks!
In AppDelegate.h
#interface AppDelegate : NSObject <NSApplicationDelegate>
#property (assign) IBOutlet NSWindow *window;
- (IBAction)showPref:(id)sender;
#property(strong)NSWindowController *windowController;
#property(strong)IBOutlet NSWindow *prefWindow;//hooked to the window of Preferences.XIB
#end
In AppDelegate.m
- (IBAction)showPref:(id)sender {
self.windowController=[[NSWindowController alloc]initWithWindowNibName:#"Preferences"];
self.prefWindow=self.windowController.window;
[self.prefWindow makeKeyAndOrderFront:self];
}
Find sample code here.

Cocoa's WebView does not load a URL upon loading the app

I'm making a simple app, to load up a single URL, I have the following code
webberAppDelegate.h
#import <Cocoa/Cocoa.h>
#import <WebKit/WebKit.h>
#interface webberAppDelegate : NSObject <NSApplicationDelegate> {
NSWindow *window;
WebView *webber;
}
#property (assign) IBOutlet NSWindow *window;
#property (assign) IBOutlet WebView *webber;
#end
webberAppDelegate.m
#import "webberAppDelegate.h"
#implementation webberAppDelegate
#synthesize window;
#synthesize webber;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSString *urlString = #"http://www.apple.com";
// Insert code here to initialize your application
[[webber mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]]];
}
#end
What do I have to do in Interface builder? I've added the Web View, do I need to link it in any way?
Thing is I added simple text field(and linked it to the web view) and it loads the URL just fine when I enter it there, however it doesn't with this code, any ideas?
In your XIB file, you should have an App Delegate object (and some other things).
Right-clicking it should bring up a HUD list, where you'll see each of your outlets (and, again, some other things).Find the webber outlet, and click the circle to its right. Then drag to your WebView.
What you've just done is linked your properties to your XIB objects. Skip this step, and your App Delegate won't know what webber is referring to.
Also, note that in order to populate that HUD list, your properties need to be specifically tagged with IBOutlet.

IBOutlets not showing

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

Question about NSWindowController and NSPersistentDocument Core Data Tutorial

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.

Resources