sending path string to ObjC class as variable

Hi All,

I’ve been wrangling over this for days. My app launches a process, rsync, and monitors output in a log file. I have a file reader class and send the log path to it and it processes

set tailendText to  ApplicationUtilityClass's readStreamAtPath_("/Users/me/Library/Logs/rsynclog.log")

I don’t want to post all the code for the file reader but I call the method via an objC utility class ( it hasn’t worked straight from the ASOC class - not sure why yet.)

-(NSMutableString*)readStreamAtPath:(NSString*)path{
    FileReader* fileReader = [[FileReader alloc] initWithFilePath:path];
    if (!fileReader) {
       NSLog(@"no file reader");
    }
    
    NSMutableString *mut = [NSMutableString stringWithCapacity:20];
    NSString* line = nil;
    int lineCount = 0;
    while ((line = [fileReader readLineBackwards]))
   // gather a few lines from the file reader and return to ASOC and Progress bar
   etc...
    return mut;
}

then in file reader class

- (id)initWithFilePath:(NSString*)filePath {
     NSLog(@"filePath =%@",filePath); // works... can read path but....

	self = [super init];
	if (self != nil) {
		if (!filePath || [filePath length] <= 0) {
			return nil;
		}
		m_fileHandle = [NSFileHandle fileHandleForReadingAtPath] ;
        
		if (m_fileHandle == nil) {
            NSLog(@"filehandel = nil ");
			return nil;
		}
          }
    }

Ok. So this works fine. The trouble begins when I try to pass the path as a variable which is necessary of course

set tailendText to  ApplicationUtilityClass's readStreamAtPath_(outputText)

It shows the path being received ok in file reader but the file handle returns nil and no go. I tried NSString stringWithString_(outputText) with no luck. Am I missing something? Also I tried using a c function for reading (open() and read()) which also worked great but again I couldn’t pass a variable to it for the life of me.

Now if I construct the path inside the file reader class instead of passing it - it works fine.

filePath = [@"~/Library/Logs/rsynclog.log" stringByExpandingTildeInPath];

For the sake of modularity though, one should be able to pass it in from ASOC, or not.

Thanks, Rob

Are you sure that you are actually passing it to the reader? Because I see you’ve got 2 instance methods not class methods, and I think that you are trying to pass and instance your variable but your code is actually calling class methods of your OBJC code. That’s why it works inside of the OBJC code itself (something does get called to run) but it won’t pass back anything. The easier way to pass things to OBJC helpers is to use a class method. IIRC, if you want to make an instance you need to do something more like:

set someReader to current application’s ReaderClass’s alloc()'s initWithFilePath_(someApplescriptVar)
set anOutputText to someReader’s readStreamAtPath_(somePath)

In my blended ASOC/OBJC apps I have almost always used class methods to do stuff like this. The construct of “alloc()'s init()'s etc” is just too bloated and a PITA for doing simple things that can be done in 1 block of OBJC code. My Cocoa methods are simple(r) in these apps that are mostly ASOC with OBJC helpers. I have some apps that are 100% OBJC and some are 90% OBJC but 10% ASOC and I do it differently for those. I’ve not needed to honestly do things where I needed to init an instance of an OBJC item and keep it around much.

It doesn’t seem like your pasted code is so complex that you couldn’t roll the INIT method into the top of the parser method. Then pass your text over to the CLASS method

+(NSMutableString*)readStreamAtPath:(NSString*)path{
//etc etc
return whatever;
}

HTH,
Chris

Thanks Chris,

Yes - that makes a lot of sense. I’m still on the learning curve for ObjC and forget about the class/instance distinctions when relating to the ASOC side. I am going to clean up the ObjC helpers classes. Interested to see how it works.

Best, Rob

Well the thing is I originally had this

 set fRead to current application's FileReader's alloc()'s initWithFilePath_("/Users/astrid/Library/Logs/rsynclog.log")
 set tailendText to fRead's readLineBackwards() as string

Which does work. I am creating an instance through init and setting the ivar and then calling the method in the FileReader class. This is a class I borrowed from Dave DeLong and it seems to work fine in his example when called in ObjC.

Again when I try to pass it the variable of the same path

 set fRead to current application's FileReader's alloc()'s initWithFilePath_(outoutTxt)
 set tailendText to fRead's readLineBackwards() as string

if fails to create the NSFileHandle and returns nil

- (id)initWithFilePath:(NSString*)filePath {
NSLog(@"filePath =%@",filePath); // works... can read path but....

   self = [super init];
   if (self != nil) {
       if (!filePath || [filePath length] <= 0) {
           return nil;
       }
       m_fileHandle = [NSFileHandle fileHandleForReadingAtPath] ;

       if (m_fileHandle == nil) {
NSLog(@"filehandel = nil ");
           return nil;
       }
}
}

The path is appearing fine in the Filereader log statement so i guess I am still bewildered. I have done this many times in other projects creating and instance of a class from ASOC class , passing variables to ivars and calling methods on them.

I have also tried using class methods in ObjC and calling those and the same thing happens - it works with the literal string but not with passing a variable.

Thanks, Rob

My first suggestion is that you triple- and quadruple-check that the path is valid. I say this on the basis of experience…

Shane, as always you are uncanny. I looked back up the chain and indeed I missed where I had made it the quoted form of outputxt. I was so used to putting that variable into the shell that I overlooked the obvious that it was another language! I was also sure I had recast the variable as a normal string but not.Thanks for bringing up such an obvious mistake.

I did learn more about class and instance methods so it wasn’t all for naught.

humbled, Rob