ios cordova联系人插件中的内存泄漏?

时间:2015-06-06 02:36:48

标签: ios objective-c cordova cocoa memory-leaks

这里是导致泄漏的方法的源代码。

- (void)search:(CDVInvokedUrlCommand*)command
{
    NSString* callbackId = command.callbackId;
    NSArray* fields = [command argumentAtIndex:0];
    NSDictionary* findOptions = [command argumentAtIndex:1 withDefault:[NSNull null]];

    [self.commandDelegate runInBackground:^{
        // from Apple:  Important You must ensure that an instance of ABAddressBookRef is used by only one thread.
        // which is why address book is created within the dispatch queue.
        // more details here: http: //blog.byadrian.net/2012/05/05/ios-addressbook-framework-and-gcd/
        CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
        CDVContacts* __weak weakSelf = self;     // play it safe to avoid retain cycles
        // it gets uglier, block within block.....
        [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError* errCode) {
            if (addrBook == NULL) {
                // permission was denied or other error - return error
                CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:errCode ? (int)errCode.errorCode:UNKNOWN_ERROR];
                [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
                return;
            }

            NSArray* foundRecords = nil;
            // get the findOptions values
            BOOL multiple = NO;         // default is false
            NSString* filter = nil;
            NSArray* desiredFields = nil;
            if (![findOptions isKindOfClass:[NSNull class]]) {
                id value = nil;
                filter = (NSString*)[findOptions objectForKey:@"filter"];
                value = [findOptions objectForKey:@"multiple"];
                if ([value isKindOfClass:[NSNumber class]]) {
                    // multiple is a boolean that will come through as an NSNumber
                    multiple = [(NSNumber*)value boolValue];
                    // NSLog(@"multiple is: %d", multiple);
                }
                desiredFields = [findOptions objectForKey:@"desiredFields"];
                // return all fields if desired fields are not explicitly defined
                if (desiredFields == nil || desiredFields.count == 0) {
                    desiredFields = [NSArray arrayWithObjects:@"*", nil];
                }
            }

            NSDictionary* searchFields = [[CDVContact class] calcReturnFields:fields];
            NSDictionary* returnFields = [[CDVContact class] calcReturnFields:desiredFields];

            NSMutableArray* matches = nil;
            if (!filter || [filter isEqualToString:@""]) {
                // get all records
                foundRecords = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople(addrBook);
                if (foundRecords && ([foundRecords count] > 0)) {
                    // create Contacts and put into matches array
                    // doesn't make sense to ask for all records when multiple == NO but better check
                    int xferCount = multiple == YES ? (int)[foundRecords count] : 1;
                    matches = [NSMutableArray arrayWithCapacity:xferCount];

                    for (int k = 0; k < xferCount; k++) {
                        CDVContact* xferContact = [[CDVContact alloc] initFromABRecord:(__bridge ABRecordRef)[foundRecords objectAtIndex:k]];
                        [matches addObject:xferContact];
                        xferContact = nil;
                    }
                }
            } else {
                foundRecords = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople(addrBook);
                matches = [NSMutableArray arrayWithCapacity:1];
                BOOL bFound = NO;
                int testCount = (int)[foundRecords count];

                for (int j = 0; j < testCount; j++) {
                    CDVContact* testContact = [[CDVContact alloc] initFromABRecord:(__bridge ABRecordRef)[foundRecords objectAtIndex:j]];
                    if (testContact) {
                        bFound = [testContact foundValue:filter inFields:searchFields];
                        if (bFound) {
                            [matches addObject:testContact];
                        }
                        testContact = nil;
                    }
                }
            }
            NSMutableArray* returnContacts = [NSMutableArray arrayWithCapacity:1];

            if ((matches != nil) && ([matches count] > 0)) {
                // convert to JS Contacts format and return in callback
                // - returnFields  determines what properties to return
                @autoreleasepool {
                    int count = multiple == YES ? (int)[matches count] : 1;

                    for (int i = 0; i < count; i++) {
                        CDVContact* newContact = [matches objectAtIndex:i];
                        NSDictionary* aContact = [newContact toDictionary:returnFields];
                        [returnContacts addObject:aContact];
                    }
                }
            }
            // return found contacts (array is empty if no contacts found)
            CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:returnContacts];
            [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
            // NSLog(@"findCallback string: %@", jsString);

            if (addrBook) {
                CFRelease(addrBook);
            }
        }];
    }];     // end of workQueue block

    return;
}

执行大部分泄漏的特定行是foundRecords = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople(addrBook);,但考虑到使用了正确的__bridge_transfer调用,这会令人困惑。这里发生了什么?

0 个答案:

没有答案