3
\$\begingroup\$

I'm trying to get the URL of the browser with Mac OS X app. I wrote some AppleScript and am trying to use it in Cocoa. The problem is, when I watch it with instruments, memory is increasing, and at the end of 3-4 hours it's nearly 20MB.

#import "AppDelegate.h"
#import <Carbon/Carbon.h>
@interface AppDelegate ()
@property (weak) IBOutlet NSWindow *window;
@end
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
 [NSTimer scheduledTimerWithTimeInterval:1
 target:self
 selector:@selector(collect)
 userInfo:nil
 repeats:YES];
}
- (void)collect{
 [self runWithEvent];
}
- (void)runWithEvent{
 NSURL *URL = [[NSBundle mainBundle] URLForResource:@"frontmostapptitle" withExtension:@"scpt"];
 if (URL) {
 NSAppleScript *appleScript = [[NSAppleScript alloc] initWithContentsOfURL:URL error:NULL];
 NSAppleEventDescriptor *returnDescriptor = [self lookUpRunningApp];
 NSDictionary *error = nil;
 NSAppleEventDescriptor *resultEventDescriptor = [appleScript executeAppleEvent:returnDescriptor error:&error];
 if (! resultEventDescriptor) {
 NSLog(@"%s AppleScript run error = %@", __PRETTY_FUNCTION__, error);
 }
 else {
 NSLog(@"%@", [self stringForResultEventDescriptor:resultEventDescriptor]);
 }
 }
}
- (NSAppleEventDescriptor *)lookUpRunningApp{
 // target
 ProcessSerialNumber psn = {0, kCurrentProcess};
 NSAppleEventDescriptor *target = [NSAppleEventDescriptor descriptorWithDescriptorType:typeProcessSerialNumber bytes:&psn length:sizeof(ProcessSerialNumber)];
 // function
 NSAppleEventDescriptor *function = [NSAppleEventDescriptor descriptorWithString:@"LookUpRunningApp"];
 // event
 NSAppleEventDescriptor *event = [NSAppleEventDescriptor
 appleEventWithEventClass:kASAppleScriptSuite
 eventID:kASSubroutineEvent
 targetDescriptor:target
 returnID:kAutoGenerateReturnID
 transactionID:kAnyTransactionID];
 [event setParamDescriptor:function forKeyword:keyASSubroutineName];
 return event;
}
- (NSString *)stringForResultEventDescriptor:(NSAppleEventDescriptor *)resultEventDescriptor
{
 NSString *result = nil;
 if (resultEventDescriptor) {
 if ([resultEventDescriptor descriptorType] != kAENullEvent) {
 if ([resultEventDescriptor descriptorType] == kTXNUnicodeTextData) {
 result = [resultEventDescriptor stringValue];
 }
 }
 }
 return result;
}
@end
nhgrif
25.4k3 gold badges64 silver badges129 bronze badges
asked Feb 10, 2015 at 22:03
\$\endgroup\$
3
  • \$\begingroup\$ Did you try commenting out lines that don't affect functionality like NSLogs? As the Applescript doesn't change, could you alloc the appleScript once and reuse it? Also the NSAppleEventDescriptor lookUpRunningApp could probably inited once and be reused. In my experience, AppleEvent generally has memory issues. Finally what is your main goal? Could you use NSRunningApplication and CGWindow API? \$\endgroup\$ Commented Feb 12, 2015 at 16:42
  • \$\begingroup\$ What I found more robust is using [[NSAppleScript alloc] initWithSource:@"tell \n -- do work \n end tell" \$\endgroup\$ Commented Feb 12, 2015 at 16:48
  • \$\begingroup\$ For the actual question on memory usage, that feels more appropriate to ask on Stack Overflow, but I'll add that the Instruments app will actually tell you what is consuming your memory, so I recommend checking out what's being allocated and not being deallocated. \$\endgroup\$ Commented Feb 13, 2015 at 0:46

1 Answer 1

2
\$\begingroup\$
- (NSString *)stringForResultEventDescriptor:(NSAppleEventDescriptor *)resultEventDescriptor
{
 NSString *result = nil;
 if (resultEventDescriptor) {
 if ([resultEventDescriptor descriptorType] != kAENullEvent) {
 if ([resultEventDescriptor descriptorType] == kTXNUnicodeTextData) {
 result = [resultEventDescriptor stringValue];
 }
 }
 }
 return result;
}

This method can be rewritten far more simply:

- (NSString *)stringForResultEventDescriptor:(NSAppleEventDescriptor *)resultEventDescriptor {
 return (resultEventDescriptor.descriptorType == kTXNUnicodeTextData) ? resultEventDescriptor.stringValue : nil;
}

- (void)collect{
 [self runWithEvent];
}

This method seems entirely unnecessary. Why doesn't the timer just call runWithEvent directly?

answered Feb 13, 2015 at 0:56
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.