在 iOS 5.0 上使用 NSURLIsExcludedFromBackupKey 而不会崩溃
Posted
技术标签:
【中文标题】在 iOS 5.0 上使用 NSURLIsExcludedFromBackupKey 而不会崩溃【英文标题】:Use NSURLIsExcludedFromBackupKey without crashing on iOS 5.0 【发布时间】:2012-03-08 15:56:43 【问题描述】:可用性检查似乎工作正常,但我似乎无法设置NSURLIsExcludedFromBackupKey
键而不会在启动时出现此崩溃:
dyld:未找到符号:_NSURLIsExcludedFromBackupKey 引用自: /用户/山姆/图书馆/应用程序支持/iPhone 模拟器/5.0/Applications/B0872A19-3230-481C-B5CE-D4BDE264FBDF/Transit.app/Transit 预计在: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk/System/Library/Frameworks/Foundation.framework/Foundation 在 /Users/sam/Library/Application Support/iPhone 模拟器/5.0/Applications/B0872A19-3230-481C-B5CE-D4BDE264FBDF/Transit.app/Transit
这是我的方法:
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
if (&NSURLIsExcludedFromBackupKey == nil)
return NO;
NSError *error;
[URL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
return (error != nil);
如果我注释掉这一行,崩溃就会消失:
[URL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
我必须弱链接 Foundation 吗?
编辑:不确定它是否有区别,但此方法放在NSFileManager
类别中。
【问题讨论】:
您确定没有调用该行吗?你能在 ios 5 中使用调试器单步调试吗? @kevboh 应用程序在启动时崩溃,但实际上从未调用过该行。尝试设置断点,它永远不会被调用。我得到的堆栈跟踪是cl.ly/ErTK 很奇怪。你的基础 SDK 是 5.1 吗?也许尝试删除应用程序的派生数据并清理? 基础 SDK 为 5.0。删除了派生数据并清理了构建文件夹,仍然没有变化:( 啊,你的Base SDK应该是最新的(5.1)。 【参考方案1】:这里是 iOS = 5.1 的代码,包括@Cocoanetics 提到的迁移技术。
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
const char* filePath = [[URL path] fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
if (&NSURLIsExcludedFromBackupKey == nil)
// iOS 5.0.1 and lower
u_int8_t attrValue = 1;
int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
return result == 0;
else
// First try and remove the extended attribute if it is present
int result = getxattr(filePath, attrName, NULL, sizeof(u_int8_t), 0, 0);
if (result != -1)
// The attribute exists, we need to remove it
int removeResult = removexattr(filePath, attrName, 0);
if (removeResult == 0)
NSLog(@"Removed extended attribute on file %@", URL);
// Set the new key
return [URL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:nil];
【讨论】:
这也不适用于用户从 5.0.1 升级到 5.1 时出现的文件。然后这些将具有文件属性,但没有键。您必须检查这种情况并迁移文件。更安全的方法是同时设置并使用实际的 NSString。 我分叉了通过检测和删除属性来添加迁移的要点:gist.github.com/2002382 您不应该使用错误的存在来检测故障;使用 setResourceValue:forKey:error 返回的 BOOL。 Cocoa 约定是错误可能在成功时包含某些内容(您应该忽略)。 @tim,我只是建议了一个您可以批准的编辑。它几乎处理了 Cocoanetics 指出的迁移技术,它包括 Jesse Rusak 对 NSError 问题的修复。我也是提交 ShareKit 2.0 以包含备份属性代码的人。感谢大家的建议,我会在以后的 pull request 中更新那里的代码。 别忘了#import这似乎是 iPhone 5.0 模拟器的一个错误。我尝试在 5.0 设备上运行代码并且没有崩溃。将此错误报告为rdar://11017158。
编辑:这已在 Xcode 4.5 DP2 中修复(不确定是否在 4.4 中)。
【讨论】:
不错的收获。我会在模拟器中#define 代码,这样你仍然可以在 5.0 中对其进行测试。 恐怕问题不仅出现在模拟器上。构建发布版本时我遇到了同样的崩溃。实际上,在模拟器上一切正常。我认为问题在于应用程序启动时的 const 评估,因为应用程序甚至在主方法调用之前就崩溃了。 我可以确认,当使用发布版本时,它实际上会在 5.0.1 设备上崩溃。【参考方案3】:添加此行以强制符号为弱导入:
extern NSString * const NSURLIsExcludedFromBackupKey __attribute__((weak_import));
【讨论】:
就我而言,这并不能解决 5.0.1 设备上的问题。我还是会崩溃。 @Martin :我将它添加到引用 NSURLIsExcludedFromBackupKey 的代码文件中。 Olivier :我从未测试过 5.0.1,我将不得不进一步调查。【参考方案4】:根据您的操作,此快速修复可能对您有用。它对我有用。
将 CoreFoundation 框架添加到您的项目中并将其标记为 OPTIONAL(非必需)。
【讨论】:
【参考方案5】:问题是这个键只存在于 5.1 及以上版本。对于 5.0.1,您需要设置扩展文件属性。唯一向后兼容的方法是找出该键的 NSString 值并将其设置为低于 5.1。
【讨论】:
我什至没有在寻找向后兼容的解决方案。我只想在 iOS 5.1 上设置属性,而不是在 5.0 上做任何事情(这就是检查的作用)。但即使最后一行从未被调用,应用程序也会因“未找到符号”错误而崩溃。 是的,但问题是NSURLIsExcludedFromBackupKey
不是弱链接!我想如果我们找出 NSURLIsExcludedFromBackupKey 的 NSString 值,它就会起作用。但是怎么找呢??
哦,我太笨了……NSLog(@"%@", NSURLIsExcludedFromBackupKey);
来找到它的价值。所以它给出了@"NSURLIsExcludedFromBackupKey"
,并通过将NSURLIsExcludedFromBackupKey
替换为@"NSURLIsExcludedFromBackupKey"
它可以工作!
感谢 Cocoanetics,我在此处发布了该问题的解决方案:***.com/a/11647534/127493 它适用于我,如果适用,请随时通知我。【参考方案6】:
在更新 ShareKit 并重做一个以 iOS 5.1 为目标的项目后,我遇到了同样的问题,我会在编译或与 NSURLIsExcludedFromBackupKey 相关的链接时遇到错误。 ShareKit 人似乎建议您可以通过确保您的项目与 CoreFoundation 框架链接并将其设置为“可选”而不是“必需”来解决问题。但是,这对我不起作用。
最终我通过使用预处理器解决了这个问题:
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
#ifndef NSURLIsExcludedFromBackupKey
// iOS <= 5.0.1.
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;
#else
// iOS >= 5.1
// First try and remove the extended attribute if it is present
int result = getxattr(filePath, attrName, NULL, sizeof(u_int8_t), 0, 0);
if (result != -1)
// The attribute exists, we need to remove it
int removeResult = removexattr(filePath, attrName, 0);
if (removeResult == 0)
NSLog(@"Removed extended attribute on file %@", URL);
return [URL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:nil];
#endif
【讨论】:
NSURLIsExcludedFromBackupKey 不是预处理器宏,#ifdef 将始终为 false。以上是关于在 iOS 5.0 上使用 NSURLIsExcludedFromBackupKey 而不会崩溃的主要内容,如果未能解决你的问题,请参考以下文章
在开发人员设备上安装以前版本的 iOS(当前为 5.0 -> 想要 4.3.5)
UIToolbar 在 ios 5.0 和 ios 6.0 模拟器上显示不同的颜色
4.2.x 设备上奇怪的 iOS 5.0 SDK GCC 副作用