4

FinderSync 拡張機能を作成するために、Xcode で提供されているテンプレートをテストしました。次の 2 つの点を除いて、すべてが正常に機能します。

a) バッジが設定されないようにフォルダが監視されている場合、メソッド requestBadgeIdentifierForURL がシステムによって呼び出されることはありません。ここで何がうまくいかないのですか?たとえば、Finder で監視対象のフォルダーを移動またはスクロールするときに、このメソッドを呼び出す必要があると思いますか? ちなみに、beginObservingDirectoryAtURL および endObservingDirectoryAtURL メソッドは、このコンテキストで適切に呼び出されます。

#import "FinderSync.h"

@interface FinderSync ()

@property NSURL *myFolderURL;

@end

@implementation FinderSync

- (instancetype)init {
    self = [super init];

    NSLog(@"%s launched from %@ ; compiled at %s", __PRETTY_FUNCTION__, [[NSBundle mainBundle] bundlePath], __TIME__);

    // Set up the directory we are syncing.
    self.myFolderURL = [NSURL fileURLWithPath:@"/Users/hmaass/Downloads"];
    [FIFinderSyncController defaultController].directoryURLs = [NSSet setWithObject:self.myFolderURL];

    // Set up images for our badge identifiers. For demonstration purposes, this uses off-the-shelf images.
    [[FIFinderSyncController defaultController] setBadgeImage:[NSImage imageNamed: NSImageNameColorPanel] label:@"Status One" forBadgeIdentifier:@"One"];
    [[FIFinderSyncController defaultController] setBadgeImage:[NSImage imageNamed: NSImageNameCaution] label:@"Status Two" forBadgeIdentifier:@"Two"];

    return self;
}

#pragma mark - Primary Finder Sync protocol methods

- (void)beginObservingDirectoryAtURL:(NSURL *)url {
    // The user is now seeing the container's contents.
    // If they see it in more than one view at a time, we're only told once.
    NSLog(@"beginObservingDirectoryAtURL:%@", url.filePathURL);
}


- (void)endObservingDirectoryAtURL:(NSURL *)url {
    // The user is no longer seeing the container's contents.
    NSLog(@"endObservingDirectoryAtURL:%@", url.filePathURL);
}

- (void)requestBadgeIdentifierForURL:(NSURL *)url {
    NSLog(@"requestBadgeIdentifierForURL:%@", url.filePathURL);

    // For demonstration purposes, this picks one of our two badges, or no badge at all, based on the filename.
    NSInteger whichBadge = [url.filePathURL hash] % 3;
    NSString* badgeIdentifier = @[@"", @"One", @"Two"][whichBadge];
    [[FIFinderSyncController defaultController] setBadgeIdentifier:badgeIdentifier forURL:url];
}

#pragma mark - Menu and toolbar item support

- (NSString *)toolbarItemName {
    return @"testfifi";
}

- (NSString *)toolbarItemToolTip {
    return @"testfifi: Click the toolbar item for a menu.";
}

- (NSImage *)toolbarItemImage {
    return [NSImage imageNamed:NSImageNameCaution];
}

- (NSMenu *)menuForMenuKind:(FIMenuKind)whichMenu {
    // Produce a menu for the extension.
    NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
    [menu addItemWithTitle:@"Example Menu Item" action:@selector(sampleAction:) keyEquivalent:@""];

    return menu;
}

- (IBAction)sampleAction:(id)sender {
    NSURL* target = [[FIFinderSyncController defaultController] targetedURL];
    NSArray* items = [[FIFinderSyncController defaultController] selectedItemURLs];

    NSLog(@"sampleAction: menu item: %@, target = %@, items = ", [sender title], [target filePathURL]);
    [items enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
        NSLog(@"    %@", [obj filePathURL]);
    }];
}

@end

b) 上記のテンプレートを実行すると、Xcode のログ コンソールに次のメッセージが表示されます。

2015-08-25 15:33:00.300 testfifi[855:8134] (NSApplication) から (NSColorPickerGridView) への (colorGridView) アウトレットの接続に失敗しました: セッターまたはインスタンス変数がありません 2015-08-25 15:33:00.300 testfifi[855 :8134] (NSApplication) から (NSColorPickerGridView) へのアウトレットの接続 (表示) に失敗しました: セッターまたはインスタンス変数がありません 2015-08-25 15:33:00.321 testfifi[855:8134] -[FinderSync init] は /Users/ hmaass/Library/Developer/Xcode/DerivedData/testtest-egudnxkifjxirpbrjkohnatmjuro/Build/Products/Debug/testtest.app/Contents/PlugIns/testfifi.appex ; 20:38:18にコンパイル

誰かがこのメッセージを取り除くのを手伝ってくれますか?

ありがとう!

4

3 に答える 3

8

私はすでにあなたの質問にコメントしましたが、より完全な回答を投稿する必要があると考えました.

あなたが抱えている問題は、別の Finder Sync 拡張機能がすべてのフォルダーを「貪欲に」監視していることのようです。おそらく Dropbox Finder Integration です。他のすべての Finder Sync 拡張機能を無効にして (システム環境設定 -> 拡張機能 -> Finder で)、テストを再実行してください。

これで問題が解決した場合、問題は、監視しようとしているフォルダーに対して Dropbox (または別のアプリ) が beginObservingDirectoryAtURL を既に呼び出していることです。残念ながら、Apple の API には、競合する拡張機能がある場合に誰がフォルダを監視できるかについてのインテリジェントなロジックがないという点で欠けています。現在、最初に開始された Finder Sync 拡張機能が「優先」されます。

Dropbox は、ユーザーのホーム ディレクトリにあるすべてのフォルダを貪欲に監視します。私はこの問題に対処するために Apple と Dropbox の両方に手紙を書きましたが、何の反応もありません。現在、私が実装した (醜い) 回避策は、既知の「貪欲な」拡張機能をシャットダウンし、独自の拡張機能を開始してから、貪欲な拡張機能を再起動することです。

于 2015-08-27T18:33:08.403 に答える
1

「貪欲な」Finder Sync 拡張機能を無効にする回避策のサンプル コードを次に示します。派手なことは何もありませんが、うまくいきます。

(これは実際には単なる回避策であり、必ずしも「正しい」答えではないため、別の答えとして追加します)。

public static void main(String[] args) throws Exception {
    String[] greedyFSProcessNames =
        new String[] { "com.getdropbox.dropbox.garcon" };

    List<String> disabledGreedyFSProcessNames = new ArrayList<>();

    for (String greedyFSProcessName : greedyFSProcessNames) {
        if (!_isFSProcessRunning(greedyFSProcessName)) {
            continue;
        }

        _enableFSProcess(greedyFSProcessName, false);

        disabledGreedyFSProcessNames.add(greedyFSProcessName);
    }

    _enableFSProcess("com.dejuknow.myfindersync", true);

    for (String disabledGreedyFSProcessName :
        disabledGreedyFSProcessNames) {

        _enableFSProcess(disabledGreedyFSProcessName, true);
    }
}

private static boolean _isFSProcessRunning(String processName)
    throws Exception {

    BufferedReader bufferedReader = null;

    try {
        Process process = Runtime.getRuntime().exec(
            "pluginkit -m -i" + processName);

        bufferedReader = new BufferedReader(
            new InputStreamReader(process.getInputStream()));

        String line = null;

        while ((line = bufferedReader.readLine()) != null) {
            if (line.startsWith("+")) {
                return true;
            }
            else {
                return false;
            }
        }
    }
    finally {
        if (bufferedReader != null) {
            bufferedReader.close();
        }
    }

    return false;
}

private static void _enableFSProcess(String processName, boolean enable)
    throws Exception {

    String electionArgument = null;

    if (enable) {
        electionArgument = "use";
    }
    else {
        electionArgument = "ignore";
    }

    String[] arguments = new String[] {
        "pluginkit", "-e", electionArgument, "-i", processName
    };

    while (_isFSProcessRunning(processName) != enable) {
        Process process = Runtime.getRuntime().exec(arguments);

        process.waitFor();

        Thread.sleep(100);
    }
}
于 2016-02-01T19:36:56.923 に答える
0

Dropbox が使用しているフォルダは、~/Dropbox、~/Documents、および ~/Desktop です。私も FinderSync アプリを持っており、それらを除くすべてのフォルダーにバッジを表示できます。幸いなことに、コンテキスト メニューは競合していないようで、両方の拡張機能のメニュー項目が表示されます。

于 2015-11-11T04:22:17.467 に答える