4

Like many of iOS developers I have encountered the issue with application crashing on system before 5.1 when using NSURLIsExcludedFromBackupKey.

It was well described how to evaluate existence of this key on this thread:

Use NSURLIsExcludedFromBackupKey without crashing on iOS 5.0

One of samvermette's comments says that there is a bug in iOS simulator.

Nevertheless I have encountered the same issue with a Release build, even in 2 separate applications. After some investigation I have discovered that application crashed even before main() method beeing called. Which hinted me that this is connected with

NSString * const NSURLIsExcludedFromBackupKey;

evaluation at application launch.

I am not an expert in this field, but I have found out that, if any reference to const value occurs in code (even if it is not actually accessed in runtime) this const is evaluated at very application launch. And this simply causes that crash that many of us experience.

I would like to ask you for some help. Maybe you know a way how to 'weakly' refer to a const value, or maybe there is specific compiler flag. (Using Apple LLVM 3.1).

Thanks in advance.

Please do not comments to put this const's value directly which is @"NSURLIsExcludedFromBackupKey" in this case. I am aware of this workaround, reson for this story is to find a general solution.

Community
  • 1
  • 1
lukewar
  • 2,715
  • 3
  • 19
  • 16
  • i think your issue was solved [here] [here]: http://stackoverflow.com/questions/13498752/how-to-use-addskipbackupattributetoitematurl-api – Ahmed Talaab Dec 04 '13 at 08:26

2 Answers2

1

You can use this code on systems < 5.0.1

#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;
}

Read more here.

edit

If you're only asking how to check for availability of an external constant you can compare its address to NULL or nil. This is the recommended way of doing it.

if (&NSURLIsExcludedFromBackupKey) {
    // The const is available
}
hwaxxer
  • 3,363
  • 1
  • 22
  • 39
  • 1
    Please read carefully the issue here. The problem is not how to exclude files from being backup on iCloud before iOS 5.1. – lukewar May 17 '12 at 12:45
  • Thank you for your attempt to help but this is not a problem here. As I have described (and linked to other story) I am aware of known solution for this issue. The problem I am describing is more about constants evaluation at application launch, which causes app crash on start. (Release build) – lukewar May 17 '12 at 13:15
  • Then that's a bug and I suggest you file a rdar. Evaluating the address of a constant shouldn't cause a crash. I'm not seeing the issue you describe running 5.1 as Base SDK and 4.x/5.0 Deployment Target. – hwaxxer May 17 '12 at 13:30
  • You have to run it before iOS 5.1. I have raised bug ID# 11494591. – lukewar May 21 '12 at 12:34
  • Having a Base SDK lower than 5.1 doesn't make any sense, then you might as well skip NSURLIsExcludedFromBackupKey completely, since it will never exist? – hwaxxer May 21 '12 at 12:38
  • I am not talking about Base SDK. I said to run/launch on device with iOS lower than 5.1. – lukewar May 22 '12 at 14:46
  • Your Base SDK needs to be 5.1.. Set the Deployment Target if you want to run on lower iOS versions. Read [this](http://stackoverflow.com/a/1358314/254422) for more information. – hwaxxer May 22 '12 at 15:56
  • Why you keep on explaining me obvious things? I know how to build app for older iOS versions and I know how to exclude files from iCloud backup. The problem is of different type, explained above. – lukewar May 23 '12 at 19:27
  • Because I've answered your question "Maybe you know a way how to 'weakly' refer to a const value" and I'm not seeing the issue you describe, running on iOS 4.3 and iOS 5.0. I'm sorry if you think I'm explaining obvious things, maybe something in your setup is wrong or there's a bug in the current SDK you are using. – hwaxxer May 24 '12 at 07:45
  • Have you done Release build? When doing debug and adhoc, everything works. What compiler did you use? – lukewar May 25 '12 at 08:44
  • Yes lukewar is right. Unlike what is mentioned in SDK Compatibility Guide, when I compile with `Base-SDK = 5.1` (latest) with this const, the application crashes at startup. If anyone have a solution I would be very, very interested. – Martin Jul 25 '12 at 09:02
  • 1
    Note that the only way to produce the bug is to make an archive (in release) and install it on the phone. ...or submit it to the appstore and see the angry comments on your app. – Martin Jul 25 '12 at 09:22
1

I found a solution, thanks to https://stackoverflow.com/a/9620714/127493 !

NSString * const NSURLIsExcludedFromBackupKey;

is NOT weak-linked, even if Base SDK is set to iOS 5.1, unlike the SDK Compatibility Guide says.

The trick is to use the result of this const.
If I do

NSLog(@"%@", NSURLIsExcludedFromBackupKey);

the result is @"NSURLIsExcludedFromBackupKey"

So my resulting code is

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

NSError * error = nil;
BOOL success;
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"5.1")) {
    success = [storeURL setResourceValue:[NSNumber numberWithBool:YES] forKey:@"NSURLIsExcludedFromBackupKey" error:&error];
}
Community
  • 1
  • 1
Martin
  • 11,881
  • 6
  • 64
  • 110