Objective c FinderSync扩展-从不调用requestBadgeIdentifierForURL
我已经测试了Xcode中提供的用于制作FinderSync扩展的模板。除了两件事外,一切都很顺利: a) 当监控文件夹时,系统不会调用requestBadgeIdentifierForURL方法,因此不会设置徽章。这里出了什么问题?我正确地假设在Finder中移动或滚动受监视的文件夹时应该调用此方法?顺便说一下,BeginObservingDirectoryStatul和EndObservingDirectoryStatul方法在此上下文中被正确调用Objective c FinderSync扩展-从不调用requestBadgeIdentifierForURL,objective-c,xcode,osx-yosemite,findersync,osx-extensions,Objective C,Xcode,Osx Yosemite,Findersync,Osx Extensions,我已经测试了Xcode中提供的用于制作FinderSync扩展的模板。除了两件事外,一切都很顺利: a) 当监控文件夹时,系统不会调用requestBadgeIdentifierForURL方法,因此不会设置徽章。这里出了什么问题?我正确地假设在Finder中移动或滚动受监视的文件夹时应该调用此方法?顺便说一下,BeginObservingDirectoryStatul和EndObservingDirectoryStatul方法在此上下文中被正确调用 #import "FinderSync.h"
#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测试FIFI[855:8134]无法连接
(colorGridView)从(非应用程序)到
(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/testtesttest egudnxkifjxirpbrjkohnatmjuro/Build/Products/Debug/testtesttest.app/Contents/PlugIns/testfifi.appex启动
; 20:38:18编译
有人能帮我把这条消息处理掉吗
谢谢 我已经对你的问题发表了评论,但我想我应该发布一个更完整的答案 听起来您遇到的问题是另一个Finder Sync扩展正在“贪婪地”观察所有文件夹,很可能是Dropbox Finder集成。尝试禁用所有其他查找同步扩展(在系统首选项->扩展->查找下),然后重新运行测试 如果这解决了问题,那么问题是Dropbox(或其他应用程序)已经为您尝试监视的文件夹调用了BeginObservingDirectoryAttribute。不幸的是,苹果的API缺乏一个智能逻辑,当存在冲突的扩展时,谁来监控文件夹。目前,无论哪个Finder Sync扩展先启动,都将“获胜”
Dropbox贪婪地监视用户主目录下的所有文件夹。我已经写信给苹果和Dropbox来解决这个问题,但没有收到任何回应。目前,我实施的(丑陋的)解决方法是关闭已知的“贪婪”扩展,启动我自己的扩展,然后重新启动贪婪扩展。我知道Dropbox使用的文件夹:~/Dropbox、~/Documents和~/Desktop。
我也有一个FinderSync应用程序,我可以在我所有的文件夹上显示徽章,除了那些。幸运的是,上下文菜单似乎没有任何冲突,两个扩展的菜单项都显示出来。以下是禁用“贪婪”查找同步扩展的解决方案示例代码。没什么特别的,但很管用 (将此作为单独的答案添加,因为它实际上只是一种变通方法,不一定是“正确”的答案)
publicstaticvoidmain(字符串[]args)引发异常{
字符串[]greedyFSProcessNames=
新字符串[]{“com.getdropbox.dropbox.garcon”};
List disabledGreedyFSProcessNames=new ArrayList();
for(字符串GREDYFSPROCESSNAME:GREDYFSPROCESSNAME){
如果(!\u isFSProcessRunning(greedyFSProcessName)){
继续;
}
_enablefsfprocess(greedyFSProcessName,false);
disabledGreedyFSProcessNames.add(greedyFSProcessName);
}
_enableFSProcess(“com.dejuknow.myfindersync”,true);
对于(字符串disabledGreedyFSProcessName:
disabledGreedyFSProcessNames){
_enablefsfprocess(disabledGreedyFSProcessName,true);
}
}
私有静态布尔值_isFSProcessRunning(字符串processName)
抛出异常{
BufferedReader BufferedReader=null;
试一试{
Process Process=Runtime.getRuntime().exec(
“pluginkit-m-i”+进程名);
bufferedReader=新的bufferedReader(
新的InputStreamReader(process.getInputStream());
字符串行=null;
而((line=bufferedReader.readLine())!=null){
if(带(“+”)的行开始){
返回true;
}
否则{
返回false;
}
}
}
最后{
if(bufferedReader!=null){
bufferedReader.close();
}
}
返回false;
}
私有静态void_enablefsfprocess(字符串processName,布尔启用)
抛出异常{
字符串electionArgument=null;
如果(启用){
electionArgument=“使用”;
}
否则{
electionArgument=“忽略”;
}
字符串[]参数=新字符串[]{
“pluginkit”、“-e”、electionArgument、“-i”、processName
};
while(_isFSProcessRunning(processName)!=启用){
Process Process=Runtime.getRuntime().exec(参数);
process.waitFor();
睡眠(100);
}
}
您是否正在运行Dropbox或任何其他使用Finder Sync扩展的应用程序?尝试禁用所有其他扩展,然后重新运行测试。是的,你是对的。令人惊讶的是,API缺乏避免此类冲突问题的逻辑。谢谢你向苹果公司致辞。你知道我问题的第二部分是关于出口错误的吗?在Xcode的测试模板中没有出口!关于您丑陋的解决方法,更改系统首选项中登录项目的顺序可能会有所帮助?所有Finder Sync应用程序似乎都会显示“连接失败(colorGridView)插座…”消息,但不会导致任何问题。我只是忽略了它。@dejuknow您能为您的解决方案提供代码片段吗?自8月份以来,您是否找到了更好的解决方案?请注意,我遇到了相同的问题,并观察到了相同的问题。苹果的finder sync扩展无法与多个客户端协同工作。Dropbox贪婪地观察整个用户目录,尽管它显然应该只观察Dropbox文件夹。我已经向苹果公司提交了错误报告(rdar://21022
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);
}
}