Расширение FinderSync — requestBadgeIdentifierForURL никогда не вызывается

Я протестировал шаблон, представленный в Xcode, для создания расширения FinderSync. Все работает хорошо, кроме двух вещей:

а) Метод 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

б) Я получаю следующее сообщение в консоли журнала Xcode при запуске шаблона выше:

2015-08-25 15:33:00.300 testfifi[855:8134] Не удалось подключить выход (colorGridView) из (NSApplication) к (NSColorPickerGridView): отсутствует установщик или переменная экземпляра 25-08-2015 15:33:00.300 testfifi[855 :8134] Не удалось подключить (просмотреть) выход из (NSApplication) к (NSColorPickerGridView): отсутствует установщик или переменная экземпляра hmaass/Library/Developer/Xcode/DerivedData/testtest-egudnxkifjxirpbrjkohnatmjuro/Build/Products/Debug/testtest.app/Contents/PlugIns/testfifi.appex; скомпилировано в 20:38:18

Может ли кто-нибудь помочь мне избавиться от этого сообщения?

Спасибо!


person hmaass    schedule 25.08.2015    source источник
comment
Используете ли вы Dropbox или любые другие приложения, использующие расширения Finder Sync? Попробуйте отключить все остальные расширения и повторно запустить тест.   -  person dejuknow    schedule 27.08.2015


Ответы (3)


Я уже прокомментировал ваш вопрос, но решил, что должен опубликовать более полный ответ.

Похоже, проблема, с которой вы столкнулись, заключается в том, что другое расширение Finder Sync «жадно» наблюдает за всеми папками, скорее всего, это интеграция Dropbox Finder. Попробуйте отключить все остальные расширения Finder Sync (в Системных настройках -> Расширения -> Finder) и повторно запустите тест.

Если это решит проблему, проблема в том, что Dropbox (или другое приложение) уже вызвало beginObservingDirectoryAtURL для папки, которую вы пытаетесь отслеживать. К сожалению, в API Apple отсутствует интеллектуальная логика того, кто может отслеживать папку при наличии конфликтующих расширений. В настоящее время «победит» любое из расширений Finder Sync, которое запустится первым.

Dropbox жадно отслеживает все папки в домашнем каталоге пользователя. Я написал в Apple и Dropbox, чтобы решить эту проблему, но не получил никакого ответа. В настоящее время (уродливый) обходной путь, который я применил, заключается в отключении известных «жадных» расширений, запуске моего собственного расширения, а затем перезапуске жадного расширения.

person dejuknow    schedule 27.08.2015
comment
Да, ты прав. Удивительно, что в API отсутствует логика для избежания таких противоречивых проблем. Спасибо за обращение в Apple. Есть ли у вас какие-либо идеи по поводу второй части моего вопроса об ошибке выхода? В тестовом шаблоне Xcode выхода нет! - person hmaass; 29.08.2015
comment
Что касается вашего уродливого обходного пути, возможно, помогает изменение порядка элементов входа в систему в настройках системы? - person hmaass; 29.08.2015
comment
Сообщение «Не удалось подключиться (colorGridView) …» появляется для всех приложений Finder Sync, но это не вызывает никаких проблем. Я просто игнорирую это. - person dejuknow; 30.08.2015
comment
@dejuknow, не могли бы вы предоставить фрагмент кода для обходного пути, пожалуйста? Вы нашли лучшее решение с августа? - person Ivan; 01.02.2016
comment
обратите внимание, что я столкнулся с той же проблемой и наблюдал те же проблемы. Расширения синхронизации Apple Finder не работают с несколькими клиентами. и Dropbox жадно наблюдает за всей пользовательской директорией, хотя, очевидно, он должен наблюдать только за папкой Dropbox. Я подавал отчеты об ошибках в Apple (rdar://21022250) еще в 10.10 и пытался связаться с Dropbox, но безрезультатно. Спустя 3 года та же проблема. - person user1259710; 24.10.2017

Вот пример кода обходного пути для отключения «жадных» расширений 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);
    }
}
person dejuknow    schedule 01.02.2016
comment
Спасибо! Это похоже на java, который не является обычным языком для разработки расширений OS X. - person Tom Andersen; 05.02.2016
comment
ах, верно. Я явно слишком долго программировал на Java. - person dejuknow; 08.02.2016
comment
хорошо, это сводится к какому-то выполнению: pluginkit -e ignore -i com.getdropbox.dropbox.garcon;pluginkit -e use -i YOUREXTENSIOJNLABEL;pluginkit -e use -i com.getdropbox.dropbox.garcon спасибо, что поделились тем, что это можно использовать в качестве обходного пути! - person user1259710; 31.10.2017

Папки, которые, как я знаю, использует Dropbox: ~/Dropbox, ~/Documents и ~/Desktop. У меня тоже есть приложение FinderSync, и я могу отображать значки во всех своих папках, кроме этих. К счастью, контекстное меню не конфликтует, отображаются оба пункта меню расширения.

person Carlos César Neves Enumo    schedule 11.11.2015