views:

449

answers:

2

Hi,

I have a shell script logging a list of numbers (1, 2, and so forth, one per line) to a log file. I need my ObjC app to read the log file every X seconds and then update my progress bar accordingly based on the last number logged in the log file.

What's the best way to do this?

A: 

You can create an instance of NSTimer and have it, every X seconds, call another method that's responsible for reading the file and updating your progress bar. That method can use NSString's stringWithContentsOfFile: to read the file into a string, then parse it appropriately.

For example:

// Create the invocation of the method to call
NSUInteger X = 2; // Change depending on how often you want the timer fired
NSMethodSignature *signature = [self methodSignatureForSelector:@selector(read)];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];

// Create the timer, adding it to the default run loop
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:X
                                              invocation:invocation
                                                 repeats:YES];

And later, you define the selector read:

- (void)read {
    NSString *fileContents = [NSString stringWithContentsOfFile:@"aFile.txt"];
    NSArray *lines = [fileContents componentsSeparatedByString:@"\n"];
    NSString *lastLine = [lines lastObject];

    // Your own parsing and updating code here
}

If you need a definite stopping point, you can store timer in an ivar inside your class, then call [timer invalidate]; whenever your parsing code inside read determines you're done with whatever process you're executing.

Relevant docs:

Tim
Thanks for the answer, I'll try that out
macatomy
+4  A: 

Why not use NSFileHandle's readInBackgroundAndNotify instead? This way, your code only runs when something really does happen in the file.

Peter Hosey
I couldn't find a method called readDataInBackgroundAndNotify, but I did find readInBackgroundAndNotify. I tried this code: http://pastie.org/592668 and the selector never gets called for some reason. I know for sure that the file is being updated. Any ideas?
macatomy
First, you're registering for the wrong notification name. You need to observe for `NSFileHandleReadCompletionNotification`, not `@"NSFileHandleReadCompletionNotification"`. Second, try setting the file handle's file descriptor as non-blocking using `fcntl`. See http://developer.apple.com/documentation/Darwin/Reference/ManPages/man2/fcntl.2.html .
Peter Hosey
+1 for finding a method that doesn't need polling - much better than my own answer :)
Tim
I tried Peter's suggestions however the method still doesn't seem to work for me, selector never gets called
macatomy