在两个或多个iPhone应用程序之间共享数据


79

是否可以在同一设备上的两个应用程序之间共享数据?

还是可以允许某些其他应用程序使用我的应用程序的信息/数据或以其他任何方式使用?

例如,第一个应用程序用于事件管理,而我使用它来保存一些事件。第二个应用程序用于提醒,它将从另一个应用程序获取数据以提醒我有关事件的信息。

这只是一个简单的示例,而不是真实的场景。

Answers:


38

从历史上看,iPhone一直试图阻止应用之间的数据共享。这个想法是,如果您无法获得另一个应用程序的数据,那么您就无法对该应用程序做任何坏事。

在最新版本的IOS中,他们对此有所放松。例如,iOS编程指南现在有一节介绍如何在应用程序之间传递数据,方法是让一个应用程序声明某个URL前缀,然后让其他应用程序引用该URL。因此,也许您将事件应用设置为回答“ event://” URL,就像网络服务器回答“ http://” URL一样。

苹果公司有关这种方法的文档在这里

窥见“实施自定义URL方案”。


谢谢,这正是我要寻找的。
Kamleshwar

可以以这种方式共享大数据,例如文件吗?
2013年

2
如果您正在阅读本文,请确保在下面检查@siejkowski响应,因为它是最新的。
mahboudz 2015年

1
来自@ chintan-maddy-ramani的回复也值得注意。
mahboudz 2015年

2
是的,自从我撰写此回复以来,添加了许多更好的方法。老问题有老答案!
baudot 2015年

102

在iOS开发的沙盒世界中,在应用程序之间共享数据非常困难,因为iOS开发人员无法直接通过文件系统共享数据,因此他们需要为其应用程序找到替代解决方案。一些常见的解决方案包括:

  • UIDocumentInteractionController

  • UIActivityViewController

  • 共享钥匙串访问

  • 自定义网址方案

  • 网络服务

  • iCloud API


UIDocumentInteractionController:

允许用户在注册为能够处理特定文档的任何其他应用程序中打开文档统一类型标识符(UTI)

过去,UIDocumentInteractionController曾被用作在设备上其他应用程序中打开文档的方式,例如,从Mail应用程序打开电子邮件附件。

UIDocumentInteractionController

不幸的是,UIDocumentInteractionController的UI仅显示六个应用程序

您不能保证您的应用程序将出现在列表中。虽然尚未弃用UIDocumentInteractionController,但从iOS 6.0开始, UIActivityViewController提供了更灵活的替代方法。

可用性: iOS 3.2+

优点:

  • 允许与各种应用程序共享通用数据类型。

缺点:

  • 允许控制发送到UIDocumentInteractionController的数据类型,但不能控制目的地。

  • 需要其他用户交互。

  • 数量有限的数据目标可能会导致您的应用程序无法显示在列表中。


UIActivityViewController:

允许用户对数据数组执行许多操作。

例如,他们可以打印,通过电子邮件发送,复制,发布到社交媒体或在其他应用程序中打开。

您可以创建自己的UIActivity子类,以向用户提供自定义服务。

UIActivityController

可用性: iOS 6.0+

优点:

  • 非常适合与各种应用程序和社交媒体共享常见数据类型。

  • 可以提供一系列项目以应用于活动。对象应符合UIActivityItemSource协议。

  • 能够设置排除的活动类型。

  • 分页UI比UIDocumentInteractionController允许更多的数据目标。

缺点:

  • 您必须定义一个自定义活动类型以限制常见数据类型的“打开位置”目标。

  • 需要其他用户交互。


共享钥匙串访问:

允许您将数据安全地存储到共享钥匙串中,作为一组应用程序一部分的其他应用程序可以访问该共享钥匙串。

共享钥匙串访问的所有应用程序必须使用相同的应用程序ID前缀。

有关操作中共享钥匙串访问的示例。请参阅Apple的GenericKeychain示例代码

共享钥匙链

可用性: iOS 3.0+

优点:

  • 安全访问数据。

缺点:

  • 您只能在共享通用应用程序ID前缀的应用程序之间共享数据。

  • iOS模拟器上的钥匙串API来自OS X,其API与iOS设备的API不同。


自定义网址方案:

允许数据使用简单的URL在应用程序之间传递。

自定义网址方案

可用性: iOS 3.0+

优点:

  • 无需网络连接。
  • 非常适合少量数据,您可以轻松将其编码为转义的合法URL。

缺点:

  • 您必须将数据编码为转义的合法URL。

    注意: base64编码已普遍使用,它将可序列化的数据转换为字符串值。但是,base64字符串可能包含在URL中使用无效的字符。您可以考虑使用base64url。有关更多信息,请参见使用URL和文件名安全字母进行Base 64编码


iCloud API:

每个人都知道什么是iCloud,优点和缺点,因此不再赘述。

但是有人可能会问,如何在单个设备内的应用程序之间共享数据,有一些解决方法可以实现。

iCloud的

这可能是因为用于iCloud的标识符不同于捆绑包标识符,因此可以共享图像,视频和其他文档。

要了解更多信息,请参阅有关此主题的讨论


网络服务:

通过第三方(例如Dropbox)或定制的Web服务同步数据。

网络服务

可用性: iOS 2.0+

优点:

  • 对于共享和分发大量数据很有用。

缺点:

  • 需要网络连接。
  • Web服务实现开销。

参考


3
例如广泛的答案和图形的使用
coolharsh55 2013年

1
您还应该提及UIPasteboardAPI。
Evgeny Karkan

@EvgenyKarkan-请随时编辑该帖子:)
Durai Amuthan.H

54

iOS 8,我已经成功使用“应用程序组功能”访问了Same文件夹我正在扩展@siejkowski的答案。

注意:仅适用于同一开发者帐户。

为此,您必须遵循以下步骤。

  1. 首先从您的开发人员帐户启用“应用程序组”。
  2. 生成配置文件。并使用它。

现在,您必须创建两个应用程序。样品名称

  1. Demo_Share_One
  2. Demo_Share_Two

现在,我们将图像从Demo_Share_One复制到共享文件夹,该文件夹在启用应用程序组并运行应用程序时默认创建。并将从Demo_Share_Two访问所有这些图像。

您必须使用已设置为开发人员帐户的组名group.filesharingdemo

在两个应用程序中添加以下方法以获取共享文件夹URL的相对路径。

- (NSString *) getSharedLocationPath:(NSString *)appGroupName {
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSURL *groupContainerURL = [fileManager containerURLForSecurityApplicationGroupIdentifier:appGroupName];
    return [groupContainerURL relativePath];
}

现在我们从Demo_Share_One复制捆绑中的图像

-(IBAction)writeImage:(id)sender
{
    for (int i = 0; i<15; i++) 
    {
        NSString *strSourcePath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"hd%d",i+1] ofType:@"jpg"];
        NSString *strDestinationPath = [[self getSharedLocationPath:@"group.filesharingdemo"] stringByAppendingPathComponent:[NSString stringWithFormat:@"hd%d",i+1]] ;

        BOOL filewrite = [[NSFileManager defaultManager]copyItemAtPath:strSourcePath toPath:strDestinationPath error:nil];
        if (filewrite)
            NSLog(@"File write");
        else
            NSLog(@"can not write file");
    }
}

现在在Demo_Share_Two中以访问这些图像

NSString *pathShared = [[self getSharedLocationPath:@"group.filesharingdemo"] stringByAppendingPathComponent:[NSString stringWithFormat:@"hd%d.jpg",number]];
NSLog(@"%@",pathShared);
//BOOL fileExist = [[NSFileManager defaultManager] fileExistsAtPath:pathShared];
imgView.image = [UIImage imageWithContentsOfFile:pathShared];

现在,您将从Demo_Share_One获取所有写入的图像。

因此,从现在开始,如果要将此文件夹共享给您的第三个应用程序。只需将该应用添加到您的组中即可。因此,访问“多个”应用程序中的相同元素太容易了。

如果您不会在您的AppID中启用应用程序组,那么您将获得[self getSharedLocationPath:@“ group.filesharingdemo”]为空。

感谢Apple提供的来自您自己的应用程序功能的Share Elements。编码愉快。:)


s / getSharedLocationPath:/ sharedLocationPathForAppGroup:/ :-)
IvanVučica2015年

1
@ChintaN -Maddy- Ramani共享位置路径可以包含sqlLite或领域数据库吗?为此需要扩展吗?
user2363025 '16

@ user2363025也许是。你可以试试。我只是尝试了图像。也许您可以在那里复制数据库。
ChintaN -Maddy- Ramani's

@ ChintaN-Maddy-Ramani。我收到以下错误消息:Domain = NSCocoaErrorDomain代码= 512“文件“ 1FAA9B86-E775-4A2D-A2D6-A442C8A9A8FA”无法保存在文件夹“ AppGroup”中。” UserInfo = {NSFilePath = / private / var / mobile / Containers / Shared / AppGroup / 1FAA9B86-E775-4A2D-A2D6-A442C8A9A8FA,NSUnderlyingError = 0x282202250 {Error Domain = NSPOSIXErrorDomain Code = 21“ Is a directory”}}
Anand Prakash


18

从iOS 8开始,您可以轻松地在应用程序之间共享数据,只要它们在公共应用程序组中即可。

Apple文档在Extensions上下文中对此做了最好的解释:https : //developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html

基本上,您需要:

  1. 为您的Apple Developer Program定义应用程序组ID(在“会员中心”的“证书,标识符和配置文件”部分中)。
  2. 启用应用组功能,为需要通信的每个应用指定上述应用组ID(可以通过Xcode:Target-> Capabilities或在Member Center中完成)。
  3. 使用两个API之一来共享容器访问。

第一个API基于NSUserDefaults

NSString *appGroupId = @"group.my.group.id";

NSUserDefaults *myDefaults = [[NSUserDefaults alloc] 
                    initWithSuiteName:appGroupId];

[myDefaults setObject:@"foo" forKey:@"bar"];

第二个API基于NSFileManager。它只是一个共享文件夹,您可以在获取其URL后对其进行访问:

NSString *appGroupId = @"group.my.group.id";

NSURL *sharedFolderURL = [[NSFileManager defaultManager] 
                           containerURLForSecurityApplicationGroupIdentifier:appGroupId];

您放入的所有内容myDefaults或指向的文件夹sharedFolderURL都将对所有应用程序可见且可访问。

如果是文件夹,请自动写/读,以确保没有死锁。


我经历了您的步骤并获得了共享的URL。但是如何将Image放在那条路径上。我附加我的图像名称并写入数据。然后我尝试检索但无法获取图像。
ChintaN -Maddy- Ramani'1

我已经成功完成了从app1写入所有图像并使用应用程序组从app2检索所有图像的操作。谢谢 。+1 :)。
ChintaN -Maddy- Ramani'1

是否可以让第三方应用程序加入我的组(通过选择),还是所有应用程序都必须来自同一开发者帐户?
DwarDoh

@DwarDoh必须来自同一开发人员帐户。
ChintaN -Maddy- Ramani'3

14

在应用之间共享数据可能吗?是的!

使用iOS 3.0提供的UIPasteBoard,此处提供文档。苹果文档说:

UIPasteboard类使应用程序可以使用系统范围的或特定于应用程序的粘贴板在应用程序内或与另一个应用程序共享数据。

也可以在钥匙串中的应用程序之间共享数据,尽管这些数据主要是用作密码的,因此,可以存储任何可序列化的内容。 是关于的堆栈溢出问题。


大!这似乎是在应用之间共享数据的可行方法。
trusktr

1
UIPasteboard听起来像是共享小数据(如复制粘贴字符串)的好方法。是否可以在应用之间共享文件?
2013年

1
@ AlikElzin-kilaka是的,它也支持NSData
Evgeny Karkan


3

提及通过UIPasteBoard在应用程序之间共享数据仅适用于iOS7中同一应用程序组中的应用程序。正如苹果所说:

+ [UIPasteboard pasteboardWithName:create:]和+ [UIPasteboard pasteboardWithUniqueName]现在使给定名称唯一,以仅允许同一应用程序组中的那些应用程序访问剪贴板。如果开发人员尝试使用已经存在的名称创建粘贴板,并且它们不属于同一应用程序套件,则他们将获得自己的唯一且私有的粘贴板。请注意,这不会影响系统提供的粘贴板,常规和查找。


苹果“同一应用程序组”是什么意思?
Magic Bullet Dave

2
@MagicBulletDave具有相同捆绑种子ID的应用程序。
MasterBeta 2013年

所述UIPasteboard类使在应用内并与另一应用程序的应用程序来共享数据。要与其他任何应用共享数据,可以使用系统范围内的粘贴板;要与具有与您的应用程序相同的团队ID的另一个应用程序共享数据,可以使用特定于应用程序的粘贴板。
测试

2

如果您不介意访问网络,则可以实施自定义Web服务或使用某些云服务。iCloud本身在这里用处不大。它仅允许您在不同设备上的同一应用之间共享数据。您可以在此处阅读有关iCloud的信息

在不使用网络的情况下,您可以利用“快速应用程序切换”通过URL编码在应用程序之间传输数量有限的数据。我不知道实际可传输的数据量,但是我确定这将是非常有限的。

在这种情况下,JugsteR和baudot的答案是最好的。


嗨psoft你能介绍更多关于您已在两行这里解释的iCloud共享
Vinayaka Karjigi

我读到iCloud ID不必与应用程序的Bundle ID匹配,因此可以选择iCloud共享。
测试

可以在标准URL内传输64kB的数据。实际上效果很好。如果没有太多数据,可以加密/ base64以提高安全性。
igraczech '16


-4

否。您将不得不使用一些云解决方案。


据我所知,iCloud是用于将一个设备上的数据与其他设备同步的。如果您知道在设备中的应用之间共享数据的任何方式,请共享它。
Durai Amuthan.H

2
dbarjkovic,您是对的,我们可以使用云解决方案在应用程序之间同步数据,因为用于iCloud的标识符不同于捆绑包标识符,并且完全有可能。这是验证stackoverflow.com/a/8882763/730807的链接。支持您的答案。
Durai Amuthan.H

为什么这个答案被否决?这是正确的答案,但需要从文档中获取更多详细信息并给出一些示例
Basheer_CAD
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.