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

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];
}
}

Related

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];
}

How do i ensure that i close my app only when all the threads have finished execution in objective - c

I have the following code
#interface MCMCustomURLSchemeHandler : NSObject
- (void)getUrl:(NSAppleEventDescriptor *)event
withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
#end
#implementation MCMCustomURLSchemeHandler
- (void)getUrl:(NSAppleEventDescriptor *)event
withReplyEvent:(NSAppleEventDescriptor *)replyEvent
{
// Get the URL
NSString *urlStr = [[event paramDescriptorForKeyword:keyDirectObject]
stringValue];
NSLog(#" CUSTOM URL %#", urlStr);
//TODO: Your custom URL handling code here
}
#end
#interface MyObject : NSObject
+(void)aMethod:(id)param;
#end
#implementation MyObject
+(void)aMethod:(id)param{
#autoreleasepool {
[NSApp activateIgnoringOtherApps:YES];
NSAppleScript *script = [[NSAppleScript alloc] initWithSource:scriptToLaunch];
[script executeAndReturnError:nil];
NSLog(#"hitting this point");
}
}
#end
int main(int argc, char *argv[]) {
#autoreleasepool {
MCMCustomURLSchemeHandler *mcmCustomURLHandler = [[MCMCustomURLSchemeHandler alloc] init];
NSAppleEventManager *em = [NSAppleEventManager sharedAppleEventManager];
[em
setEventHandler:mcmCustomURLHandler
andSelector:#selector(getUrl:withReplyEvent:)
forEventClass:kInternetEventClass
andEventID:kAEGetURL];
[NSThread detachNewThreadSelector:#selector(aMethod:) toTarget:[MyObject class] withObject:nil];
//sleep(10000);
return 0;
}
}
In the MyObject method, i am launching a Jar. Till i quit my Jar, i do not get a callback.
How do i ensure that my app continues to be in running state when my thread is listening to the Jar.
I need the app to be in a functional position (sleep won't help) because it has to listen to some other events (custom URL).

How do I go about handling Cocoa Events in a fullscreen application

I have been trying to create an app for Cocoa without a nib/xib (No, I don't want to use a nib/xib. I want to be in full control programatically) and I can't seem to be able to catch the Events such as keystrokes and mouse clicks. Here is the code I have so far:
Main.m
#import <Cocoa/Cocoa.h>
#import "AppDelegate.h"
int main(int argc, char *argv[])
{
#autoreleasepool {
NSApplication *app = [NSApplication sharedApplication];
AppDelegate *appDelegate = [[AppDelegate alloc] init];
[app setDelegate:appDelegate];
[app activateIgnoringOtherApps:YES];
[app run];
}
return EXIT_SUCCESS;
}
AppDelegate.h/m
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate>
{
NSWindow *window;
}
#end
#import "AppDelegate.h"
#import "GLView.h"
#implementation AppDelegate
- (id)init{
self = [super init];
if (!self) {
return nil;
}
NSRect bounds = [[NSScreen mainScreen] frame];
GLView *view = [[GLView alloc]initWithFrame:bounds];
window = [[NSWindow alloc] initWithContentRect:bounds
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
[window setReleasedWhenClosed:YES];
[window setAcceptsMouseMovedEvents:YES];
[window setContentView:view];
return self;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[window makeKeyAndOrderFront:self];
}
#end
GLView.h/m
#import <Cocoa/Cocoa.h>
#interface GLView : NSView
#end
#import "GLView.h"
#implementation GLView
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
// Drawing code here.
}
- (BOOL)canBecomeKeyView
{
return YES;
}
- (BOOL)acceptsFirstResponder
{
return YES;
}
- (BOOL)becomeFirstResponder
{
return YES;
}
- (BOOL)resignFirstResponder
{
return YES;
}
- (void)keyDown:(NSEvent *)theEvent
{
NSString* const character = [theEvent charactersIgnoringModifiers];
unichar const code = [character characterAtIndex:0];
NSLog(#"Key Down: %hu", code);
switch (code)
{
case 27:
{
EXIT_SUCCESS;
break;
}
}
}
- (void)keyUp:(NSEvent *)theEvent
{
}
#end
Nothing I have tried for it has worked. I thought that by setting the view as the first responder I would be able to get the events. So far... Not working. Any ideas on how I can fix this? Remember, NO NIB.
Thanks,
Tyler
First, you need to make sure that your window can actually become key, by subclassing and returning YES from canBecomeKeyWindow, because windows without title bars cannot become key by default.
Next, your build target needs to be an application. I would guess that you're starting from the Command-Line Tool template in Xcode. This is fine, but you need to produce an application bundle in order for your app to recieve key events. Create a new target in your project that will build a Cocoa Application. It needs to have an Info.plist file (from which you'll want to delete the "Main nib file base class" entry) and have a "Copy Bundle Resources" Build Phase.
I can't quite figure out what all the other differences are in the build process, but starting from your code, I got the window to accept key events with these two steps.

NSTextField doesn't respond to keyboard input

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.

In a CLI Cocoa application, how does one implement a event loop?

I have a Delegate class that handles responses from CLLocationManager and prints them via printf(). Is there some type of busy loop I can put in main() so that the program stays open and keeps CLLocationManager connected to Delegate happily processing events?
#import <Foundation/Foundation.h>
#import "Delegate.h"
#import <CoreLocation/CoreLocation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Delegate *del = [Delegate alloc];
CLLocationManager *locationManager;
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = del;
[locationManager startUpdatingLocation];
// Something goes here
[pool drain];
return 0;
}
This is what NSRunLoop is for, and CLLocationManager is explicitly documented as requiring one (search for “run loop” on that page), so that's what you need to do: Run the run loop.