Расширение FinderSync - requestBadgeIdentifierForURL никогда не вызывается
Я проверил шаблон, предоставленный в XCode для создания Расширения FinderSync. Все работает хорошо, кроме двух вещей:
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
б) я получаю следующее сообщение в консоли журнала XCode при запуске шаблона выше:
2015-08-25 15:33:00.300 testfifi[855:8134] Не удалось подключить выход (colorGridView) из (NSApplication) к (NSColorPickerGridView): отсутствует установщик или переменная экземпляра 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/ Библиотека / Разработчик /Xcode/DerivedData/testtest-egudnxkifjxirpbrjkohnatmjuro/Build/Products/Debug/testtest.app/ Содержание / Подключаемые модули /testfifi.appex; составлено в 20:38:18
Может ли кто-нибудь помочь мне избавиться от этого сообщения?
Спасибо!
3 ответа
Я уже прокомментировал ваш вопрос, но решил опубликовать более полный ответ.
Похоже, проблема в том, что другое расширение Finder Sync "жадно" наблюдает за всеми папками, скорее всего, за интеграцию с Dropbox Finder. Попробуйте отключить все остальные расширения Finder Sync (в Системных настройках -> Расширения -> Finder) и перезапустите тест.
Если это решает проблему, проблема заключается в том, что Dropbox (или другое приложение) уже вызвал beginObservingDirectoryAtURL для папки, которую вы пытаетесь отслеживать. К сожалению, API Apple отсутствует в том смысле, что нет разумной логики для того, кто контролирует папку при наличии конфликтующих расширений. В настоящее время, какое бы расширение Finder Sync ни запустило первым, оно "победит".
Dropbox жадно следит за всеми папками в домашнем каталоге пользователя. Я написал в Apple и Dropbox об этом, но ответа не услышал. В настоящее время (уродливый) обходной путь, который я реализовал, заключается в отключении известных "жадных" расширений, запуске моего собственного расширения, а затем перезапуске жадного расширения.
Вот пример обходного кода для отключения "жадных" расширений 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);
}
}
Папки, которые я знаю, использует Dropbox: ~/Dropbox, ~/Documents и ~/Desktop. У меня тоже есть приложение FinderSync, и я могу отображать значки на всех своих папках, кроме тех. К счастью, контекстное меню, похоже, не страдает никаким конфликтом, отображаются оба пункта меню расширения.