Search code examples
objective-ciosnsnotificationcenternstask

Objective-C: Multiple Views and Data Coming From An NSTask


So, I managed to get NSTask to read asynchronously from a program, but I did it inside the class of a UIView in my storyboard. (Not an Obj-C expert)

My ideia is: I read the text from the program place it on a UITextView and then when there's more repeat the process via NSNotificationCenter

So far this is my code:

LView.m:

- (void)viewDidLoad
{

    [super viewDidLoad];

    NSPipe *out_pipe = [NSPipe pipe];
    sshoutput = [out_pipe fileHandleForReading];
    [sshoutput readInBackgroundAndNotify];

    utilT = [[NSTask alloc] init];
    [utilT setLaunchPath:@"/usr/bin/utilfc9"];
    [utilT setArguments:[NSArray arrayWithObjects: @"-p", @"-f", @"log.txt", nil]];

    [utilT setStandardOutput: out_pipe];
    [utilT setStandardError: out_pipe];
    [utilT launch];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(readPipe:) name:NSFileHandleReadCompletionNotification object:nil];
}

-(void)readPipe: (NSNotification *)notification
{
    NSData *data;
    NSString *new_input;

    if( [notification object] != sshoutput ) { return };

    data = [[notification userInfo] objectForKey:NSFileHandleNotificationDataItem];
    new_input = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];

    self.log.text = [self.wifilog.text stringByAppendingFormat: @"\n%@", new_input];

    if( utilT ) {
        [sshoutput readInBackgroundAndNotify];
    }
}

LView.h:

#import <UIKit/UIKit.h>
#import "NSTask.h"

NSTask *sshT;
NSFileHandle *sshoutput;

So far it works great, I get the data live without any issues.

But, how can I place this NSTask in a more "global" place like AppDelegate's application didFinishLaunchingWithOptions and then process the data and update multiple views in another classes? I tried and of course I can stuff like log.text = new_input inside AppDelegate because it's from another class, and including it does not solve the problem.

As you might noticed, I'm not interested in sending this to the AppStore. It's an app for myself to use on a jailbroken iPhone. Thank you.


Solution

  • Quick way to do it is

    In all of the Views that you want to recieve this same notification add the following

    ReceiverView

    -(void) viewDidLoad
    {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(read:)     name:@"ReadTest" object:nil];
    }
    
    //read function
    -(void) read:(NSNotification*)notification
    { // Do something with the notification }
    

    Now in LView.m

    -(void)readPipe: (NSNotification *)notification
    {
        NSData *data;
        NSString *new_input;
    
        if( [notification object] != sshoutput ) { return };
    
        data = [[notification userInfo] objectForKey:NSFileHandleNotificationDataItem];
        new_input = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
    
        self.log.text = [self.wifilog.text stringByAppendingFormat: @"\n%@", new_input];
    
        if( utilT ) {
            [sshoutput readInBackgroundAndNotify];
        }
        //Add the following
        [[NSNotificationCenter defaultCenter] postNotificationName:@"ReadTest" object:notification]
    }