In my project,I added a extra NSWindowController namedNewWindow.Now I want add an button to hiden/view the wimdow.My code as following.
#import "AppDelegate.h"
#import "NewWindow.h"
#interface AppDelegate ()
#property (weak) IBOutlet NSView *view;
- (IBAction)showNewWindow:(id)sender;
#end
#implementation AppDelegate
{
NewWindow *newWindow;
BOOL isNewWindowLoad;
}
-(id)init
{
self = [super init];
if(self)
{
newWindow = [[NewWindow alloc] init];
}
return self;
}
- (IBAction)showNewWindow:(id)sender
{
if(!isNewWindowLoad)
{
[newWindow loadWindow];
isNewWindowsLoad = YES;
}
else
{
[[newWindow window] close];
isNewWindowLoad = NO;
}
}
#end
the window can load,but it can't be hidden.
Anyone can tell me how to do it?Through clicking the button to control the window load/hidden.
Call orderOut to hide the window. It's still there, you can call orderFront or makeKeyAndOrderFront to show it again.
Related
In Objective-C, I am trying to make a NSTextField, when clicked, open a sheet with a NSDatePicker that slides out under the text field. You select a date which closes the sheet and populates the NSTextField with the date chosen.
I have found this article on how to use a protocol to do this in Swift. http://www.knowstack.com/swift-nsdatepicker-sample-code/#comment-20440
But when I convert it to Objective-C I have a few issues.
The first time I click my button to trigger the sheet, the sheet appears in the middle of the screen, ignoring the event:
-(NSRect)window:(NSWindow *)window willPositionSheet:(NSWindow *)sheet usingRect:(NSRect)rect {
When I select a date, the textfield in the main xib is updated with the selection so the protocol part is working but the sheet remains unresponsive on screen.
If I click the button a second time, the unresponsive sheet closes and reappears under the NSTextField and dismisses itself when I choose a date. This is the expected behaviour.
My question is, why does this not work the first time I click the button but only works the second time?
Here is the code:
#import <Cocoa/Cocoa.h>
#protocol DatePickerProtocol
#required
-(void) selectedDate:(NSDate *)date;
#optional
#end
#interface datePickerWindowController : NSWindowController {
id delegate;
}
-(void)setDelegate:(id)newDelegate;
#end
#import "datePickerWindowController.h"
#interface datePickerWindowController ()
#property (weak) IBOutlet NSDatePicker *datePicker;
#end
#implementation datePickerWindowController
- (void)windowDidLoad {
[super windowDidLoad];
self.datePicker.dateValue = [NSDate date];
}
-(void)setDelegate:(id)newDelegate {
delegate = newDelegate;
NSLog(#"delegate has been set in datePickerWindowController");
}
- (IBAction)selectDate:(NSDatePicker *)sender {
[delegate selectedDate:self.datePicker.dateValue];
[self.window close];
}
#end
#import <Cocoa/Cocoa.h>
#import "datePickerWindowController.h"
#interface AppDelegate : NSObject <NSApplicationDelegate, DatePickerProtocol, NSWindowDelegate>
#end
#import "AppDelegate.h"
#interface AppDelegate ()
#property (weak) IBOutlet NSWindow *window;
#property (weak) IBOutlet NSDatePicker *timePicker;
#property (weak) IBOutlet NSTextField *textDate;
#property (retain) datePickerWindowController * myDatePickerWindowController;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
self.window.delegate = self;
[self.window setDelegate:self];
self.textDate.stringValue = [NSString stringWithFormat:#"%#",[NSDate date]];
datePickerWindowController * windowController = [[datePickerWindowController alloc] initWithWindowNibName:#"datePickerWindowController"];
self.myDatePickerWindowController = windowController;
self.myDatePickerWindowController.delegate = self;
[self.myDatePickerWindowController setDelegate:self];
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
}
-(void)selectedDate:(NSDate *)date {
self.textDate.stringValue = [NSString stringWithFormat:#"%#", date];
}
- (IBAction)pickDateButton:(NSButton *)sender {
[self.window beginSheet:self.myDatePickerWindowController.window completionHandler:nil];
}
// Position sheet under text field
-(NSRect)window:(NSWindow *)window willPositionSheet:(NSWindow *)sheet usingRect:(NSRect)rect {
if (sheet == self.myDatePickerWindowController.window) {
NSRect r = self.textDate.frame;
r.origin.y = r.origin.y + 5;
return r;
} else {
return rect;
}
}
#end
I am assuming I have the delegate messed up somehow. Maybe in the xib or the code. I can not see why it works a second time though. Is this due to retain or how I am keeping the DatePicker around.
Many thanks for any help.
I'm currently trying to write a Mac application. In doing so, I'm having some peculiar problems when trying to setup an NSToolbar.
Although I have setup all the components as per the API documentation, when the application loads, the toolbar always starts empty. When I open the customisation pane, the toolbar items are there, and I can drag them into the toolbar, but when I quit the application and restart the changes are gone.
Note: I am aware that many of you will be of the opinion that the best way to solve this is to use interface builder rather than doing it in code. That is not the answer I am looking for - I chose to make this application without IB in order to better understand the internals of a Cocoa app.
I have verified (with NSLogs) that neither the toolbarAllowedItemIdentifiers nor the toolbarDefaultItemIdentifiers delegate methods get called when the toolbar is first initialised, but they do get called when you enter the customisation pane.
Below, please find a minimal, verifiable and complete example version of a basic app that demonstrates this bug. Anyone that can shed some light on this matter would be hugely appreciated!
Thanks
Defines.h
#define UNUSED(x) (void)(x)
#define TOOLBAR_ONE #"ONE"
#define TOOLBAR_TWO #"TWO"
#define TOOLBAR_IDENT #"TOOLBAR"
#define WINDOW_MASK NSTitledWindowMask | \
NSClosableWindowMask | \
NSResizableWindowMask | \
NSMiniaturizableWindowMask
main.m
#import "BWAppDelegate.h"
#import <AppKit/AppKit.h>
int main(void) {
#autoreleasepool {
NSApplication* application = [NSApplication sharedApplication];
BWAppDelegate* delegate = [[BWAppDelegate alloc] init];
application.delegate = delegate;
[application run];
return EXIT_SUCCESS;
}
}
BWAppDelegate.h
#import <Cocoa/Cocoa.h>
#import "BWMainToolbarDelegate.h"
#interface BWAppDelegate : NSObject<NSApplicationDelegate>
#property (atomic, strong) NSWindow* window;
#property (atomic, strong) BWMainToolbarDelegate* toolbarDelegate;
#end
BWAppDelegate.m
#import <AVFoundation/AVFoundation.h>
#import <AppKit/AppKit.h>
#import <Cocoa/Cocoa.h>
#import "BWAppDelegate.h"
#import "Defines.h"
#implementation BWAppDelegate
#synthesize window, toolbarDelegate;
- (void) applicationDidFinishLaunching: (NSNotification*) aNotification
{
UNUSED(aNotification);
NSRect dims = NSMakeRect(0, 0, 300, 300);
self.window = [[NSWindow alloc] initWithContentRect:dims
styleMask:WINDOW_MASK
backing:NSBackingStoreBuffered
defer:NO];
[self.window makeKeyAndOrderFront:nil];
self.window.toolbar = [[NSToolbar alloc] initWithIdentifier:TOOLBAR_IDENT];
toolbarDelegate = [[BWMainToolbarDelegate alloc] initWithToolbar:self.window.toolbar];
}
#end
BWMainToolbarDelegate.h
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
#interface BWMainToolbarDelegate : NSObject<NSToolbarDelegate>
- (instancetype) initWithToolbar: (NSToolbar*) theToolbar;
- (NSArray*) toolbarAllowedItemIdentifiers: (NSToolbar*) toolbar;
- (NSArray*) toolbarDefaultItemIdentifiers: (NSToolbar*) toolbar;
- (NSToolbarItem*) toolbar: (NSToolbar*) toolbar
itemForItemIdentifier: (NSString*) identifier
willBeInsertedIntoToolbar: (BOOL) flag;
#end
BWMainToolbarDelegate.m
#import "BWMainToolbarDelegate.h"
#import "Defines.h"
#implementation BWMainToolbarDelegate {
NSToolbar* toolbar;
}
- (instancetype) initWithToolbar: (NSToolbar*) theToolbar
{
self = [super init];
if(self) {
toolbar = theToolbar;
toolbar.displayMode = NSToolbarDisplayModeIconAndLabel;
toolbar.allowsUserCustomization = YES;
toolbar.autosavesConfiguration = YES;
toolbar.delegate = self;
}
return self;
}
- (NSArray*) toolbarAllowedItemIdentifiers: (NSToolbar*) theToolbar
{
UNUSED(theToolbar);
return #[TOOLBAR_ONE, TOOLBAR_TWO];
}
- (NSArray*) toolbarDefaultItemIdentifiers: (NSToolbar*) theToolbar
{
UNUSED(theToolbar);
return #[TOOLBAR_ONE, TOOLBAR_TWO];
}
- (NSToolbarItem*) toolbar: (NSToolbar*) theToolbar
itemForItemIdentifier: (NSString*) identifier
willBeInsertedIntoToolbar: (BOOL) flag
{
UNUSED(flag);
NSToolbarItem* returnVal = nil;
NSString* label;
if([theToolbar.identifier isEqualToString:TOOLBAR_IDENT]) {
if([identifier isEqualToString:TOOLBAR_ONE]) {
returnVal = [[NSToolbarItem alloc] initWithItemIdentifier:TOOLBAR_ONE];
label = #"Toolbar One";
} else if([identifier isEqualToString:TOOLBAR_TWO]) {
returnVal = [[NSToolbarItem alloc] initWithItemIdentifier:TOOLBAR_TWO];
label = #"Toolbar TWO";
}
}
returnVal.label = label;
returnVal.paletteLabel = label;
return returnVal;
}
#end
Set the delegate of the toolbar before adding the toolbar to the window.
I'm quite new to Mac programming (not to Objective C).
I'm developing a small application, that shows some data and opens a second window on button press.
In the second window is a textfield and a submit button. If the submit button is pressed, the window should close + the value of the textfield needs to be passed to the first window.
I think the best method for that is a simple Delegate. I tried that but i can't change the label in the first window using the second window..
The delegate however seems to work as i can call methods from the other class and send data to it. It just won't change the label.
As this is my first try on Delegates, im pretty sure I've done something stupid here^^
or is there a better solution? Can't be to complicated to change a label from an second window.. right?
ViewController.h (FirstController)
#import <Cocoa/Cocoa.h>
#class ViewController;
#protocol ViewControllerDelegate
-(void)sayHello:(ViewController *)ViewController;
#end
#interface ViewController : NSViewController
{
IBOutlet NSTextField *txtlabel;
}
#property (nonatomic, assign) id delegate;
-(void)helloDelegate;
-(void)reciveVar:(NSString*)strvar;
#end
ViewController.m (FirstController)
#import "ViewController.h"
#implementation ViewController
#synthesize delegate;
-(id)init {
self = [super init];
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
txtlabel.stringValue=#"TEST";
}
-(void)helloDelegate
{
[delegate sayHello:self];
}
-(void)reciveVar:(NSString*)strvar
{
NSLog(#"recived: %#", strvar);
txtlabel.stringValue=strvar; // DOSENT WORK!!
}
#end
secondController.h
#import <Cocoa/Cocoa.h>
#import "ViewController.h"
#interface secondController : NSViewController <ViewControllerDelegate>
{
IBOutlet NSTextField *txtfield;
}
-(IBAction)submit:(id)sender;
#end
secondController.m
#import "firstController.h"
#implementation secondController
-(void)viewDidLoad
{
[super viewDidLoad];
ViewController *custom = [[ViewController alloc] init];
// assign delegate
custom.delegate = self;
[custom helloDelegate];
}
-(void)sayHello:(ViewController *)ViewController
{
NSLog(#"Hiya!");
}
-(IBAction)submit:(id)sender
{
NSString *txtval= txtfield.stringValue;
NSLog(#"submit: %#", txtval);
ViewController *custom = [[ViewController alloc] init];
// assign delegate
custom.delegate = self;
[custom reciveVar:txtval];
}
#end
LOG Output:
Hiya!
submit: test
recived: test
(so i guess the delegate works..)
SOLVED. (Thanks to Phillip Mills)
NSNotification is way simpler and efficient than Delegates in this case.
ViewController.m
[...]
- (void)viewDidLoad
{
[super viewDidLoad];
txtlabel.stringValue=#"TEST";
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(handleUpdatedData:)
name:#"DataUpdated"
object:nil];
}
-(void)handleUpdatedData:(NSNotification *)notification
{
NSLog(#"recieved %#", notification);
txtlabel.stringValue=[notification object];
}
secondController.m
-(IBAction)submit:(id)sender
{
NSString *txtval= txtfield.stringValue;
NSLog(#"submit: %#", txtval);
[[NSNotificationCenter defaultCenter] postNotificationName:#"DataUpdated"
object:txtval];
}
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.
I have a segmented control which when clicked the user will be forced to enter a password.
After a successful check the modal screen should dismiss and in the controller with the segmented control a method is called and a segue should be performed to another controller.
The segue itself works but not after the login check. I think this is a problem with the "self"...
Code of delegate class:
#protocol LoginUserControllerDelegate
- (void)proceedAfterLogin:(BOOL)proceedToNextController;
#end
#interface LoginUserController : UIViewController {
IBOutlet UITextField *loginPWD;
id<LoginUserControllerDelegate> _delegate;
}
#property (nonatomic, retain) UITextField *loginPWD;
#property (nonatomic, assign) id<LoginUserControllerDelegate> delegate;
- (void)checkLogindata; // checks for correct password
#end
#implementation LoginUserController
#synthesize loginPWD;
#synthesize delegate = _delegate;
- (void)checkLogindata {
...
if ([tempDBPWD isEqualToString:tempLoginPWD]) {
if (_delegate != nil) {
[self dismissModalViewControllerAnimated:YES];
[_delegate proceedAfterLogin:YES];
}
}
...
}
#end
The segmented controller with the method:
#interface StartViewController : UIViewController <LoginUserControllerDelegate> {
UISegmentedControl *segmentedControl;
LoginUserController *_loginUserController;
}
#property (nonatomic,retain) IBOutlet UISegmentedControl *segmentedControl;
#property (nonatomic, retain) LoginUserController *loginUserController;
- (IBAction)segmentedControlIndexChanged:(id)sender;
#end
#implementation StartViewController
#synthesize segmentedControl;
#synthesize loginUserController = _loginUserController;
- (IBAction)segmentedControlIndexChanged:(id)sender
{
if (self.segmentedControl.selectedSegmentIndex == 0) {
// get delegate
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
UIStoryboard *storyboard = appDelegate.window.rootViewController.storyboard;
LoginUserController *loginUserControllerView = [storyboard instantiateViewControllerWithIdentifier:#"LoginUserViewID"];
loginUserControllerView.delegate = self;
// now show screen
[self presentModalViewController:loginUserControllerView animated:YES];
} else {
}
}
- (void)proceedAfterLogin:(BOOL)proceedToNextController
{
if (proceedToNextController) {
// yes, correct login now perform the segue to the controller
[[self segmentedControl] setSelectedSegmentIndex:UISegmentedControlNoSegment];
[self performSegueWithIdentifier:#"NextControllerSegueID" sender:self];
}
}
#end
I think the [self performSegueWithIdentifier:#"NextControllerSegueID" sender:self]; is the problem, because self is not correct. Is this where the error arises and how can I achieved my desired behaviour?
You're close, but you need to return to the delegate, and then call dismissModalViewControllerAnimated:YES. A modal controller can't dismiss itself, so you need to do your login, call back to the delegate, and have the delegate dismiss the modal controller.