1

I have this method that checks if we have a username and password stored in the keychain:

- (BOOL)hasLoginDetails
{
    FLog
    NSString *username = [self.keychainItem objectForKey:(__bridge id)kSecAttrAccount];
    if (username == nil || [username isEqualToString:@""])
        return NO;

    NSData *passData = [self.keychainItem objectForKey:(__bridge id)kSecValueData];
    if (passData == nil || [passData length] == 0)
        return NO;

    NSString *password = [[NSString alloc] initWithData:passData encoding:NSUTF8StringEncoding];
    if (password == nil || [password isEqualToString:@""])
        return NO;

    return YES;
}

password is returned as NSData so needs converting to a string. This works perfectly fine in normal use however when it's used in the background application:performFetchWithCompletionHandler: method I sometimes get crashes pointing to this line:

NSString *password = [[NSString alloc] initWithData:passData encoding:NSUTF8StringEncoding];

the crash log complains of

-[__NSCFString bytes]: unrecognized selector sent to instance 0x156104a0

I only see these crashes after distributing AdHoc builds. I'm assuming the crash log is saying that the passData variable is actually a string at this point? Any ideas what's going on here?

Thanks

Edit ----

The password is added to the keychain simply using [self.keychainItem setObject:password forKey:(__bridge id)kSecValueData]; password being an NSString. I'm using KeychainItemWrapper from here which converts the password NSString to NSData but doesn't convert it back again which is why I am doing it.

Edit 2 ----

After a debug crash, I check thee passData variable and it was in fact the NSString that should be NSData, so sometimes I'm getting NSData and every now and then i'm getting NSString.

Darren
  • 10,182
  • 20
  • 95
  • 162

2 Answers2

1

Depending on the data protection option that you've set for the keychain item, when the phone is locked, the keychain isn't accessible, so you get some unexpected value and hence you crash.

It was actually quite popular issue, enough so that Apple addressed it specifically in their tech talk videos.

Could you paste the code that deals with setting the keychain item?

Also take a look at these:

iOS KeyChain not retrieving values from background

iOS Keychain occasionally return empty string

Apple Tech Talk Video

Community
  • 1
  • 1
Andrew
  • 3,166
  • 21
  • 32
  • if this was the problem the crash wouldn't be in that line, remember this if: `if (passData == nil || [passData length] == 0) return 0` makes sure the keychain is returning something – Nicos Karalis Mar 11 '14 at 18:00
  • Thanks. I've updated the questions. I can get this to crash on the simulator sometimes but not much. – Darren Mar 11 '14 at 19:20
  • I've just checked the variable contents of passData after a crash and it is in fact the NSString that should be NSData, so sometimes I get data and sometimes a string! – Darren Mar 11 '14 at 19:26
0

Looking for this specific error i found that this exception happens thenyou try call the method initWithData:encoding: passing a NSString instead of a NSData

unrecognized selector sent to instance for NSKeyedUnarchiver: Source

please check in your code, when you save the password, do you save it as a string? if you do you don't have to initWithData:encoding: to read, you can or read as it is or NSString initWithString:

Community
  • 1
  • 1
Nicos Karalis
  • 3,724
  • 4
  • 33
  • 62