ios - 返回具有 Core Foundation 属性的 Objective-C 对象

标签 ios objective-c memory-management automatic-ref-counting core-foundation

我有一个方法,它返回一个名为“Credential”的自定义对象的 NSArray,该对象有两个属性:一个 NSString 和一个 CFDataRef。

正如您所注意到的,该对象有两种类型的属性,一个 NS Objective-C 属性和一个 Core-Foundation 属性。

该对象在每个交互循环中初始化,因为它填充 NSArray,如下所示:

cred = [[Credential alloc] init];
cred.cn = [NSString stringWithString:(__bridge NSString *)(summary)];
cred.serialNumber = CFDataCreateCopy(kCFAllocatorDefault, serialNumber);

当我运行分析器时,我收到消息:

Object leaked: allocated object is not referenced later in this 
execution path and has a retain count of +1

我假设发生此警告是因为我正在初始化一个 CF 对象并从该方法返回而不释放它,但负责释放该对象的 new 应该 是调用该方法的代码。

我应该在哪里调用 Credential 类的 CFDataRef 属性的 CFRelease?

编辑:

我使用的是ARC,所以我把释放NSString(cred.cn)的责任留给了他。不过,关于 CFDataRef (cred.serialNumber),我不会释放它,因为稍后我会从另一个类和部分代码中需要它。然后,我不知道如何管理它。当对象“Credential”被释放时,ARC 会释放它吗?如果没有,我可以重写Credential的dealloc方法来在那里执行serialNumber的CFRelease吗?

这是初始化并返回 Credential 对象的 NSArray 的完整方法:

- (NSArray *) retrieveIdentities
{
    CFArrayRef identities = NULL;
    NSMutableArray *returnIdentities = nil;
    OSStatus sanityCheck = NULL;

    const void *keys[] = {kSecClass, kSecMatchLimit, kSecReturnRef, kSecReturnData, kSecReturnAttributes};
    const void *values[] = {kSecClassIdentity, kSecMatchLimitAll, kCFBooleanTrue, kCFBooleanTrue, kCFBooleanTrue};
    CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, sizeof(values)/sizeof(const void *), NULL, NULL);

    sanityCheck = SecItemCopyMatching(query, (CFTypeRef *)&identities);

    if (query)
        CFRelease(query);
    if (sanityCheck == errSecItemNotFound)
        return nil;
    if (sanityCheck != noErr)
        @throw [[KeychainException alloc] initWithName:@"KeychainException" reason:@"ERROR_LISTING_IDENTITIES" userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithLong: sanityCheck], @"osstatus", nil]];

    CFDictionaryRef result = NULL;
    CFStringRef summary = NULL;
    SecCertificateRef certificate = NULL;
    CFDataRef serialNumber = NULL;
    Credential *cred = nil;
    CFIndex resultCount = CFArrayGetCount(identities);

    returnIdentities = [[NSMutableArray alloc] init];

    for (CFIndex i = 0; i<resultCount; i++)
    {
        result = CFArrayGetValueAtIndex(identities,i);
        SecIdentityRef identity = (SecIdentityRef) CFDictionaryGetValue(result, kSecValueRef);

        if ((sanityCheck = SecIdentityCopyCertificate(identity, &certificate)) != noErr)
             @throw [[KeychainException alloc] initWithName:@"KeychainException" reason:@"ERROR_EXTRACTING_CERTIFICATE" userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithLong: sanityCheck], @"osstatus", nil]];

        CFTypeRef keyClass = CFDictionaryGetValue(result, kSecAttrKeyClass);
        if ([[(__bridge id)keyClass description] isEqual:(__bridge id)(kSecAttrKeyClassPrivate)])
        {
            summary = SecCertificateCopySubjectSummary(certificate);
            serialNumber = CFDataCreateCopy(NULL, CFDictionaryGetValue(result, kSecAttrSerialNumber));
            cred = [[Credential alloc] init];
            cred.cn = [NSString stringWithString:(__bridge NSString *)(summary)];
            cred.serialNumber = CFDataCreateCopy(kCFAllocatorDefault, serialNumber);
            [returnIdentities addObject:cred];

            if (summary)
                CFRelease(summary);

            if (serialNumber)
                CFRelease(serialNumber);
        }
    }

    if (certificate)
        CFRelease(certificate);


    return returnIdentities;
}

最佳答案

如果字符串是使用 CF 函数创建的,这意味着您拥有它,您应该将所有权转移给 ARC。目前,您只是桥接对 ARC 的引用,而不会取得所有权。

对于数据,您需要重写dealloc并在数据上调用CFRelease


分析器并不完美。有些事情它发现很困难,所以它会谨慎行事并告诉您可能存在问题。

可以肯定的是,特别是在泄漏和内存管理方面,您应该使用 Instruments 来检查发生了什么。

关于ios - 返回具有 Core Foundation 属性的 Objective-C 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17319590/

相关文章:

c - 如何计算碎片?

c++ - 使用 strtok 复制部分字符串时出现内存错误

ios - Xcode地址簿显示全名而不是电话号码

php - 如何将文本字段值带入 xcode Obj c 中的其他 viewController?

ios - 使用按需资源自动上传 iOS AppStore

iphone - 如何在 NSURLResponse 中设置 statusCode

ios - 想从 appdelegate 调用 ViewController 的方法

linux - 访问连续的物理地址比访问虚拟地址更快吗?

ios - 访问 Apple AirTag 数据的 Apple Developer API 是什么?

iphone - 每次从标签栏按下标签时如何执行方法?