[UPDATED AFTER FIRST AWNSER]
I have tried to find a way to use and implement the keyDown option in Objective C. But when I try it, it always fails...
Can anyone give me an example of how this is done. I understand Objective C good and a full explaination is not needed.
I deleted the method in -(void) keyDown because it wasn't working.
This is my code now:
#import <Cocoa/Cocoa.h>
#interface ViewController : NSView {
IBOutlet id pressLabel;
}
#end
#import "ViewController.h"
#implementation ViewController
-(BOOL) acceptsFirstResponder
{
return YES;
}
-(BOOL) becomeFirstResponder
{
return YES;
}
-(BOOL) resignFirstResponder
{
return YES;
}
-(void)keyDown:(NSEvent *)theEvent
{
NSString *theUpArrow = [NSString stringWithFormat:#"%c",NSUpArrowFunctionKey];
if( [[theEvent characters] isEqualToString:theUpArrow]){
[pressLabel setStringValue:#"Pressed"];
} else {
[super keyDown:theEvent];
}
}
#end
keyDown: is an NSResponder method, typically implemented in views. This class is named Controller, which would suggest it isn't a view, and thus won't receive key down events. You probably want to put it in a view instead.
[self keyDown:theEvent];
This doesn't solve your problem, but I think for the line above, you want to use super and not self. If you use self it will invoke the same method again, and it will keep invoking the same method over and over, eventually crashing your application once there is no more stack space.
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.
This is a follow-up on the previous question.
Sorry. I could not figure out how to add code or edit something written over 5 minues ago.
A brief summary. I am trying to display a customized/derived TableView over a regular View. I am not using IB, but doing everything from the code. The goal here is to build the application, but also to learn Cocoa/OSX programming. This is my first OSX coding attempt.
NSView atop of which I would like to display my custom TableView is being displayed fine. Please excuse the NSLog garbage. It helps me to learn about the app lifecycle.
Header:
#import <Cocoa/Cocoa.h>
#import "MSNavigationTableView.h"
#interface MSNavigationPanelView : NSView
#property (strong, nonatomic) IBOutlet MSNavigationTableView *myNavigationTable;
#end
code:
#import "MSNavigationPanelView.h"
#implementation MSNavigationPanelView
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
NSLog(#"Initializing Navigation Panel");
}
self.myNavigationTable = [[MSNavigationTableView alloc] initWithFrame:self.frame];
[self.myNavigationTable setDataSource:self.myNavigationTable];
[self.myNavigationTable setDelegate:self.myNavigationTable];
[self addSubview:self.myNavigationTable];
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
[super drawRect:dirtyRect];
// Drawing code here.
NSLog(#"Drawing navigation view!");
}
#end
Now the NSTableView derived class.
Header:
#import <Cocoa/Cocoa.h>
#interface MSNavigationTableView : NSTableView <NSTableViewDataSource>
#end
NSArray *myNavigationArray;
Source:
#import "MSNavigationTableView.h"
#implementation MSNavigationTableView
+ (void)initialize {
NSLog(#"Called NavigationTableView::initialize!");
myNavigationArray = [NSArray arrayWithObjects:#"Call History" #"Contacts", #"Messages", #"Voicemail", nil];
}
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
[super drawRect:dirtyRect];
// Drawing code here.
}
- (NSInteger)numberOfRowsInTableView: (NSTableView *) aTableView
{
return [myNavigationArray count];
}
- (id)tableView: (NSTableView*) aTableView objectValueForTableColumn: (NSTableColumn *)aTableColum row: (NSInteger)rowIndex
{
NSLog([myNavigationArray objectAtIndex:rowIndex]);
return [myNavigationArray objectAtIndex:rowIndex];
}
#end
Thank you. I am sure that I am doing something stupid, and/or perhaps not doing something necessary. I have tried to figure this out for a couple of hours. No ideas so far.
You really need to use Interface Builder to make a table.
I would never try to programmatically initialized a table... to many things to configure.
NSTableView needs to have NSTableColumns, NSTableColumns need to have NSCell's, etc. etc.
NSTableView needs to be embedded in an NSScrollView.
I figured out what needs to be done.
First, array initialization has to be moved from +(void)initialize to another method. For me - (id)initWithFrame works fine.
Second, while this was not clear for me, overwriting NSTableViewDataSource is not enough.
One has to create NSTableColumn(s) then add the column(s) to the table using addTableColumn method of NSTableView class. Once that is done, we proceed with setDataSource and so on.
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 just started reading up on Objective-C yesterday, and i can't quite figure why my
textFieldShouldReturn
method isn't being run.
This is the actual method:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
self.itemTxt.text = #"Return pressed";
return YES;
}
This is the interface line in my header file:
#interface ArrViewController : UIViewController <UITextFieldDelegate>
You need to actively set the delegate for the UITextField:
For example, in viewDidLoad you could write:
myTextField.delegate = self;
You can also hook this up in Interface Builder if desired.
Use setDelegate method of your textfield to self
I'm trying to implement a shake recognition that works throughout my application. To do this I'm adding the following code to my xxxAppDelegate.m:
-(BOOL)canBecomeFirstResponder {
return YES;
}
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event {
if (event.type == UIEventSubtypeMotionShake) {
NSLog(#"Shaken, not stirred.");
}
}
But because in the .h file the delegate is defined as a
#interface xxxAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate>
I cannot use the
[self becomeFirstResponder];
in the .m to make the app delegate the first responder. Therefore of course it doesn't work.
What would be the best way to get it working?
What happens if you change the app delegate to a subclass of UIResponder?
Edit
You can read about the responder chain here in the documentation.