【问题标题】:AppleScript/OSAKit/Cocoa Inter-Application Communication Memory LeakAppleScript/OSAKit/Cocoa 应用间通信内存泄漏
【发布时间】:2021-05-07 07:17:04
【问题描述】:

我有一个支持各种 AppleScript 命令的应用程序,当将 list(数组)对象从脚本传递到应用程序时,我遇到了内存泄漏问题。关于将 AppleScript 支持添加到您的可可应用程序,没有大量 100% 清晰且有用的文档,所以我希望这只是我的一个简单的疏忽/错误,有人可以帮助我找到它。

我的最终目标是让另一个 Cocoa 应用程序通过 OSAKit 编译和运行脚本,但我也使用 macOS 的 Script Editor.app 进行了测试,以传递 list 和我的主要这样做时 Cocoa 应用程序仍然会泄漏:

-- This AppleScript command causes leaks
tell application "MyApp"
    update database with things {"thing1", "thing2", "thing3"}
end tell

在我的另一个 Cocoa 应用程序(不是主要的 Cocoa 应用程序)中,我通过 OSAKit 运行上述程序,但它也在那里泄漏:

 #import <OSAKit/OSAKit.h>

 OSAScript *script= [[OSAScript alloc] initWithSource:[NSString stringWithFormat:@"tell application \"MyApp\"\nupdate database with things %@", listOfThings]];
 NSDictionary * errorDict = nil;
 NSAppleEventDescriptor *returnDescriptor = [script executeAndReturnError: &errorDict];



在接收端,我的主要 Cocoa 应用程序设置了一个 NSScriptCommand 类,并且可以接收和响应 AppleScript 命令,而不会出现任何其他已知问题。这是 list 部分的样子:

MyScriptHandler.h

#import "AppDelegate.h"
#import <Cocoa/Cocoa.h>
#import <Foundation/Foundation.h>

@interface MyScriptHandler : NSScriptCommand

- (NSAppleEventDescriptor *) performDefaultImplementation;

@end    

**MyScriptHandler.m**
#import "MyScriptHandler.h"

@implementation MyScriptHandler

- (NSAppleEventDescriptor *) performDefaultImplementation
{
    NSString* cmdName = [[self commandDescription] commandName];

    if ([cmdName isEqualToString: @"update database"])
    {
        // GET THE LIST AND PASS IT OFF TO APP DELEGATE FOR PROCESSING
        NSMutableArray *things = [[self evaluatedArguments] valueForKey:@"things"];
        [(AppDelegate *)[[NSApplication sharedApplication] delegate] updateDatabaseFromAppleScript:options];
    }
    
    return  [NSAppleEventDescriptor descriptorWithBoolean:YES];
}

不确定这是否有用,但我的主要 Cocoa 应用程序的 AppleScript 字典 (.sdef) 对于命令如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">

<dictionary title="MyApp Terminology">

    <suite name="MyApp Suite" code="MyAp" description="Commands for MyApp">
        
        <command name="update database" code="MyApUpDB" description="Update the database">
            <parameter name="with things" code="optn" type="list of text" optional="yes" description="">
                <cocoa key="things"/>
            </parameter>
            <cocoa class="MyScriptHandler"/>
        </command>
        
    </suite>
    
</dictionary>


提前感谢您的帮助!

【问题讨论】:

  • 看看这个和你的答案,我认为问题出在你的 sdef 中,这里:type="list of text"。这不是正确的 sdef 格式(我很惊讶它完全有效)。正确的格式应该是两个键值对:type="text" list="yes"我猜你发生内存泄漏是因为应用程序期望来自事件管理器的 text 描述符(它只是忽略了'list of ' 部分并看到 'text'),但正在接收 list 描述符。它以某种方式管理转换,但在此过程中造成泄漏。
  • @TedWrigley 非常感谢您的评论。这是非常有用的信息,我会试一试!

标签: objective-c cocoa memory-leaks applescript


【解决方案1】:

我相信我已经通过以下更改解决了内存泄漏问题...

在我的 .sdef 文件中,我将命令的参数类型更改为 type="record" 而不是 type="list of text"。这意味着我必须将一些无用/重复的信息(键名)传递到我的主应用程序中,但这是可以接受的,因为据我所知,它现在没有泄漏并且不会花费任何额外的 CPU。

    <command name="update database" code="MyApUpDB" description="Update the database">
        <parameter name="with things" code="optn" type="record" optional="yes" description="">
            <cocoa key="things"/>
        </parameter>
        <cocoa class="MyScriptHandler"/>
    </command>



然后,我更新了 AppleScript 以传递 record 而不是 list

-- This AppleScript command does NOT cause leaks
tell application "MyApp"
    update database with things {thing1:"thing1", thing2:"thing2", thing3:"thing3"}
end tell

【讨论】:

    猜你喜欢
    • 2010-12-01
    • 2017-06-09
    • 2010-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-12
    • 2014-08-16
    • 2015-02-27
    相关资源
    最近更新 更多