Why is my target not printing to the console? - objective-c

I just started learning targets, and have followed all the instructions to create my first console app which should print "Ouch!" every two seconds, but although it is looping it isn't printing to the console and I can't figure out why. Would someone mind telling me what I am doing wrong?
My .h file has the following:
#import <Foundation/Foundation.h>
#interface Logger : NSObject
- (void)sayOuch:(NSTimer *)t;
#end
My .m file has the following:
#import "Logger.h"
#implementation Logger
- (void)sayOuch:(NSTimer *)t
{
NSLog(#"Ouch!");
}
#end
And finally, my main.m file contains the following:
#import <Foundation/Foundation.h>
#import "Logger.h"
int main (int argc, const char * argv[])
{
#autoreleasepool {
Logger *logger = [[Logger alloc] init];
__unused NSTimer *timer = [NSTimer timerWithTimeInterval:2.0
target:logger
selector:#selector(sayOuch:)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] run];
}
return 0;
}
The thing is, whenever I run the message "Ouch!" is not printing to my console. Thanks for the help in advance.

Change
timerWithTimeInterval
with
scheduledTimerWithTimeInterval
So your code changed to working:
#import <Foundation/Foundation.h>
#import "Logger.h"
int main (int argc, const char * argv[])
{
#autoreleasepool {
Logger *logger = [[Logger alloc] init];
__unused NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0
target:logger
selector:#selector(sayOuch:)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] run];
}
return 0;
}

Related

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).

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

iOS NSObject nil after initialisation in block

I have an NSObject that I create inside a block. As per the code below:
__block NSObject *myObject;
[self myMethod:^{
myObject = [[NSObject alloc] init];
....
}];
if(myObject == nil){
NSLog(#"Why is my object nil?!");
}
In the definition of myMethod I have the following:
backgroundQueue = dispatch_queue_create("backgroundqueue", NULL);
dispatch_async(backgroundQueue,
^{
dispatch_async(dispatch_get_main_queue(),
^{
if(block){
block();//Never called.
}
});
However the block is never called.
The problem here is that you never seem to execute the block in which you instantiate myObject. For illustration, run this little program:
#import <Foundation/Foundation.h>
typedef void(^MyTestBlock)(void);
#interface Foo:NSObject
- (id)initWithBlock:(MyTestBlock)aBlock;
- (void)someMethod;
#end
#implementation Foo {
MyTestBlock _block;
}
- (id)initWithBlock:(MyTestBlock)aBlock {
self = [super init];
if( !self ) { return nil; }
_block = aBlock;
return self;
}
- (void)someMethod {
_block();
}
#end
int main(int argc, char *argv[]) {
#autoreleasepool {
__block NSObject *myObject;
Foo *myFoo = [[Foo alloc] initWithBlock:^{
myObject = [[NSObject alloc] init];
}];
[myFoo someMethod];
NSLog((myObject)?#"Your object was created":#"Why is my object nil?");
}
}
This prints 2012-11-26 05:00:58.519 Untitled 2[23467:707] Your object was created to the console. The point is that blocks don't execute themselves. In the code above, although we set the block as an ivar of the class, we don't execute it until we call someMethod on our Foo.
EDIT:
An edit to your question states that the block is not executed in the context of an asynchronous dispatch block sent to the main queue. If this is a command line application, then you must call dispatch_main() at the end of main. See the man page for dispatch_get_main_queue(). Here is a full working command line application to illustrate this, as well as issues related to race conditions:
#import <Foundation/Foundation.h>
typedef void(^MyTestBlock)(void);
#interface Foo:NSObject
- (id)initWithBlock:(MyTestBlock)aBlock;
- (void)someMethod;
#end
#implementation Foo {
MyTestBlock _block;
}
- (id)initWithBlock:(MyTestBlock)aBlock {
self = [super init];
if( !self ) { return nil; }
_block = aBlock;
return self;
}
- (void)someMethod {
dispatch_queue_t backgroundQueue = dispatch_queue_create("backgroundqueue", NULL);
dispatch_async(backgroundQueue, ^{
dispatch_queue_t innerQueue = dispatch_get_main_queue();
dispatch_async(innerQueue, ^{
if( _block){
NSLog(#"Will call block.");
_block();
}
});
});
}
#end
int main(int argc, char *argv[]) {
#autoreleasepool {
__block NSObject *myObject;
Foo *myFoo = [[Foo alloc] initWithBlock:^{
myObject = [[NSObject alloc] init];
}];
[myFoo someMethod];
// this log statement should show that myObject is nil because it will (probably)
// be executed before your block.
NSLog((myObject)?#"Your object was created":#"Why is my object nil?");
// wait a little bit to resolve race condition (just for illustrative purposes)
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.4f * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
NSLog((myObject)?#"Your object was created":#"Why is my object nil?");
});
}
// this isn't a Cocoa app, so must call dispatch_main() at end of main
dispatch_main();
}
You have forgotten to call your block in your myMethod. Try the code bellow.
typedef void(^MyBlock)();
- (void)myMethod:(MyBlock)aBlock
{
aBlock();
}

NSThread issue how to resolve?

I m writting the following code.
#import <objc/objc.h>
#import <Foundation/Foundation.h>
#interface myT :NSObject
-(void) startT;
-(void) tfun;
#end
#implementation myT
-(void) tfun
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog (#"Inside thread Function .. ");
[pool drain];
}
-(void) startT
{
[NSThread detachNewThreadSelector:#selector(tfun) toTarget:self withObject:nil ];
}
#end
int main ( int argc, char ** argv)
{
myT *t = [[myT alloc] init];
[t startT];
return 0;
}
it compiles, and leads to run time error. what i am doing wrong ? i am familiar with pthread. how can i wait till the thread completes, ie: pthread_wait kind.
You can spin the run loop until you set a complete flag like:
-(void) startT
{
[NSThread detachNewThreadSelector:#selector(tfun) toTarget:self withObject:nil ];
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} while (!self.completed);
}
And in your tfun method
-(void) tfun
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog (#"Inside thread Function .. ");
[pool drain];
self.complete = YES;
}

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.