Is it possible to initialize a NSRunLoop without loading any NIB files (i.e., without calling NSApplicationMain())?
Thanks.
The solution is to invoke NSApplication manually. Create your app delegate first than replace the NSApplicationMain() call in main.m with the following:
AppDelegate * delegate = [[AppDelegate alloc] init];
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSApplication * application = [NSApplication sharedApplication];
[application setDelegate:delegate];
[NSApp run];
[pool drain];
[delegate release];
The delegate will be invoked when ready, without needing a nib
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
In Swift, you can achieve this by appending the following line to the end of your main.swift:
NSRunLoop.currentRunLoop().run(); // Swift < 3.0
RunLoop.current.run(); // Swift >= 3.0
If you want to be able to stop the run loop you have to use the Core Foundation methods.
CFRunLoopRun(); // start
And you can stop it like this
CFRunLoopStop(CFRunLoopGetCurrent()); // stop
Yes; you can write your own main method and run NSRunLoop without returning from NSApplicationMain.
Have a look at this link; this guy is using NSRunLoop in his main method, he is not loading NIB files though, but it should get you going with NSRunloops.
// Yes. Here is sample code (tested on OS X 10.8.4, command-line).
// Using ARC:
// $ cc -o timer timer.m -fobjc-arc -framework Foundation
// $ ./timer
//
#include <Foundation/Foundation.h>
@interface MyClass : NSObject
@property NSTimer *timer;
-(id)init;
-(void)onTick:(NSTimer *)aTimer;
@end
@implementation MyClass
-(id)init {
id newInstance = [super init];
if (newInstance) {
NSLog(@"Creating timer...");
_timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(onTick:)
userInfo:nil
repeats:YES];
}
return newInstance;
}
-(void)onTick:(NSTimer *)aTimer {
NSLog(@"Tick");
}
@end
int main() {
@autoreleasepool {
MyClass *obj = [[MyClass alloc] init];
[[NSRunLoop currentRunLoop] run];
}
return 0;
}
Have a look at asynctask.m that runs an NSRunLoop manually to enable the use of asynchronous "waitForDataInBackgroundAndNotify" notifications.
http://www.cocoadev.com/index.pl?NSPipe
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
while(!terminated)
{
//if (![[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:100000]])
if (![[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]])
{
break;
}
[pool release];
pool = [[NSAutoreleasePool alloc] init];
}
[pool release];
Here is my take using only DispatchQueue. Most command line tools want to exit with a status. The background dispatch queue is concurrent.
import Foundation
var exitStatus: Int32 = 0
let background = DispatchQueue(label: "commandline", qos: .userInteractive, attributes: [], autoreleaseFrequency: .workItem)
background.async {
var ii = 1
while ii < CommandLine.arguments.count {
process(file:CommandLine.arguments[ii])
ii += 1
}
}
background.async {
exit(exitStatus)
}
RunLoop.current.run()
NSURLConnectioninmain. Without any special handling, he could exitmainbefore the program really completes due to delegates being invoked. - jww