NSTextField doesn't respond to keyboard input - objective-c

I tried to write a single-window application using Objective-C in OS X 10.8 to test some thing. Everything works fine except that the NSTextField I created does not respond to keyboard input. The code is as follows:
#import <Cocoa/Cocoa.h>
#interface customizedView:NSView
+(customizedView *)aCustomizedView; // changed method name to follow convention
#end
#implementation customizedView
+(customizedView *)aCustomizedView{
customizedView *newView = [[[customizedView alloc] initWithFrame:NSMakeRect(0,0,400,300)] autorelease];
NSTextField *tf = [[[NSTextField alloc] initWithFrame:NSMakeRect(200,150,150,50)] autorelease];
[newView addSubview: tf positioned:NSWindowBelow relativeTo:newView];
return newView;
}
-(void)windowWillClose:(NSNotification *)aNot{
[NSApp terminate:self];
}
#end
void setup(){
NSWindow *aWindow = [[[NSWindow alloc] initWithContentRect:NSMakeRect(0,0,400,300) styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask backing:2 defer:NO] autorelease];
customizedView *aView = [customizedView aCustomizedView];
[aWindow setContentView:aView];
[aWindow setDelegate:aView];
[aView setNeedsDisplay:YES];
[aWindow makeKeyAndOrderFront:nil];
}
int main(int argc, char **argv){
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSApplication *NSApp = [NSApplication sharedApplication];
setup();
[NSApp run]; [NSApp release]; [pool release];
exit(EXIT_SUCCESS);
}
Compile using
gcc -w filename.m -o tmp -framework Cocoa
Everything works except that I cannot input using keyboard to input into the textfield in my customized NSView. Paste using mouse is okay. So far I still have no ideal why this happens and I give my thanks in advance to all who read this tip sincerely.

Related

How do assign a type of file to my app on Mac

I try to assign a file type to my application.
In Info.plist I add:
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>type</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>icon</string>
<key>CFBundleTypeName</key>
<string>My Project</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSTypeIsPackage</key>
<false/>
</dict>
</array>
In Main.mm:
....
-(BOOL) application:(NSApplication *)sender openFile:(NSString *)filename {
NSLog(#"Opened by file");
return YES;
}
#end
int main(int argc, char* argv[]) {
[NSApplication sharedApplication];
[[[[Window alloc] init] autorelease] makeMainWindow];
[NSApp run];
return 0;
}
But when I try double click on the my file type, The app only open with the warn: could not be opened, MyApp cannot open file in format. Also the message from NSLog is not called at all.
There are several issues with the code you posted but I was able to get the desired behavior with a few modifications.
I assume this is your window interface and implementation:
#interface Window : NSWindow <NSApplicationDelegate>
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;
#end
#implementation Window
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename {
NSLog(#"Opened by file");
return YES;
}
#end
This is extremely odd to be using a window object as an application delegate. Normally, you have a controller object that owns and manages the window and also acts as the application's delegate.
In any case, it's still possible to get... well, functional behavior by changing the main() function to the following:
int main(int argc, const char * argv[]) {
[NSApplication sharedApplication];
Window *window = [[[Window alloc] init] autorelease];
NSApp.delegate = window;
[window makeKeyAndOrderFront:nil];
[NSApp run];
return 0;
}
There are two notable changes. First, your problem was that you didn't set the window instance to be the application delegate. Second, IIRC, you should never call -makeMainWindow directly; rather, that method exists so that you can override it if you wish. If you want to display the window on screen, you call -makeKeyAndOrderFront:.
Opening a file should display the logged line in console (if you're using Xcode 12.5.1, resize the log window if needed to workaround the display bug).
Under manual reference counting, I believe this would leak memory, since no autorelease pool is created, but I didn't see any of the usual warnings in console. Anyway, while this code works, it results in a fairly undesirable scenario. There is no main menu in the app so to quit it you have to use the Dock. The window created is also tiny and has no resizing capabilities, etc.
EDIT: An example project is at https://github.com/NSGod/OpenFile.
The following subclass of NSWindow should allow you to save a file with a unique ‘.jaf’ extension and then reopen the file into the app by double clicking on it. The info.plist is not as critical as I initially thought; I did not alter the one created by Xcode. Most important for this non-Document based app seems to be the calling of NSApplicationDelegate method -(BOOL) application: openFile. The NSApplicationDelegate was added to the NSWindow subclass instead of having a separate AppDelegate as is usually the case. When working correctly you should hear a beep when this method is called after a .jaf file is double-clicked; I couldn’t find the NSLog output. To run the demo in Xcode first create an objc project and delete everything in the ‘main.m’ file and copy/paste the following source code into it. Delete the pre-supplied AppDelegate class to avoid duplicate symbols. In the entitlements set the App Sandbox to NO and set read-only to zero. After the JAF app has been made, use it to save a file to your desktop with the ‘.jaf’ extension. Then make a copy of the app (shown in the Finder) and copy/paste it into the Applications folder. The next step is critical; right click on the file that you just made and use either Get Info or Open With to set the file to always open with your newly made app. At this point you should be able to double click on the xxxx.jaf file and have it open into your app with an audible beep.
#import <Cocoa/Cocoa.h>
#interface Window : NSWindow <NSApplicationDelegate> {
NSTextView *txtView;
}
- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSWindowStyleMask)style backing:(NSBackingStoreType)backingStoreType defer:(BOOL)flag;
-(void) buildMenu;
-(void) openAction;
-(void) saveAction;
#end
#implementation Window
#define _wndW 700
#define _wndH 550
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename {
NSLog(#"This comes from JAF : filename = %#.",filename);
NSBeep(); // Listen for this.
NSError *error;
NSURL *url = [NSURL fileURLWithPath:filename];
NSString *fileStr = [[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
if (!fileStr) {
NSLog(#"Unable to open file %#", error);
} else {
[txtView setString:fileStr];
}
return YES;
}
-(void) buildMenu {
// **** Menu Bar **** //
NSMenu *menubar = [NSMenu new];
[NSApp setMainMenu:menubar];
// **** App Menu **** //
NSMenuItem *appMenuItem = [NSMenuItem new];
NSMenu *appMenu = [NSMenu new];
[appMenu addItemWithTitle: #"Quit" action:#selector(terminate:) keyEquivalent:#"q"];
[appMenuItem setSubmenu:appMenu];
[menubar addItem:appMenuItem];
}
-(void) openAction {
NSOpenPanel *op = [NSOpenPanel openPanel];
[op setAllowedFileTypes:[NSArray arrayWithObjects: #"jaf", #"txt", nil]];
[op beginSheetModalForWindow: self completionHandler: ^(NSInteger returnCode) {
if (returnCode == NSModalResponseOK) {
NSURL *url = [op URL];
NSError *error;
NSString *fileStr = [[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
if (!fileStr) {
NSLog(#"Unable to open file %#", error);
} else {
[self->txtView setString:fileStr];
}
}
}];
}
-(void) saveAction {
NSSavePanel *sp = [NSSavePanel savePanel];
[sp setTitle:#"Save contents to file"];
[sp setAllowedFileTypes:[NSArray arrayWithObjects: #"jaf", nil]];
[sp setNameFieldStringValue: #".jaf"];
[sp beginSheetModalForWindow: self completionHandler: ^(NSInteger returnCode) {
if (returnCode == NSModalResponseOK) {
NSURL *url = [sp URL];
NSString *viewStr = [[self->txtView textStorage] string];
NSError *err;
BOOL fileSaved = [viewStr writeToURL:url atomically:YES encoding:NSUTF8StringEncoding error:&err];
if (!fileSaved) { NSLog(#"Unable to save file due to error: %#", err);}
}
}];
}
- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSWindowStyleMask)style backing:(NSBackingStoreType)backingStoreType defer:(BOOL)flag {
self = [super initWithContentRect:NSMakeRect(0, 0, _wndW, _wndH) styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable backing:NSBackingStoreBuffered defer:NO];
[self setTitle: #"Test window"];
[self center];
[self makeKeyAndOrderFront: nil];
// ****** NSTextView with Scroll ****** //
NSScrollView *scrlView = [[NSScrollView alloc] initWithFrame:NSMakeRect( 10, 10, _wndW - 20, _wndH - 80 )];
[[self contentView] addSubview:scrlView];
[scrlView setHasVerticalScroller: YES];
[scrlView setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
txtView = [[NSTextView alloc] initWithFrame:NSMakeRect( 0, 0, _wndW - 20, _wndH - 80 )];
[scrlView setDocumentView: txtView];
// **** Open Button **** //
NSButton *openBtn =[[NSButton alloc]initWithFrame:NSMakeRect( 30, _wndH - 50, 95, 30 )];
[openBtn setBezelStyle:NSBezelStyleRounded ];
[openBtn setTitle: #"Open"];
[openBtn setAutoresizingMask: NSViewMinYMargin];
[openBtn setAction: #selector (openAction)];
[[self contentView] addSubview: openBtn];
// **** Save Button **** //
NSButton *saveBtn =[[NSButton alloc]initWithFrame:NSMakeRect( 130, _wndH - 50, 95, 30 )];
[saveBtn setBezelStyle:NSBezelStyleRounded ];
[saveBtn setTitle: #"Save"];
[saveBtn setAutoresizingMask: NSViewMinYMargin];
[saveBtn setAction: #selector (saveAction)];
[[self contentView] addSubview: saveBtn];
return self;
}
- (BOOL)windowShouldClose:(id)sender {
[NSApp terminate:sender];
return YES;
}
#end
int main() {
NSApplication *application = [NSApplication sharedApplication];
Window *window = [[Window alloc]init];
[window buildMenu];
[application setDelegate:window];
[application activateIgnoringOtherApps:YES];
[NSApp run];
return 0;
}

I can't write text to NSTextField Objective C

I've spent much time finding an answer but I don't understand how right it googling.
I just need to create a simple text field. I've done it but I can't write some text.
After build and run I tried to write but the text was written in x-code window.
What's wrong?
I guess it's related to focus NSWindow or NSApplication.
It's very strange because I can call the context menu and I see cut/copy/paste functions. I even can use those but I can write text by the keyboard.
All code already in main.m
#include <Cocoa/Cocoa.h>
#interface Window : NSWindow {
NSTextField* textBox1;
NSTextField* textBox2;
}
- (instancetype)init;
- (BOOL)windowShouldClose:(id)sender;
#end
#implementation Window : NSWindow
- (instancetype)init {
NSTextField* textBox1 = [[[NSTextField alloc] initWithFrame:NSMakeRect(10, 270, 100, 20)] autorelease];
[textBox1 setStringValue:#"textBox1"];
NSTextField* textBox2 = [[[NSTextField alloc] initWithFrame:NSMakeRect(10, 230, 100, 20)] autorelease];
[textBox2 setStringValue:#"textBox2"];
[super initWithContentRect:NSMakeRect(100, 100, 300, 300)
styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable | NSWindowStyleMaskUnifiedTitleAndToolbar
backing:NSBackingStoreBuffered
defer:NO];
[self setTitle:#"TextBox Example"];
[[self contentView] addSubview:textBox1];
[[self contentView] addSubview:textBox2];
[self makeFirstResponder:textBox2];
[self setIsVisible:YES];
return self;
}
- (BOOL)windowShouldClose:(id)sender {
[NSApp terminate:sender];
return YES;
}
#end
int main(int argc, char* argv[]) {
[[[Window alloc] init] autorelease];
NSApplication *application = [NSApplication sharedApplication];
[application activateIgnoringOtherApps:YES];
[NSApp run];
}
Thank you for your help but it didn't help me... :(
I could resolve my problem.
I just added the method call setActivationPolicy.
int main(int argc, char* argv[]) {
[[[Window alloc] init] autorelease];
NSApplication *application = [NSApplication sharedApplication];
[application activateIgnoringOtherApps:YES];
[application setActivationPolicy:NSApplicationActivationPolicyRegular];
[NSApp run];
}

Adding events to NSWindow using Cocoa and Objective-C++

I've seen a lot of questions, but I couldn't find anything what helped me. I've looked at many Apple developer pages, but I find those to be a bit unclear.
I want to make applications in Objective-C++ without Xcode or any other IDE that does all the work for me. My IDE is Atom, and I compile with g++. I have the following class to create a window:
//Window.mm
#ifndef WINDOW_H
#define WINDOW_H
#import "Cocoa/Cocoa.h"
class Window
{
private: NSWindow* window;
public: Window(const char* title, int x, int y, int w, int h, NSColor* bg = [NSColor colorWithCalibratedRed:0.3f green:0.3f blue:0.3f alpha:1.0f])
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
[NSApplication sharedApplication];
NSRect frame = NSMakeRect(x, y, w, h);
NSUInteger windowStyle = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable;
NSRect rect = [NSWindow contentRectForFrameRect:frame styleMask:windowStyle];
this->window = [[[NSWindow alloc] initWithContentRect:rect styleMask:windowStyle backing:NSBackingStoreBuffered defer:NO] autorelease];
[this->window makeKeyAndOrderFront: this->window];
[this->window setBackgroundColor: bg];
[this->window setTitle: [NSString stringWithUTF8String:title]];
[this->window orderFrontRegardless];
[pool drain];
[NSApp run];
}
};
#endif
From what I did understand is that I need to do something with an NSView, but I'm not sure what I'm supposed to do. How will I be able to get key input from my window?
You need to subclass NSWindow in order to receive key input events, for example:
KWCustomWindow.h:
#import <Cocoa/Cocoa.h>
#interface KWCustomWindow : NSWindow
#end
KWCustomWindow.m
#import "KWCustomWindow.h"
#implementation KWCustomWindow
- (void)keyDown:(NSEvent *)event
{
NSLog(#"Key Down");
}
#end

crash in `[NSApp run]` when delegate is not referenced anymore

This is the code:
#interface AppDelegate : NSObject <NSApplicationDelegate>
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
printf("My app delegate: finish launching\n");
}
#end
int main(int argc, char *argv[])
{
#autoreleasepool
{
[NSApplication sharedApplication];
[NSApp setDelegate:[[AppDelegate alloc] init]];
[NSApp run];
}
}
It crashes in [NSApp run] but I don't really see what I'm missing. If I add an [NSApp finishLaunching] before the run, it crashes in there.
If I don't set the delegate, it doesn't crash.
If I reference the delegate before, it works fine:
AppDelegate* appDelegate = [[AppDelegate alloc] init];
[NSApp setDelegate:appDelegate];
So I guess it releases the delegate immediately in the first version because of ARC and because the delegate is probably only a weak reference, right? But how are you supposed to do the same code otherwise?
Yes you guess right, NSApplication don't retain the delegate, (weak reference with ARC).
So you can just build the main.m file with -fno-objc-arc with you current code :
int main(int argc, char *argv[])
{
#autoreleasepool
{
[NSApplication sharedApplication];
[NSApp setDelegate:[[AppDelegate alloc] init]];
[NSApp finishLaunching];
[NSApp run];
}
}
or set you AppDelegate static in main.m, for example, and build with ARC
static AppDelegate* _appDelegate;
int main(int argc, char *argv[])
{
#autoreleasepool
{
_appDelegate = [[AppDelegate alloc] init];
[NSApplication sharedApplication];
[NSApp setDelegate:_appDelegate];
[NSApp run];
}
}

Xcode SIGABRT when accessing photo gallery

I've been trying to get my application to select a photo from the photo gallery and then display it, it worked in a different project fine, but in this one the application runs fine but when I press the UIButton that is supposed to bring up the gallery, I get the error SIGABRT in main.m on int retVal = UIApplicationMain(argc, argv, nil, nil);
As I said, this has worked fine in the past so I don't know why it isn't now, here's the parts of the code related to the error, I'm only posting that as I've got a lot of code and it's easier this way.
ViewController.h
#import <UIKit/UKit.h>
#interface ViewController : UIViewController
<UIImagePickerControllerDelegate, UINavigationControllerDelegate>
{
//Blah blah blah
}
//Blah blah blah
-(IBAction) selectExistingpicture;
#property (nonatomic, retain) IBOutlet UIImageView *theImageView;
//Blah blah blah
#end
ViewController.m
#import "ViewController.h"
#implementation ViewController
#synthesize theImageView;
-(IBAction) selectExistingPicture
{
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary])
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
[self presentModalViewController:picker animated:YES];
[picker release];
}
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage : (UIImage *)image editingInfo:(NSDictionary *)editingInfo
{
theImageView.image = image;
[picker dismissModalViewControllerAnimated:YES];
}
-(void)imagePickerControllerDidCancel:(UIImagePickerController *) picker
{
[picker dismissModalViewControllerAnimated:YES];
}
I have linked selectExistingPicture to a UIButton but I don't know what's causing that button to cause me errors.
Any help is greatly appreciated.
Here is how i use my camera roll
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagePickerController.mediaTypes = [NSArray arrayWithObjects:(NSString *) kUTTypeImage, (NSString *) kUTTypeMovie,
nil];
imagePickerController.delegate = self;
[self presentModalViewController:imagePickerController animated:YES];
}
else {
NSLog(#"Error");
}
the thing that i see wrong with yours is
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
which should be
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
Also you appear to be missing
imagePickerController.mediaTypes = [NSArray arrayWithObjects:(NSString *) kUTTypeImage, (NSString *) kUTTypeMovie,
nil];
Take a look at how i have mine set up
Your problem has nothing to do with the photo gallery. It probably never executes selectExistingPicture in the first place.
Possible problems:
The view controller isn't an instance of ViewController because you didn't specify the correct class in IB.
You write selectExistingpicture instead of selectExistingPicture (lower vs. upper case P) in a few places.
selectExistingpicture != selectExistingPicture...
that is you declare selectExistingpicture then define selectExistingPicture which is why your autocomplete would select selectExistingpicture for you, as it exists in your .h file, this mis-match will cause a compiler warning... change all instances to proper camelCased selectExistingPicture and you will be fine... well at least that error will go away.
As others noted, you have a typo (incorrect case on selectExistingPicture), noted for you right there in the error message:
reason: '-[ViewController selectExistingpicture]: unrecognized
selector