質問

Leak instruments shows number of leaked NSCFData objects and stack trace apparently contains the following method at the end of the boundary of my app methods.

NSData* SAKeychainGetValue(NSString *key)
{
    NSMutableDictionary *searchDictionary = SAGetKeychainSearchDictionary(key);
    [searchDictionary setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
    [searchDictionary setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];

    CFDataRef value = nil;
    OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)searchDictionary, (CFTypeRef *)&value);
    if (status != errSecSuccess && status != errSecItemNotFound)
    {
        NSLog(@"failed to get key %@ with error %ld.", key, (long)status);
    }
    return (__bridge NSData*)value;
}

But I can't see what is wrong with this method to leak.

役に立ちましたか?

解決

You should use __bridge_transfer instead of __bridge in (__bridge NSData*)value.

The value return from SecItemCopyMatching method (copy means the value returns should be released in apple naming convention) should be released, so you should transfer the ownership to ARC.

他のヒント

You can try using the static analyser to solve issues like this CMD+Shift+B is the default shortcut

But you're mixing your bridges up

NSData* SAKeychainGetValue(NSString *key)
{
    NSMutableDictionary *searchDictionary = SAGetKeychainSearchDictionary(key);
    [searchDictionary setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
    [searchDictionary setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];

    CFDataRef value = nil;
    OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)searchDictionary, (CFTypeRef *)&value);
    if (status != errSecSuccess && status != errSecItemNotFound)
    {
        NSLog(@"failed to get key %@ with error %ld.", key, (long)status);
    }
    return (__bridge_transfer NSData*)value;
}

You could also probably just use NSData directly:

    NSData *value = nil;
    OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)searchDictionary, (CFTypeRef *)&value);
    ...
    return value;
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top