2

NSTaskを介してコマンドラインユーティリティを使用してファイルを圧縮しようとしています。

擬似コード:

controller:
  init:
    register_self_as_observer_of_nstask_notifications

  startZip(file):
    file = somefileobject 
    task = "zip" with file path as argument
    task.launch

  notification_listener(notification):
    task = notification.get_object
    file = task.??? 

では、通知がどのファイルオブジェクトに関連しているかをどのように見つけることができますか?私は通常、そのようなことのためにuserInfoディクショナリを使用しますが、NSTaskにはそのようなオプションがありません。Apple Devから:この通知にはuserInfoディクショナリが含まれていません。

ありがとう!

4

2 に答える 2

2

関連するオブジェクトAPIを使用して、ユーザー情報ディクショナリをタスクインスタンスにアタッチします。これは最もクリーンなアプローチですが、Mac OSX10.6に関連付けられたオブジェクトAPIが導入される前は使用できません。

または、タスクからユーザー情報にマップする辞書を使用することもできます。タスクからユーザー情報への辞書マッピングの作成は、思ったほど簡単ではありません。

  • [taskInfoDict setObject:userInfo forKey:task]に準拠していないという理由だけでNSTask準拠することはできませんNSCopyingが、NSDictionaryそのキーのコピーに依存しています。
  • NSNumberタスクオブジェクトのプロキシとしてラップされたプロセス識別子を使用すると、ほとんどの場合機能します。ただし、プロセスIDは再利用でき、タスクは起動されるまでPIDを取得しません。問題の根本は次のとおりです。プロセスIDを制御していません。基盤となるOSはそうします。

タスクオブジェクトのアドレスを使用するのが最善の解決策のようです。

[taskInfoDict setObject:userInfo forKey:[NSValue valueWithPointer:task]]

参照カウント環境を想定すると、タスクオブジェクトのアドレスはその存続期間中安定しており、その存続期間は完全にアプリケーションの制御下にあります。このソリューションでは、ガベージコレクターをコピーするとレンチがスローされますが、その場合は、ポインターを直接処理できるコレクションクラスを使用できます(NSMapTable)。

于 2011-06-09T21:25:42.180 に答える
1

連想参照を使用して、ファイルのURL/パスを各タスクインスタンスに関連付けることを検討してください。すべてのオブジェクトには複数の関連付けられたオブジェクトを含めることができ、関連付けられた各オブジェクトには、必要に応じて関連付けられたオブジェクトを参照するために使用される対応するキーがあります。

コントローラでstatic、ファイルのURL/パスキーを表す変数を作成します。

static char fileURLKey;

インスタンスを作成するときNSTaskに、対応するファイルのURLをそのインスタンスに関連付けます。

NSURL *fileURL = …;
NSTask *task = …;
objc_setAssociatedObject(task, &fileURLKey, fileURL, OBJC_ASSOCIATION_RETAIN);

タスクの実行が終了したら、通知オブジェクトからタスクを取得してから、タスクからファイルのURLを取得します。

NSTask *task = [notification object];
NSURL *fileURL = (NSURL *)objc_getAssociatedObject(task, &fileURLKey);
于 2011-06-09T22:00:47.847 に答える