无法将Apple的地址簿中的vCard拖到Mac OS X Lion中的应用程序中

时间:2012-02-02 00:58:22

标签: objective-c macos drag-and-drop addressbook

我正在使用仅限Mac OS X Lion的Objective-C应用。我正在努力接受拖累和放弃从地址簿中删除。看起来在Lion中,地址簿vCard表示不会返回任何数据。不幸的是,我不能在以前的操作系统下测试代码,尽管我找到了示例代码,表明它之前是可行的。

我设置我的表格以接收kUTTypeVCard,就像10.6+的文档建议一样(虽然NSVCardPboardType也有效),我确实收到了drop事件。所以要调试我设置一个循环来从drop:

输出数据类型及其值
- (BOOL)tableView:(NSTableView *)aTableView acceptDrop:(id <NSDraggingInfo>)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)operation
{
    NSPasteboard *pb = [info draggingPasteboard];

    NSArray *types = pb.types;
    for (NSString *type in types)
    {
        NSLog(@" ");
        NSLog(@"%@:", type);
        NSLog(@"    property list = %@", [pb propertyListForType:type]);
        NSLog(@"    data = %@", [pb dataForType:type]);
        NSLog(@"    string = %@", [pb stringForType:type]);
    }
    NSLog(@" ");

    return YES;
}

结果如下:

2012-02-01 19:46:18.907 MyAppName[586:60b]  
2012-02-01 19:46:18.907 MyAppName[586:60b] dyn.ah62d4rv4gu8ycuwftb2gc5xeqzwfg3pqqzv1k4ptr3m1k6xmr3xyc6xwqf6zk8puqy:
2012-02-01 19:46:18.909 MyAppName[586:60b]     property list = (null)
2012-02-01 19:46:18.911 MyAppName[586:60b]     data = (null)
2012-02-01 19:46:18.912 MyAppName[586:60b]     string = (null)
2012-02-01 19:46:18.913 MyAppName[586:60b]  
2012-02-01 19:46:18.913 MyAppName[586:60b] ABExpandedSelectionStringArrayType:
2012-02-01 19:46:18.914 MyAppName[586:60b]     property list = (null)
2012-02-01 19:46:18.914 MyAppName[586:60b]     data = (null)
2012-02-01 19:46:18.915 MyAppName[586:60b]     string = (null)
2012-02-01 19:46:18.915 MyAppName[586:60b]  
2012-02-01 19:46:18.915 MyAppName[586:60b] dyn.ah62d4rv4gu8ycuwxqz0gn25yrf106y5ysmy0634bsm3gc8nytf2gn:
2012-02-01 19:46:18.917 MyAppName[586:60b]     property list = (null)
2012-02-01 19:46:18.918 MyAppName[586:60b]     data = (null)
2012-02-01 19:46:18.918 MyAppName[586:60b]     string = (null)
2012-02-01 19:46:18.918 MyAppName[586:60b]  
2012-02-01 19:46:18.919 MyAppName[586:60b] ABSelectionStringArrayType:
2012-02-01 19:46:18.919 MyAppName[586:60b]     property list = (null)
2012-02-01 19:46:18.921 MyAppName[586:60b]     data = (null)
2012-02-01 19:46:18.922 MyAppName[586:60b]     string = (null)
2012-02-01 19:46:18.922 MyAppName[586:60b]  
2012-02-01 19:46:18.922 MyAppName[586:60b] dyn.ah62d4rv4gu8yc6durvwwa3xmrvw1gkdusm1044pxqyuha2pxsvw0e55bsmwca7d3sbwu:
2012-02-01 19:46:18.922 MyAppName[586:60b]     property list = (
    vcf
)
2012-02-01 19:46:18.923 MyAppName[586:60b]     data = <3c3f786d 6c207665 7273696f 6e3d2231 2e302220 656e636f 64696e67 3d225554 462d3822 3f3e0a3c 21444f43 54595045 20706c69 73742050 55424c49 4320222d 2f2f4170 706c652f 2f445444 20504c49 53542031 2e302f2f 454e2220 22687474 703a2f2f 7777772e 6170706c 652e636f 6d2f4454 44732f50 726f7065 7274794c 6973742d 312e302e 64746422 3e0a3c70 6c697374 20766572 73696f6e 3d22312e 30223e0a 3c617272 61793e0a 093c7374 72696e67 3e766366 3c2f7374 72696e67 3e0a3c2f 61727261 793e0a3c 2f706c69 73743e0a>
2012-02-01 19:46:18.923 MyAppName[586:60b]     string = <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <string>vcf</string>
</array>
</plist>
2012-02-01 19:46:18.923 MyAppName[586:60b]  
2012-02-01 19:46:18.923 MyAppName[586:60b] Apple files promise pasteboard type:
2012-02-01 19:46:18.923 MyAppName[586:60b]     property list = (
    vcf
)
2012-02-01 19:46:18.924 MyAppName[586:60b]     data = <3c3f786d 6c207665 7273696f 6e3d2231 2e302220 656e636f 64696e67 3d225554 462d3822 3f3e0a3c 21444f43 54595045 20706c69 73742050 55424c49 4320222d 2f2f4170 706c652f 2f445444 20504c49 53542031 2e302f2f 454e2220 22687474 703a2f2f 7777772e 6170706c 652e636f 6d2f4454 44732f50 726f7065 7274794c 6973742d 312e302e 64746422 3e0a3c70 6c697374 20766572 73696f6e 3d22312e 30223e0a 3c617272 61793e0a 093c7374 72696e67 3e766366 3c2f7374 72696e67 3e0a3c2f 61727261 793e0a3c 2f706c69 73743e0a>
2012-02-01 19:46:18.924 MyAppName[586:60b]     string = <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <string>vcf</string>
</array>
</plist>
2012-02-01 19:46:18.924 MyAppName[586:60b]  
2012-02-01 19:46:18.925 MyAppName[586:60b] dyn.ah62d4rv4gu8ycuwuqz11a5dfnzeyk64uqm10c6xenv61a3k:
2012-02-01 19:46:18.925 MyAppName[586:60b]     property list = (
    "C9786D5F-157A-4A65-A95E-C61752D2B4E3:ABPerson"
)
2012-02-01 19:46:18.925 MyAppName[586:60b]     data = <3c3f786d 6c207665 7273696f 6e3d2231 2e302220 656e636f 64696e67 3d225554 462d3822 3f3e0a3c 21444f43 54595045 20706c69 73742050 55424c49 4320222d 2f2f4170 706c652f 2f445444 20504c49 53542031 2e302f2f 454e2220 22687474 703a2f2f 7777772e 6170706c 652e636f 6d2f4454 44732f50 726f7065 7274794c 6973742d 312e302e 64746422 3e0a3c70 6c697374 20766572 73696f6e 3d22312e 30223e0a 3c617272 61793e0a 093c7374 72696e67 3e433937 38364435 462d3135 37412d34 4136352d 41393545 2d433631 37353244 32423445 333a4142 50657273 6f6e3c2f 73747269 6e673e0a 3c2f6172 7261793e 0a3c2f70 6c697374 3e0a>
2012-02-01 19:46:18.926 MyAppName[586:60b]     string = <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <string>C9786D5F-157A-4A65-A95E-C61752D2B4E3:ABPerson</string>
</array>
</plist>
2012-02-01 19:46:18.926 MyAppName[586:60b]  
2012-02-01 19:46:18.926 MyAppName[586:60b] ABPeopleUIDsPboardType:
2012-02-01 19:46:18.927 MyAppName[586:60b]     property list = (
    "C9786D5F-157A-4A65-A95E-C61752D2B4E3:ABPerson"
)
2012-02-01 19:46:18.927 MyAppName[586:60b]     data = <3c3f786d 6c207665 7273696f 6e3d2231 2e302220 656e636f 64696e67 3d225554 462d3822 3f3e0a3c 21444f43 54595045 20706c69 73742050 55424c49 4320222d 2f2f4170 706c652f 2f445444 20504c49 53542031 2e302f2f 454e2220 22687474 703a2f2f 7777772e 6170706c 652e636f 6d2f4454 44732f50 726f7065 7274794c 6973742d 312e302e 64746422 3e0a3c70 6c697374 20766572 73696f6e 3d22312e 30223e0a 3c617272 61793e0a 093c7374 72696e67 3e433937 38364435 462d3135 37412d34 4136352d 41393545 2d433631 37353244 32423445 333a4142 50657273 6f6e3c2f 73747269 6e673e0a 3c2f6172 7261793e 0a3c2f70 6c697374 3e0a>
2012-02-01 19:46:18.937 MyAppName[586:60b]     string = <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <string>C9786D5F-157A-4A65-A95E-C61752D2B4E3:ABPerson</string>
</array>
</plist>
2012-02-01 19:46:18.937 MyAppName[586:60b]  
2012-02-01 19:46:18.937 MyAppName[586:60b] public.vcard:
2012-02-01 19:46:18.942 MyAppName[586:60b]     property list = (null)
2012-02-01 19:46:18.944 MyAppName[586:60b]     data = (null)
2012-02-01 19:46:18.945 MyAppName[586:60b]     string = (null)
2012-02-01 19:46:18.945 MyAppName[586:60b]  
2012-02-01 19:46:18.945 MyAppName[586:60b] Apple VCard pasteboard type:
2012-02-01 19:46:18.945 MyAppName[586:60b]     property list = (null)
2012-02-01 19:46:18.946 MyAppName[586:60b]     data = (null)
2012-02-01 19:46:18.946 MyAppName[586:60b]     string = (null)
2012-02-01 19:46:18.948 MyAppName[586:60b]  
2012-02-01 19:46:18.949 MyAppName[586:60b] dyn.ah62d4rv4gu8z82xqqz1gk3penm11swpsqvw1u3px:
2012-02-01 19:46:18.949 MyAppName[586:60b]     property list = (null)
2012-02-01 19:46:18.949 MyAppName[586:60b]     data = <040b7374 7265616d 74797065 6481e803 84014084 8484114e 534d7574 61626c65 496e6465 78536574 0084840a 4e53496e 64657853 65740084 84084e53 4f626a65 63740085 84014901 96817c01 960186>
2012-02-01 19:46:18.949 MyAppName[586:60b]     string = (null)
2012-02-01 19:46:18.949 MyAppName[586:60b]  
2012-02-01 19:46:18.950 MyAppName[586:60b] _blendedRowIndexes:
2012-02-01 19:46:18.950 MyAppName[586:60b]     property list = (null)
2012-02-01 19:46:18.950 MyAppName[586:60b]     data = <040b7374 7265616d 74797065 6481e803 84014084 8484114e 534d7574 61626c65 496e6465 78536574 0084840a 4e53496e 64657853 65740084 84084e53 4f626a65 63740085 84014901 96817c01 960186>
2012-02-01 19:46:18.950 MyAppName[586:60b]     string = (null)
2012-02-01 19:46:18.950 MyAppName[586:60b]  
2012-02-01 19:46:18.950 MyAppName[586:60b] com.apple.pasteboard.promised-file-content-type:
2012-02-01 19:46:18.951 MyAppName[586:60b]     property list = public.vcard
2012-02-01 19:46:18.951 MyAppName[586:60b]     data = <7075626c 69632e76 63617264>
2012-02-01 19:46:18.951 MyAppName[586:60b]     string = public.vcard
2012-02-01 19:46:18.952 MyAppName[586:60b]  
2012-02-01 19:46:18.952 MyAppName[586:60b] com.apple.pasteboard.promised-file-url:
2012-02-01 19:46:18.954 MyAppName[586:60b]     property list = (null)
2012-02-01 19:46:18.954 MyAppName[586:60b]     data = <>
2012-02-01 19:46:18.954 MyAppName[586:60b]     string = 
2012-02-01 19:46:18.955 MyAppName[586:60b]  
2012-02-01 19:46:18.955 MyAppName[586:60b] dyn.ah62d4rv4gu8y6y4usm1044pxqzb085xyqz1hk64uqm10c6xenv61a3k:
2012-02-01 19:46:18.955 MyAppName[586:60b]     property list = (null)
2012-02-01 19:46:18.956 MyAppName[586:60b]     data = <>
2012-02-01 19:46:18.956 MyAppName[586:60b]     string = 
2012-02-01 19:46:18.956 MyAppName[586:60b]  
2012-02-01 19:46:18.956 MyAppName[586:60b] NSPromiseContentsPboardType:
2012-02-01 19:46:18.956 MyAppName[586:60b]     property list = (null)
2012-02-01 19:46:18.957 MyAppName[586:60b]     data = <>
2012-02-01 19:46:18.957 MyAppName[586:60b]     string = 
2012-02-01 19:46:18.957 MyAppName[586:60b] 

大多数类型看起来像私有地址簿数据类型。但是您可以看到vCard表示为空。而且我在想,即使我使用ABPeopleUIDsPboardType,它也会被App Store拒绝,因为它在任何头文件中都不可用。

有关如何处理拖拽的任何建议从Lion下的地址簿中删除?

感谢。

*编辑2/5/12 *

尝试研究承诺的拖延和承诺的内容,但仍然空洞:

- (BOOL)tableView:(NSTableView *)aTableView acceptDrop:(id <NSDraggingInfo>)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)operation
{
    NSPasteboard *pb = [info draggingPasteboard];

    // Supposed to call this before readFileContentsType:toFile: for some reason
    NSArray *types = pb.types;

    NSString *destPath = NSTemporaryDirectory();
    NSURL *destURL = [NSURL fileURLWithPath:destPath isDirectory:YES];
    NSArray *fileNames = [info namesOfPromisedFilesDroppedAtDestination:destURL];
    NSLog(@"fileNames = %@", fileNames);

    NSString *afile = [pb readFileContentsType:nil toFile:@"random_filename"];
    // Tried with (NSString *)kUTTypeVCard as well, same results
    NSLog(@"afile = %@", afile);
    // What do I do with this result?
    NSString *card = [NSString stringWithContentsOfFile:afile];
    NSLog(@"card = %@", card);

    NSFileWrapper *wrapper = [pb readFileWrapper];
    NSLog(@"wrapper = %@", wrapper);

    return YES;
}

结果:

2012-02-05 12:36:58.419 MyAppName[3650:60b] fileNames = (null)
2012-02-05 12:36:58.419 MyAppName[3650:60b] afile = random_filename
2012-02-05 12:36:58.419 MyAppName[3650:60b] card = (null)
2012-02-05 12:36:58.420 MyAppName[3650:60b] wrapper = (null)

3 个答案:

答案 0 :(得分:0)

你是对的,AddressBook将其粘贴板行为从以前的OS版本更改为Lion。以前,vCard数据直接存储在类型为NSVCardPboardType的粘贴板中。但是在Lion中,您可以找到所有信息来阅读掉落的电子名片。

有两种方法可以处理粘贴板。 “直接”方式和“对话”方式。 (我的话,不是Apple的)。直接将所有数据放入粘贴板,接收器找到它们并可以读取它们。有时,当数据很大时,非常耗费时间和空间,因为图像或长文本(带图像的RTFD)通常很常见。因此存在另一种方式,需要发送方和接收方之间的小对话。 发送者(拖动操作)将(几乎)没有数据放入粘贴板,但承诺将数据存储在文件系统中的某个位置。接收器(拖动操作)必须告诉该位置(文件夹)应该在哪里。然后,发件人的答案是新创建的文件的名称,以便接收者可以从该文件中读取数据。所有这些都应该在方法-(BOOL)performDragOperation:(id <NSDraggingInfo>)sender中完成。但是如果通过tableView,outLineView,浏览器等完成删除,则需要实现另一种方法。在文档中搜索acceptDrop:。基本上他们做的都是一样的。

在您的情况下(删除tableView),以下(伪)代码将(我希望如此)完成这项工作:

- (BOOL)tableView:(NSTableView *)aTableView acceptDrop:(id < NSDraggingInfo >)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)operation
{
    NSPasteBoard *pb = [info draggingPasteboard];

    NSArray *types = pb.types;

    if( ([types containsObject: NSVCardPboardType]) && *data_exist for this type* ){
       // read the data directly from here
       . . . . 
       return YES;
    }

    if( [types containsObject:NSFilesPromisePboardType] ){
      // create a place for the promised data
      NSString *destPath = NSTemporaryDirectory();
      NSURL *destURL = [NSURL fileURLWithPath:destPath isDirectory:YES];
      // let the sender know it
      // the sender answers with filenames (without the path)
      NSArray *fileNames = [sender namesOfPromisedFilesDroppedAtDestination:destURL];
      if( fileNames == nil ) return NO;  // Firefox likes to return nothing
      NSString *resultStr = [destPath stringByAppendingPathComponent:[fileNames objectAtIndex:0]];
      // read the vCard data from here
         . . . . . 
      return YES;
    }
    // search for other pbTypes or just return  without success
    return NO;
}

正如您在pasteBoard上的所有类型的日志中所看到的,类型NSFilesPromisePboardType(内部名称是 Apple文件承诺粘贴板类型)具有非空的propertyList,它只是说明了数据类型为vcf(文件后缀)。使用这个pbType是AddressBook的新方法。这是将数据发送到finder的首选方式。

答案 1 :(得分:0)

我不知道你为什么没有成功,但我有一个问题:你是否为NSFilesPromisePboardType注册了tableView?否则它不起作用! 我现在将展示我的一个应用程序的代码片段,该代码片段经过测试且有效:

- (BOOL)  tableView:(NSTableView *)aTableView
         acceptDrop:(id <NSDraggingInfo>)info
                row:(NSInteger)row
      dropOperation:(NSTableViewDropOperation)operation
{
    NSPasteboard *pboard = [info draggingPasteboard];
    NSArray *types = pboard.types;

    if( [types containsObject:NSFilesPromisePboardType] ){
        NSString *destPath = NSTemporaryDirectory();  // or whatever you want
        NSURL *destURL = [NSURL fileURLWithPath:destPath isDirectory:YES];
        NSLog(@"destURL %@", destURL);
        NSArray *fileNames = [info namesOfPromisedFilesDroppedAtDestination:destURL];
        NSLog(@"fileNames %@", fileNames);
        if( fileNames == nil ) return NO;
        NSString *resultPath = [destPath stringByAppendingPathComponent:[fileNames objectAtIndex:0]];
        NSLog(@"resultPath %@", resultPath);
        // read the vCard data from here
        NSString *vCard = [NSString stringWithContentsOfFile:resultPath
                                                    encoding:NSASCIIStringEncoding
                                                       error:NULL];
        NSLog(@"vCard =\n%@", vCard);
        return YES;
    }
    return NO;
}

测试输出是;

destURL file://localhost/var/folders/j2/78r9kp_d08gc52z04w2dwkv80000gn/T/
fileNames (
    "Heinrich Giesen 2.vcf"
)
resultPath /var/folders/j2/78r9kp_d08gc52z04w2dwkv80000gn/T/Heinrich Giesen 2.vcf
vCard =
BEGIN:VCAR
VERSION:3.0

。 。 。等等。以

结尾
END:VCARD

答案 2 :(得分:0)

我也遇到了这个问题。读者摘要。

在10.7上注册NSFilesPromisePboardType和kUTTypeVCard。处理NSFilesPromisePboardType。

10.8+注册kUTTypeVCard并处理kUTTypeVCard