OK, what am I doing wrong?
1. Created cocoa app and appDelegate named: window2AppDelegate
2. window2AppDelegate.h
#import "PrefWindowController.h"
#interface window2AppDelegate : NSObject <NSApplicationDelegate> {
NSWindow *window;
PrefWindowController * ctrl;
}
#property (assign) IBOutlet NSWindow *window;
- (IBAction) buttonClick:(id)sender;
- (IBAction) buttonCloseClick:(id)sender;
#end
3. in xib editor, window connected to window controller - set to appdelegate, buttonclick actions to buttons
4, created
#import <Cocoa/Cocoa.h>
#interface PrefWindowController : NSWindowController {
#private
}
#end
#import "PrefWindowController.h"
#implementation PrefWindowController
- (id)init {
self = [super initWithWindowNibName: #"PrefWindow"];
return self;
}
- (void)dealloc {
// Clean-up code here.
[super dealloc];
}
- (void)windowDidLoad {
[super windowDidLoad];
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
}
#end
5. created new xib file named PrefWindow window IBOutlet connected to window from its controller (also controller set to PrefWindowController) Option "Visible At Launch" UNCHECKED! i want to see this window on buttonclick.
6. implemented window2AppDelegate
#import "window2AppDelegate.h"
#implementation window2AppDelegate
#synthesize window;
- (id) init {
if ((self = [super init])) {
ctrl = [[PrefWindowController alloc] init];
if ([ctrl window] == nil)
NSLog(#"Seems the window is nil!\n");
}
return self;
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
return YES;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
}
- (IBAction) buttonClick:(id)sender {
// [[ctrl window] makeKeyAndOrderFront:self]; this doesn't work too :(
NSLog(#"it is here");
[ctrl showWindow:sender];
}
- (IBAction) buttonCloseClick:(id)sender {
[window close];
}
#end
7. After I build and run app: closebutton closes the app but buttonclick - won't show me PrefWindow!? Why and what am i doing wrong? Don't dell me that to show other window in cocoa objective-c is more difficult than in "stupid" Java or C#?
Finally i've managed the problem! In the nib editor for PrefWindow I had to do: Set File's owner class to: NSWindowController then connect window IBOutlet from File's owner to my (preferneces) window. After 6 days of unsuccessful attempts, google works.
Anyway, thanks for all your responses and time!
I'd suggest you move the creation of the PrefWindowController to applicationDidFinishLaunching:
I am not sure the application delegate's init method is called. Probably only initWithCoder: gets called when unarchiving the object from the NIB.
- (id) init {
if ((self = [super init])) {
ctrl = [[PrefWindowController alloc] init];
if ([ctrl window] == nil)
NSLog(#"Seems the window is nil!\n");
}
return self;
}
init is way too early in the scheme of things to be trying to test IBOutlets. They will still be nil yet. Not until later on in the object creation process will the nib outlets be "hooked up". The standard method where you can know that everything in the nib file has been hooked up is:
- (void)awakeFromNib {
}
At that point, all of your IBOutlets should be valid (provided they're not purposely referencing an object in a separate, yet-unloaded nib).
If PrefWindowController is a class that will only be used after the user chooses Preferences from the app menu, I would have to disagree with the others and say that I would not create the instance of the PrefsWindowController at all during the initial load. (Your main controller should be able to function independently from the prefs window). If you have a method that is meant to load the preferences window, then when that method is called, you should check to see if the PrefsWindowController instance is nil, and if it is, create it, then proceed to show the prefs window.
Related
I have successfully implemented a file-drop functionality in my app. The Application window has a few NSTabView objects where dropping on them does not work. Anywhere else in the window the file-drop works fine.
I have tried to make the app delegate a delegate for the NSTabView, but this did not help.
Anyone have a setup for the NSTabView not to filter out the drop-actions so the whole window can be transparent to the file-drop actions ?
For a more generic solution than olekeh's I made it IB friendly so you can hook it up to any object that complies with the NSDraggingDestination protocol.
#import <Cocoa/Cocoa.h>
#interface DropFilesView : NSView
#property (nullable, assign) IBOutlet id<NSDraggingDestination> dropDelegate;
#end
#implementation DropFilesView
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
}
-(void) awakeFromNib {
[self registerForDraggedTypes:
[NSArray arrayWithObjects:NSFilenamesPboardType,
(NSString *)kPasteboardTypeFileURLPromise,kUTTypeData, NSURLPboardType, nil]]; //kUTTypeData
[super awakeFromNib];
}
-(NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender{
return [self.dropDelegate draggingEntered:sender];
}
- (BOOL)performDragOperation:(id < NSDraggingInfo >)sender {
return [self.dropDelegate performDragOperation:sender];
}
#end
I found the solution to this !! - I am posting it here for others who might need.
The NSTabView object has for each of its tabs an NSTabViwItem.
Under each of those, there is a regular NSView - that I subclassed with the following code: - The code assumes that you already have "draggingEntered" and "performDragOperation" in your AppDelegate as this class just forwards these messages to the app delegate. You will also need to put the declarations for those methods in you AppDelegate.h
// DropFilesView.h
#import <Cocoa/Cocoa.h>
#import "AppDelegate.h"
#interface DropFilesView : NSView
#end
and the implementation:
// DropFilesView.m
#import "DropFilesView.h"
#implementation DropFilesView
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
}
-(void) awakeFromNib {
[self registerForDraggedTypes:
[NSArray arrayWithObjects:NSFilenamesPboardType,
(NSString *)kPasteboardTypeFileURLPromise,kUTTypeData, NSURLPboardType, nil]]; //kUTTypeData
[super awakeFromNib];
}
-(NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender
{
AppDelegate* del = [AppDelegate sharedAppDelegate];
return [del draggingEntered:sender];
}
- (BOOL)performDragOperation:(id < NSDraggingInfo >)sender {
AppDelegate* del = [AppDelegate sharedAppDelegate];
return [del performDragOperation:sender];
}
#end
In Interfacebuilder, I set the new class for all the NSView objects covering areas where drop does not work, to this new one.
A similar approach can be used for NSImageView and the WebView classes. However, for the last one, do not use [super awakeFromNib] to prevent the default drag-and drop handling for the web view object.
I am new in cocoa application development. I am trying to create model based application in cocoa.
I created two windows in cocoa application say mainMenu.xib and windows2.xib. The mainMenu.xib is created while project creation and windows2.xib is manually created. Now I inserted a button on mainMenu.xib say (button1) and when clicked on button then window2.xib poped up but when click on button of second windows it is generated a error. the code is follwoing
AppDelegate.h
#interface AppDelegate : NSObject <NSApplicationDelegate>
And AppDelegate.mm
#import "AppDelegate.h"
#implementation AppDelegate
NSWindowController *AdvSettingController;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
}
- (IBAction)AdvSettingBtn:(id)sender {
AdvSettingController= [[NSWindowController alloc] initWithWindowNibName:#"window2"];
[NSApp runModalForWindow:AdvSettingController.window];
[NSApp endSheet:AdvSettingController.window];
[AdvSettingController.window orderOut:self];
}
- (IBAction)OkBtn:(id)sender {
[NSApp terminate:self];
}
- (IBAction)CancelBtn:(id)sender {
[NSApp terminate:self];
}
Now, windows2.h file for second windows(windows2.xib)
#import <Cocoa/Cocoa.h>
#interface windows2 : NSWindowController
#end
and windows2.mm
#import "windows2.h"
#interface windows2 ()
#end
#implementation windows2
- (id)initWithWindow:(NSWindow *)window
{
self = [super initWithWindowNibName:#"windows2"];
if (self) {
// Initialization code here.
}
return self;
}
- (void)windowDidLoad
{
[super windowDidLoad];
// Implement this method to handle any initialization after your window controller's window has been loaded from
}
- (IBAction)CancelBtn:(id)sender {
[self.window close];
} **//Error is generating at run time when clicked on button of second dialog**
You are trying to connect the CancelButton method, but the instance method is named CancelBtn.
In one of my controllers I'd like to open a modal sheet on 10.9.
This is the implementation code for the first controller:
#import "ABSAdvancedPreferencesViewController.h"
#import "ABSUnsyncableWindowController.h"
#interface ABSAdvancedPreferencesViewController ()
#property (strong, nonatomic) ABSUnsyncableWindowController *unsyncableWindowController;
#end
#implementation ABSAdvancedPreferencesViewController
- (id)init {
return [super initWithNibName:#"ABSAdvancedPreferencesViewController" bundle:nil];
}
- (IBAction)showUnsyncableSheet:(id)sender {
if (self.unsyncableWindowController == nil) {
self.unsyncableWindowController = [ABSUnsyncableWindowController new];
}
[self.view.window beginSheet:[self.unsyncableWindowController window] completionHandler:^(NSModalResponse returnCode) {
CLS_LOG(#"Table dismissed");
}];
}
When I execute the linked IBAction nothing happens. The NSWindowController subclass that should should show the modal has a XIB, Visible at launch is deactivated and window is already an outlet.
Debugging I saw that the window parameter is nil here, presumably because I call new in the previous controller:
#implementation ABSUnsyncableWindowController
- (id)initWithWindow:(NSWindow *)window {
self = [super initWithWindow:window];
if (self) {
// Initialization code here.
}
return self;
}
Is there something else that I can check to show the modal sheet?
your ABSAdvancedPreferencesViewController initmethod is missing assigning the super result to self. Also, why don't you alloc/init the sheet controller as expected?
self.unsyncableWindowController = [[ABSUnsyncableWindowController alloc] initWithWindowNibName:#"XIBNAME"];
That should alloc the window controller and you should be able to access its window for display.
My approach to this may be all wrong so I appreciate your patience.
I have a button in my main XIB file linked to this method in my document.m file:
- (IBAction)showTagModal:(id)sender {
if (!_FileTagWindowController){
_FileTagWindowController = [[FileTagWindowController alloc]init];
}
[_FileTagWindowController showWindow:self];
}
_FileTagWindowController is declared as a property in document.h and using breakpoints when the method is called, as far as I can tell is initializing properly, however _windowNibName and _window remains nil.
FileTagWindowController.h looks like this.
#import <Cocoa/Cocoa.h>
#interface FileTagWindowController : NSWindowController{
}
#property (strong) IBOutlet NSArrayController *tagsArray;
- (IBAction)saveContext:(id)sender;
#end
FileTagWindowController.m looks like this:
#import "FileTagWindowController.h"
#interface FileTagWindowController ()
#end
#implementation FileTagWindowController
- (id)initWithWindow:(NSWindow *)window
{
self = [super initWithWindow:window];
if (self) {
// Initialization code here.
}
return self;
}
- (void)windowDidLoad
{
[super windowDidLoad];
NSLog(#"Window Did Load!");
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
}
- (IBAction)saveContext:(id)sender {
}
#end
in my FileTagWindowController.xib I have File Owner set to FileTagWindowController as the custom class. I have the File Owner's "window" outlet linked to the window (NSPanel). That's all that should be required correct? The NSLOG statement in WindowDidLoad never gets called. I tried using [super initWithWindowNibName] in FileTagWindowController.m but that crashes not only the app, but Xcode as well with an endless initialization loop. Am I missing something obvious here?
Thanks all so much.
Try something like the following.
// document.h
#import "FileTagWindowController.h"
#property (strong) filetagWindowController *FileTagWindowController;
// document.m
#synthesize filetagWindowController;
- (IBAction)showTagModal:(id)sender {
if (self.filetagWindowController == nil) {
self.filetagWindowController = [[FileTagWindowController alloc] initWithWindowNibName:#"FileTagWindowController"];
}
[filetagWindowController showWindow:self];
[[filetagWindowController window] setReleasedWhenClosed:NO];
[NSApp runModalForWindow:filetagWindowController.window];
filetagWindowController = nil;
}
You may also want to call NSWindowWillCloseNotification to observe its state and see if filetagWindowController is closed.
I was wondering if it is possible to open a second window with like a button. I have no clue how to do this, please help.
First set up an IBAction to get called when the user clicks the button.
- (IBAction)buttonClicked:(id)sender {
}
In Interface Builder, control-drag from the NSButton object you want to fire that action to the method implementation.
Now, to create a second window, you'll probably want to create a SecondWindowController class to manage it. Declare an IBOutlet to the NSWindow and hook it up in Interface Builder, just like you did for the IBAction (by control-dragging to the IBOutlet declaration).
In the initializer, load the nib file that contains the window you're presenting.
- (id)init {
if (self = [super init]) {
[NSBundle loadNibNamed:#"DubBouncerConversionProgressWindow" owner:self];
}
return self;
}
Then, define a method to present the window by calling orderFront: on it.
- (void)displayWindow {
if (![progressWindow isVisible]) {
[progressWindow setIsVisible:YES];
[progressWindow orderFront:nil];
}
}
Now, when the user clicks the button you can call -displayWindow on an instance of SecondViewController.
- (IBAction)buttonClicked:(id)sender {
[mySecondViewController displayWindow];
}
Here's a full picture of what's going on:
FirstViewController.h
#interface FirstViewController : NSObject {
SecondViewController *mySecondViewController;
}
- (IBAction)buttonClicked:(id)sender;
#end
FirstViewController.m
#implementation FirstViewController
- (IBAction)buttonClicked:(id)sender {
if (!mySecondViewController) {
// If the second view controller doesn't exist yet, make it!
mySecondViewController = [[MySecondViewController alloc] init];
}
[mySecondViewController displayWindow];
}
#end
SecondViewController.h
#interface SecondViewController : NSObject {
IBOutlet NSWindow *progressWindow;
}
- (void)displayWindow;
#end
SecondViewController.m
#implementation SecondViewController
- (id)init {
if (self = [super init]) {
[NSBundle loadNibNamed:#"DubBouncerConversionProgressWindow" owner:self];
}
return self;
}
- (void)displayWindow {
if (![progressWindow isVisible]) {
[progressWindow setIsVisible:YES];
[progressWindow orderFront:nil];
}
}
#end
Connect the button to the NSWindow's orderFont: action. I haven't got Xcode 4, so I can't tell you how to do it in there, but for Xcode 3, open the xib in Interface Builder. While holding the control key, click and drag a line from the button to another window in the nib (drag over the title bar if the window is opened up, otherwise drag it onto the icon in the xib project window). In the menu that pops up, choose "orderFront:" or "makeKeyAndOrderFront:" (depending on the required behaviour).
If the window is in another nib, you'll need to use an approach like Stephen's.