防止 iCloud 同步数据(使用 .nosync?)
Posted
技术标签:
【中文标题】防止 iCloud 同步数据(使用 .nosync?)【英文标题】:Prevent iCloud sync of data (using .nosync?) 【发布时间】:2011-10-14 20:48:16 【问题描述】:编辑:到目前为止,我能想到的最好的方法是弹出一个窗口,要求用户禁用 iCloud 同步,同时将所有数据移动到 Documents 目录,这样它就不会了t 被擦除:In iOS5, is it possible to detect if a user has an app set to back up?
我为 iPhone/iPad 开发离线地图应用程序。
我们过去将所有数据(可能有很多演出)存储在 Caches 目录中。
从 ios5 开始,当用户的硬盘开始变满时,可以随机删除 Caches 目录中的文件。
如何在不将数据同步到 iCloud、iTunes 且不被随机删除的情况下存储本地数据?我的本地数据是一个大型目录树,其中包含许多小数据文件,位于数千个子目录中。
我将目录树从库缓存目录移动到文档目录中的 data.nosync 目录,因为我们已经阅读过这可能是一个解决方案。但是,nosync 文件夹中的数据仍在备份到 iCloud。
现在我创建目录:
NSString* noSyncDirectory()
static NSString *directory = nil;
if (!directory)
directory = [[NSString stringWithFormat:@"%@/%@",
documentsDirectory(), @"data.nosync"] retain];
[Constants createDirectoryIfNeeded:directory];
return directory;
【问题讨论】:
我认为我们将不得不等待 Apple 发布这方面的指导。 你提交bug report了吗? 我就这个问题提交了当年的技术支持请求。 我认为声誉赏金远比 200 美元的奖励更合适。 @AndrewJohnson 财务赏金被强烈劝阻并破坏网站的运作方式:Offering actual money as a bounty? 【参考方案1】:发件人:https://developer.apple.com/library/ios/#qa/qa1719/_index.html
您可以使用以下方法设置“不备份”扩展属性。每当您创建不应备份的文件或文件夹时,将数据写入文件,然后调用此方法,将 URL 传递给文件。
#include <sys/xattr.h>
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
const char* filePath = [[URL path] fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
u_int8_t attrValue = 1;
int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
return result == 0;
更多信息可以找到:https://developer.apple.com/icloud/documentation/data-storage/
进一步说明:虽然开发人员文档错误地暗示(“这些文件将不会被清除,并且不会包含在用户的 iCloud 或 iTunes 备份中。”)不备份标志兼作不 -清除标志并非如此。只需将文件留在缓存目录中并标记它们不备份不会阻止它们的擦除。
【讨论】:
+1,但应该指出的是,这只适用于 iOS 5.0.1 及更高版本(因此所有其他答案)。 我会将其标记为已回答,但正如其他评论者指出的那样,这是从 5.0.1 开始的,它已更改,因为在发布之前这是不可能的。 是的。确实如此。也许需要一个衍生问题,寻找专门为 5.0 工作的变通方法?我已经对这个特定问题进行了大量研究,到目前为止,还没有发现适用于 5.0.0 上的设备的可行解决方法【参考方案2】:也许您可以禁用应用程序的备份并将数据文件存储在应用程序树的其他位置。任何需要支持的东西都可以放在你的应用之外的公共区域。
您也许可以在配置中做到这一点:invalid code signing app submission
或settings:
当您想要让用户选择完全为您的应用启用或禁用 iCloud 使用时。如果您的应用程序包含设置包或内联首选项,您可以包含一个首选项以切换您的应用程序是否将内容存储在 iCloud 中。例如,数据完全由私人管理的文件组成的应用程序可能会这样做,以便让用户选择这些文件的存储方式。
或通过使用 Xcode 删除 com.apple.developer.ubiquity-container-identifiers
权利(可以自动添加):Configuring Your App's iCloud Entitlements
否则,您可能需要发出警告,其中包含有关通过 UI 禁用的说明:
http://www.pcmag.com/article2/0,2817,2394702,00.asp#fbid=bpIwPLZ1HeQ
另一种解决方法是将地图分组到作为单独应用程序安装的集合中。这将是一种无需创建任何同步或备份目录即可存储数据的方法。数据将存储在 .app 目录中并受到保护。
根据缓存空间回收功能的工作方式,它可能不会删除最近访问或修改的文件。您可以尝试在计时器上定期触摸它们。您还可以添加一些旧文件作为诱饵,并检测它们何时被删除或空间不足时至少发出警告或重新下载已删除的对象...
【讨论】:
我认为我们都需要看到更多关于缓存清除行为的测试,我的理论也是它会最后删除最近创建的项目,因此在应用启动/唤醒时触摸它们会使其更有可能离线如果可能,数据将被单独保留。【参考方案3】:这个问题可能还没有解决方法...您可以尝试显式调用URLForUbiquityContainerIdentifier,因为它会在第一次调用时进行一些初始化。然后创建一个带有.nosync
后缀的子目录(基于this example)。
第一次为给定的容器目录调用此方法时,iOS 会扩展您的应用程序沙箱以包含该容器目录。因此,在尝试在 iCloud 中搜索文件之前,至少调用一次此方法非常重要。如果您的应用程序访问多个容器目录,您应该为每个目录调用一次该方法。
.nosync
上的doc:
为确保 iCloud 不会同步持久存储本身:当您为 NSPersistentStoreUbiquitousContentNameKey 设置值时,UIManagedDocument 会将持久存储放在文档包内的 .nosync 目录中。如果使用附加内容(使用 writeAdditionalContent:toURL:originalContentsURL:error: 方法),则必须确保文档目录不是包。通常,您为文档目录提供一个无法识别为文档扩展名的扩展名。
您可能希望确保您拥有com.apple.developer.ubiquity-container-identifiers
权利。
iCloud Containers 字段标识了您的应用可以在用户的 iCloud 存储中访问的容器目录列表。 (此字段对应于 com.apple.developer.ubiquity-container-identifiers 权利。)
【讨论】:
您能否发布一个示例来说明您如何创建无处不在的容器?我还没有使用它们,文档有点混乱。 在Ubiquity返回的容器内外创建.nosync? 我想我只是不知道“Ubiquity 返回的容器”是什么意思。我只是从 NSFileManager 中的 Ubiquity 相关函数中得到 nil。 我会在 ubiquity 内部尝试(基于 this doc,这似乎暗示.nosync
将在 ubiquity 目录中得到遵守)。不知道为什么它给出nil
,可能是一个权利问题(?)
问题是,在阅读完这些文档后,我认为它们仅与防止通过 iCloud 将数据同步到其他应用程序实例有关 - 不一定要备份,目录可能仍会被备份。 【参考方案4】:
可能在项目的摘要窗格中取消选中“启用权利”或编辑配置文件以删除 *ubiquity 设置。 (Notes for ios 5 beta 7 参考权利。)
还有setUbiquitous
函数:
setUbiquitous:itemAtURL:destinationURL:error:
设置指定 URL 处的项目是否应存储在云端。
参数
标志
指定“是”将项目移至 iCloud,或指定“否”将其从 iCloud 中删除(如果当前存在)。
http://developer.apple.com/library/ios/#DOCUMENTATION/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/Reference/Reference.html#//apple_ref/occ/instm/NSFileManager/setUbiquitous:itemAtURL:destinationURL:error:
【讨论】:
那是关于 iCloud 同步,不一定要备份数据。【参考方案5】:有一种更新的方法可以在不直接使用扩展属性的情况下阻止 iCloud 同步数据:
- (BOOL)addSkipBackupAttributeToItemAtPath:(NSString *) filePathString
NSURL* URL= [NSURL fileURLWithPath: filePathString];
assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);
NSError *error = nil;
BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES]
forKey: NSURLIsExcludedFromBackupKey error: &error];
if(!success)
NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error);
return success;
有关更多详细信息,请参阅 Apple 的 Technical Q&A QA1719。
【讨论】:
【参考方案6】:您是否尝试仅将目录命名为“.nosync”而没有前面的数据?一般是可以的。目录被忽略,或者可能是特别的。
但是,这种行为似乎就像用户想要的那样——他们当前可能未使用的应用程序使用的潜在空间可能会被自动回收。我不确定,但你会认为系统会很聪明地回收最近创建的文件,因为只有在别无选择的情况下,所以如果用户最近刚刚存储了地图,除非别无选择,否则它们不会被删除。
出于提交错误的目的,我将要求一种方法来标记目录以供用户在删除前提示 - 这样,如果他们正在同步大量电影并且它会清除数据集,例如您的地图正在谈论,用户将被询问是否要从应用程序“MyCoolMapper”中删除数据“离线地图”以继续同步。
【讨论】:
“但是,这种行为似乎就像用户想要的那样” - 不,用户明确下载地图图块集,当他们在森林中或飞行时将需要这些图块集飞机,或航行他们的船。他们不希望他们被删除,直到他们按下已保存地图的删除按钮。这个新的“功能”可能会破坏几乎所有流行的地图应用程序,更不用说 Instapaper。 隐藏文件似乎被同步了,.nosync 或 .otherwise。 我使用了许多离线地图应用程序。但是有些我不经常使用,我不在乎离线地图是否消失,实际上更希望它们会被系统自动清除。但我不介意,因为我说系统提示我输入一些应用程序数据以提醒我它将被同步删除,我认为这比创建大多数应用程序开发人员将切换到的“永久缓存”目录更可取如果给定选择,则使用真实的。我会对离线地图应用程序做的是在启动时更新磁贴时间戳。 感谢您尝试帮助肯德尔,但我认为您根本不明白。想象一下,我有一个被空军使用的 Flight Charts 应用程序。该应用程序会自动下载整个美国的图表,当图表即将更新时,它还会提前抓取它们,以便在周期变化时更新图表,而无需花费数小时下载新图表。现在想象一下,当他们起飞并打开应用程序时,一半的图表消失了。您是否建议我构建应用程序以在发生这种情况时继续下载新地图? @Kendall - 你错了。阅读marco.org/2011/10/13/ios5-caches-cleaning。如果您将数据放入缓存中,它可能会被删除而不会发出警告。如果你把它放在 /Documents 中,你的应用可能会被拒绝。苹果把这件事搞砸了。以上是关于防止 iCloud 同步数据(使用 .nosync?)的主要内容,如果未能解决你的问题,请参考以下文章
通过 iCloud 同步 CouchBase Lite 数据
核心数据 + iCloud 同步 NSPersistentStoreDidImportUbiquitousContentChangesNotification