【问题标题】:FinderSync Extension - requestBadgeIdentifierForURL is never calledFinderSync 扩展 - requestBadgeIdentifierForURL 永远不会被调用
【发布时间】:2023-03-22 05:12:01
【问题描述】:

我已经测试了 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

b) 运行上面的模板时,我在 Xcode 的日志控制台中收到以下消息:

2015-08-25 15:33:00.300 testfifi[855:8134] 连接失败 (colorGridView) 出口从 (NSApplication) 到 (NSColorPickerGridView):缺少 setter 或实例变量 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 编译

有人可以帮我摆脱这条消息吗?

谢谢!

【问题讨论】:

  • 您是否在运行 Dropbox 或任何其他使用 Finder Sync 扩展的应用程序?尝试禁用所有其他扩展并重新运行测试。

标签: objective-c xcode osx-yosemite findersync osx-extensions


【解决方案1】:

我已经对你的问题发表了评论,但我认为我应该发布一个更完整的答案。

听起来您遇到的问题是另一个 Finder Sync 扩展“贪婪地”观察所有文件夹,很可能是 Dropbox Finder 集成。尝试禁用所有其他 Finder Sync 扩展(在 System Preferences -> Extensions -> Finder 下)并重新运行测试。

如果这样可以解决问题,则问题在于 Dropbox(或其他应用)已经为您尝试监控的文件夹调用了 beginObservingDirectoryAtURL。不幸的是,Apple 的 API 缺乏智能逻辑,当存在冲突的扩展名时谁可以监视文件夹。目前,无论哪个 Finder Sync 扩展首先启动都会“获胜”。

Dropbox 贪婪地监视用户主目录下的所有文件夹。我已经写信给 Apple 和 Dropbox 来解决这个问题,但没有收到任何回复。目前,我实施的(丑陋的)解决方法是关闭已知的“贪婪”扩展,启动我自己的扩展,然后重新启动贪婪扩展。

【讨论】:

  • 是的,你是对的。令人惊讶的是,API 缺乏避免此类冲突问题的逻辑。感谢您向 Apple 发表讲话。您对我关于插座错误的问题的第二部分有任何想法吗? Xcode的测试模板中没有出线!
  • 关于你丑陋的解决方法也许改变系统偏好中登录项的顺序有帮助?
  • “无法连接 (colorGridView) 插座...”消息似乎出现在所有 Finder Sync 应用程序中,但不会导致任何问题。我只是忽略它。
  • @dejuknow 能否为您的解决方法提供代码 sn-p?自 8 月以来,您是否找到了更好的解决方案?
  • 请注意,我遇到了同样的问题,并且观察到了同样的问题。 Apple 的 finder 同步扩展不适用于多个客户端。 Dropbox 贪婪地观察整个用户目录,尽管它显然应该只观察 Dropbox 文件夹。我已经在 10.10 向 Apple (rdar://21022250) 提交了错误报告,并试图联系 Dropbox,但无济于事。 3 年后,同样的问题仍然存在。
【解决方案2】:

以下是禁用“贪婪”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);
    }
}

【讨论】:

  • 谢谢!虽然这看起来像 java,但它不是 OS X 扩展开发的常用语言。
  • 啊,对。我显然用 Java 编码太久了。
  • 好的,这归结为以某种方式执行:pluginkit -e ignore -i com.getdropbox.dropbox.garcon;pluginkit -e use -i YOUREXTENSIOJNLABEL;pluginkit -e use -i com.getdropbox.dropbox.garcon 感谢分享这可以用作解决方法!
【解决方案3】:

我知道 Dropbox 使用的文件夹:~/Dropbox、~/Documents 和 ~/Desktop。 我也有一个 FinderSync 应用程序,我可以在我的所有文件夹上显示徽章,除了那些。幸运的是上下文菜单似乎没有发生任何冲突,两个扩展的菜单项都显示出来了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-18
    • 2012-10-27
    • 2013-10-12
    • 2012-03-27
    • 2013-08-29
    • 2013-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多