2017-12-02 286 views
0

我在我的应用程序中使用linphone SDK。当我开始立即运行应用程序崩溃时。 应用程序启动后它的呼叫[Fastaddreesbook init]呼吁[FastAddreesBook reload]呼吁[FastAddreesBook loadData]呼吁[FastAddreesBook normalizeSipURI]EXC_BAD_ACCESS在这种方法崩溃发生:EXC_BAD_ACCESS在开始运行应用程序时崩溃?

LinphoneAddress* linphoneAddress = linphone_core_interpret_url([LinphoneManager getLc], [address UTF8String]); 

主题1:EXC_BAD_ACCESS(代码= 1,地址=为0x0)

/* FastAddressBook.h 
* 
* Copyright (C) 2011 Belledonne Comunications, Grenoble, France 
* 
* This program is free software; you can redistribute it and/or modify 
* it under the terms of the GNU General Public License as published by 
* the Free Software Foundation; either version 2 of the License, or 
* (at your option) any later version. 
* 
* This program is distributed in the hope that it will be useful, 
* but WITHOUT ANY WARRANTY; without even the implied warranty of 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
* GNU General Public License for more details. 
* 
* You should have received a copy of the GNU General Public License 
* along with this program; if not, write to the Free Software 
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
*/ 
#ifdef __IPHONE_9_0 
#import <Contacts/Contacts.h> 
#endif 
#import "FastAddressBook.h" 
#import "LinphoneManager.h" 
#import "BundleLocalData.h" 
#import "AppUtil.h" 
#import "WebserviceUtil.h" 
#import "ContactEntry.h" 
#import "ContactsViewController.h" 

@implementation FastAddressBook 

static void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef info, void *context); 

+ (NSString*)getContactDisplayName:(ABRecordRef)contact { 
    NSString *retString = nil; 
    if (contact) { 
     CFStringRef lDisplayName = ABRecordCopyCompositeName(contact); 
     if(lDisplayName != NULL) { 
      retString = [NSString stringWithString:(NSString*)lDisplayName]; 
      CFRelease(lDisplayName); 
     } 
    } 
    return retString; 
} 

+ (UIImage*)squareImageCrop:(UIImage*)image 
{ 
    UIImage *ret = nil; 

    // This calculates the crop area. 

    float originalWidth = image.size.width; 
    float originalHeight = image.size.height; 

    float edge = fminf(originalWidth, originalHeight); 

    float posX = (originalWidth - edge)/2.0f; 
    float posY = (originalHeight - edge)/2.0f; 


    CGRect cropSquare = CGRectMake(posX, posY, 
            edge, edge); 


    CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, cropSquare); 
    ret = [UIImage imageWithCGImage:imageRef 
           scale:image.scale 
         orientation:image.imageOrientation]; 

    CGImageRelease(imageRef); 

    return ret; 
} 

+ (UIImage*)getContactImage:(ABRecordRef)contact thumbnail:(BOOL)thumbnail { 
    UIImage* retImage = nil; 
    if (contact && ABPersonHasImageData(contact)) { 
     CFDataRef imgData = ABPersonCopyImageDataWithFormat(contact, thumbnail? 
                  kABPersonImageFormatThumbnail: kABPersonImageFormatOriginalSize); 

     retImage = [UIImage imageWithData:(NSData *)imgData]; 
     if(imgData != NULL) { 
      CFRelease(imgData); 
     } 

     if (retImage != nil && retImage.size.width != retImage.size.height) { 
      [LinphoneLogger log:LinphoneLoggerLog format:@"Image is not square : cropping it."]; 
      return [self squareImageCrop:retImage]; 
     } 
    } 

    return retImage; 
} 

- (ABRecordRef)getContact:(NSString*)address { 
    @synchronized (addressBookMap){ 
     return (ABRecordRef)addressBookMap[address]; 
    } 
} 

+ (BOOL)isSipURI:(NSString*)address { 
    return [address hasPrefix:@"sip:"] || [address hasPrefix:@"sips:"]; 
} 

+ (NSString*)appendCountryCodeIfPossible:(NSString*)number { 
    if (![number hasPrefix:@"+"] && ![number hasPrefix:@"00"]) { 
     NSString* lCountryCode = [[LinphoneManager instance] lpConfigStringForKey:@"countrycode_preference"]; 
     if (lCountryCode && lCountryCode.length>0) { 
      //append country code 
      return [lCountryCode stringByAppendingString:number]; 
     } 
    } 
    return number; 
} 

+ (NSString*)normalizeSipURI:(NSString*)address { 
    NSString *normalizedSipAddress = nil; 
    LinphoneAddress* linphoneAddress = linphone_core_interpret_url([LinphoneManager getLc], [address UTF8String]); 
    if(linphoneAddress != NULL) { 
     char *tmp = linphone_address_as_string_uri_only(linphoneAddress); 
     if(tmp != NULL) { 
      normalizedSipAddress = [NSString stringWithUTF8String:tmp]; 
      ms_free(tmp); 
     } 
     linphone_address_destroy(linphoneAddress); 
    } 
    return normalizedSipAddress; 
} 

+ (NSString*)normalizePhoneNumber:(NSString*)address { 
    NSMutableString* lNormalizedAddress = [NSMutableString stringWithString:address]; 
    [lNormalizedAddress replaceOccurrencesOfString:@" " 
             withString:@"" 
              options:0 
              range:NSMakeRange(0, lNormalizedAddress.length)]; 
    [lNormalizedAddress replaceOccurrencesOfString:@"(" 
             withString:@"" 
              options:0 
              range:NSMakeRange(0, lNormalizedAddress.length)]; 
    [lNormalizedAddress replaceOccurrencesOfString:@")" 
             withString:@"" 
              options:0 
              range:NSMakeRange(0, lNormalizedAddress.length)]; 
    [lNormalizedAddress replaceOccurrencesOfString:@"-" 
             withString:@"" 
              options:0 
              range:NSMakeRange(0, lNormalizedAddress.length)]; 
    return [FastAddressBook appendCountryCodeIfPossible:lNormalizedAddress]; 
} 

+ (BOOL)isAuthorized { 
    //addme // return !ABAddressBookGetAuthorizationStatus || ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized; 
    return ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized; 
} 


- (FastAddressBook*)init { 
    if ((self = [super init]) != nil) { 
     addressBookMap = [[NSMutableDictionary alloc] init]; 
     addressBook = nil; 
     [self reload]; 
    } 


    self.needToUpdate = FALSE; 
    if ([CNContactStore class]) { 
     //ios9 or later 
     CNEntityType entityType = CNEntityTypeContacts; 
     if([CNContactStore authorizationStatusForEntityType:entityType] == CNAuthorizationStatusNotDetermined) { 
      CNContactStore * contactStore = [[CNContactStore alloc] init]; 
      // nslo(@"CNContactStore requesting authorization"); 
      [contactStore requestAccessForEntityType:entityType completionHandler:^(BOOL granted, NSError * _Nullable error) { 
       //  LOGD(@"CNContactStore authorization granted"); 
      }]; 
     } else if([CNContactStore authorizationStatusForEntityType:entityType]== CNAuthorizationStatusAuthorized) { 
      // LOGD(@"CNContactStore authorization granted"); 
     } 
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateAddressBook:) name:CNContactStoreDidChangeNotification object:nil]; 
    } 


    return self; 
} 




-(void) updateAddressBook:(NSNotification*) notif { 
    // LOGD(@"address book has changed"); 
    self.needToUpdate = TRUE; 
} 




- (void) checkContactListForJogvoiceList { 
    // if (![BundleLocalData isLoadingJogvoiceContactList]) { 
    //  [BundleLocalData setLoadingJogvoiceContactList:true]; 

    int maxPhoneNumberSubmit = 200; 
    NSArray *lContacts = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook); 
    NSMutableDictionary *phoneNumberContactsDictionary = [[NSMutableDictionary alloc] init]; 
    NSMutableArray *allPhoneNumberList = [[NSMutableArray alloc] init]; 
    for (id lPerson in lContacts) { 
     ABRecordRef person = (ABRecordRef)lPerson; 
     NSArray *phoneList = [AppUtil getContactPhoneList:person]; 
     for (NSString* phoneNumber in phoneList) { 
      NSMutableArray* contactList = phoneNumberContactsDictionary[phoneNumber]; 
      if (!contactList) { 
       contactList = [[NSMutableArray alloc] init]; 
      } 
      [contactList addObject:(__bridge ABRecordRef)person]; 
      phoneNumberContactsDictionary[phoneNumber] = contactList; 
     } 
     [allPhoneNumberList addObjectsFromArray:phoneList]; 

     if (allPhoneNumberList.count >= maxPhoneNumberSubmit) { 
      [self checkContactList:allPhoneNumberList phoneNumberContactsDictionary:phoneNumberContactsDictionary]; 
     } 
    } 

    if (allPhoneNumberList.count > 0) { 
     [self checkContactList:allPhoneNumberList phoneNumberContactsDictionary:phoneNumberContactsDictionary]; 
    } 


    //  ABAddressBookUnregisterExternalChangeCallback(addressBook, sync_address_book, self); 

    //  [BundleLocalData setLoadingJogvoiceContactList:false]; 
    // } 
} 

-(void) checkContactList:(NSMutableArray*)allPhoneNumberList phoneNumberContactsDictionary:(NSMutableDictionary*)phoneNumberContactsDictionary { 

    [WebserviceUtil apiGetUsersRegistered:[NSArray arrayWithArray:allPhoneNumberList] 
            success:^(AFHTTPRequestOperation *operation, id responseObject){ 

             NSDictionary* response = responseObject; 
             for (id phoneNumber in allPhoneNumberList) { 
              NSNumber *status = response[phoneNumber]; 
              if (status.intValue == 1) { // registered 
               NSArray* contactList = phoneNumberContactsDictionary[phoneNumber]; 
               for (int index = 0; index < contactList.count; index++) { 
                ABRecordRef contact = (__bridge ABRecordRef) contactList[index]; 
                [self saveContact:phoneNumber contact:contact]; 
               } 
              } 
             } 
             [self saveAddressBook]; 
             [allPhoneNumberList removeAllObjects]; 

            } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
             // nothing 
            }]; 

} 

-(void) saveContact:(NSString*)phoneNumber contact:(ABRecordRef)contact { 

    if(contact == NULL || phoneNumber == NULL) { 
     return; 
    } 

    ABMultiValueRef lMap = ABRecordCopyValue(contact, kABPersonInstantMessageProperty); 
    if (!lMap) { 
     return; 
    } 
    BOOL avafoneAlready = false; 
    for(int i = 0; i < ABMultiValueGetCount(lMap); ++i) { 
     ABMultiValueIdentifier identifier = ABMultiValueGetIdentifierAtIndex(lMap, i); 
     CFDictionaryRef lDict = ABMultiValueCopyValueAtIndex(lMap, i); 
     if(CFDictionaryContainsKey(lDict, kABPersonInstantMessageServiceKey)) { 
      if(CFStringCompare((CFStringRef)[LinphoneManager instance].contactSipField, CFDictionaryGetValue(lDict, kABPersonInstantMessageServiceKey), kCFCompareCaseInsensitive) == 0) { 
       avafoneAlready = true; 
      } 
     } else { 
      //check domain 
      LinphoneAddress* address = linphone_address_new(((NSString*)CFDictionaryGetValue(lDict,kABPersonInstantMessageUsernameKey)).UTF8String); 
      if (address) { 
       if ([[ContactSelection getSipFilter] compare:@"*" options:NSCaseInsensitiveSearch] == NSOrderedSame) { 
        avafoneAlready = true; 
       } else { 
        NSString* domain = [NSString stringWithCString:linphone_address_get_domain(address) 
                  encoding:[NSString defaultCStringEncoding]]; 
        if ([domain compare:[ContactSelection getSipFilter] options:NSCaseInsensitiveSearch] == NSOrderedSame) { 
         avafoneAlready = true; 
        } 
       } 
       linphone_address_destroy(address); 
      } 
     } 
     CFRelease(lDict); 
     if(avafoneAlready) { 
      avafoneAlready = true; 
      break; 
     } 
    } 
    CFRelease(lMap); 

    if (avafoneAlready) { 
     return; 
    } 
    NSString *value = [NSString stringWithFormat:@"900%@", phoneNumber]; 
    ContactEntry *entry = nil; 

    ABMultiValueRef lcMap = ABRecordCopyValue(contact, kABPersonInstantMessageProperty); 
    if(lcMap != NULL) { 
     lMap = ABMultiValueCreateMutableCopy(lcMap); 
     CFRelease(lcMap); 
    } else { 
     lMap = ABMultiValueCreateMutable(kABStringPropertyType); 
    } 
    ABMultiValueIdentifier index; 
    NSError* error = NULL; 

    CFStringRef keys[] = { kABPersonInstantMessageUsernameKey, kABPersonInstantMessageServiceKey}; 
    CFTypeRef values[] = { [value copy], [LinphoneManager instance].contactSipField }; 
    CFDictionaryRef lDict = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values, 2, NULL, NULL); 
    if (entry) { 
     index = ABMultiValueGetIndexForIdentifier(lMap, entry.identifier); 
     ABMultiValueReplaceValueAtIndex(lMap, lDict, index); 
    } else { 
     CFStringRef label = (CFStringRef)[NSString stringWithString:(NSString*)kABPersonPhoneMobileLabel]; 
     ABMultiValueAddValueAndLabel(lMap, lDict, label, &index); 
    } 

    if (!ABRecordSetValue(contact, kABPersonInstantMessageProperty, lMap, (CFErrorRef*)&error)) { 
     [LinphoneLogger log:LinphoneLoggerLog format:@"Can't set contact with value [%@] cause [%@]", value,error.localizedDescription]; 
     CFRelease(lMap); 
    } else { 
     if (entry == nil) { 
      entry = [[[ContactEntry alloc] initWithData:index] autorelease]; 
     } 
     CFRelease(lDict); 
     CFRelease(lMap); 

     /*check if message type is kept or not*/ 
     lcMap = ABRecordCopyValue(contact, kABPersonInstantMessageProperty); 
     lMap = ABMultiValueCreateMutableCopy(lcMap); 
     CFRelease(lcMap); 
     index = ABMultiValueGetIndexForIdentifier(lMap, entry.identifier); 
     lDict = ABMultiValueCopyValueAtIndex(lMap,index); 
     //  if(!CFDictionaryContainsKey(lDict, kABPersonInstantMessageServiceKey)) { 
     /*too bad probably a gtalk number, storing uri*/ 
     NSString* username = CFDictionaryGetValue(lDict, kABPersonInstantMessageUsernameKey); 
     LinphoneAddress* address = linphone_core_interpret_url([LinphoneManager getLc] 
                   ,username.UTF8String); 
     if(address){ 
      char* uri = linphone_address_as_string_uri_only(address); 
      CFStringRef keys[] = { kABPersonInstantMessageUsernameKey, kABPersonInstantMessageServiceKey}; 
      CFTypeRef values[] = { [NSString stringWithCString:uri encoding:[NSString defaultCStringEncoding]], [LinphoneManager instance].contactSipField }; 
      CFDictionaryRef lDict2 = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values, 2, NULL, NULL); 
      ABMultiValueReplaceValueAtIndex(lMap, lDict2, index); 
      if (!ABRecordSetValue(contact, kABPersonInstantMessageProperty, lMap, (CFErrorRef*)&error)) { 
       [LinphoneLogger log:LinphoneLoggerLog format:@"Can't set contact with value [%@] cause [%@]", value,error.localizedDescription]; 
      } 
      CFRelease(lDict2); 
      linphone_address_destroy(address); 
      ms_free(uri); 
     } 
     //  } 
     CFDictionaryRef lDict = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values, 2, NULL, NULL); 
     ABMultiValueReplaceValueAtIndex(lMap, lDict, index); 
     CFRelease(lMap); 
    } 
    CFRelease(lDict); 



} 

- (void)saveAddressBook { 
    if(addressBook != nil){ 
     NSError* err = nil; 
     if(!ABAddressBookSave(addressBook, (CFErrorRef*)err)){ 
      Linphone_warn(@"Couldn't save Address Book"); 
     } 
    } 
} 

- (void)reload { 
    NSLog(@"Fastadd reload first is loaded"); 


    CFErrorRef error; 

    // create if it doesn't exist 
    if (addressBook == nil) { 
    addressBook = ABAddressBookCreateWithOptions(NULL, &error); 
    } 

    if (addressBook != nil) { 
    __weak FastAddressBook *weakSelf = self; 
    ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) { 
    if (!granted) { 
    Linphone_warn(@"Permission for address book acces was denied: %@", [(__bridge NSError *)error description]); 
    return; 
    } 

    ABAddressBookRegisterExternalChangeCallback(addressBook, sync_address_book, (__bridge void *)(weakSelf)); 
    dispatch_async(dispatch_get_main_queue(), ^(void) { 
    [weakSelf loadData]; 
    }); 

    }); 
    } else { 
    Linphone_warn(@"Create AddressBook failed, reason: %@", [(__bridge NSError *)error localizedDescription]); 
    } 




    /* 
    //method1 

    if(addressBook != nil) { 
    ABAddressBookUnregisterExternalChangeCallback(addressBook, sync_address_book, self); 
    CFRelease(addressBook); 
    addressBook = nil; 
    } 
    NSError *error = nil; 

    addressBook = ABAddressBookCreateWithOptions(NULL, NULL); 
    if(addressBook != NULL) { 
    ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) { 
    ABAddressBookRegisterExternalChangeCallback (addressBook, sync_address_book, self); 
    [self loadData]; 
    }); 
    } else { 
    [LinphoneLogger log:LinphoneLoggerError format:@"Create AddressBook: Fail(%@)", [error localizedDescription]]; 
    } 

    */ 



    } 






- (void)loadData { 
    ABAddressBookRevert(addressBook); 
    @synchronized (addressBookMap) { 
     [addressBookMap removeAllObjects]; 
     //melog 
     NSLog(@"Fastadd loaddata is loaded"); 
     NSArray *lContacts = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook); 
     for (id lPerson in lContacts) { 
      // Phone 
      { 
       ABMultiValueRef lMap = ABRecordCopyValue((ABRecordRef)lPerson, kABPersonPhoneProperty); 
       if(lMap) { 
        for (int i=0; i<ABMultiValueGetCount(lMap); i++) { 
         CFStringRef lValue = ABMultiValueCopyValueAtIndex(lMap, i); 
         CFStringRef lLabel = ABMultiValueCopyLabelAtIndex(lMap, i); 
         CFStringRef lLocalizedLabel = ABAddressBookCopyLocalizedLabel(lLabel); 
         NSString* lNormalizedKey = [FastAddressBook normalizePhoneNumber:(NSString*)lValue]; 
         NSString* lNormalizedSipKey = [FastAddressBook normalizeSipURI:lNormalizedKey]; 
         if (lNormalizedSipKey != NULL) lNormalizedKey = lNormalizedSipKey; 
         addressBookMap[lNormalizedKey] = lPerson; 
         CFRelease(lValue); 
         if (lLabel) CFRelease(lLabel); 
         if (lLocalizedLabel) CFRelease(lLocalizedLabel); 
        } 
        CFRelease(lMap); 
       } 
      } 

      // SIP 
      { 
       ABMultiValueRef lMap = ABRecordCopyValue((ABRecordRef)lPerson, kABPersonInstantMessageProperty); 
       if(lMap) { 
        for(int i = 0; i < ABMultiValueGetCount(lMap); ++i) { 
         CFDictionaryRef lDict = ABMultiValueCopyValueAtIndex(lMap, i); 
         BOOL add = false; 
         if(CFDictionaryContainsKey(lDict, kABPersonInstantMessageServiceKey)) { 
          CFStringRef contactSipField = (CFStringRef)[LinphoneManager instance].contactSipField; 
          if (!contactSipField) { 
           contactSipField = CFStringCreateWithCString(NULL, "SIP", kCFStringEncodingMacRoman); 
          } 
          if(CFStringCompare(contactSipField, CFDictionaryGetValue(lDict, kABPersonInstantMessageServiceKey), kCFCompareCaseInsensitive) == 0) { 
           add = true; 
          } 
         } else { 
          add = true; 
         } 
         if(add) { 

          CFStringRef lValue = CFDictionaryGetValue(lDict, kABPersonInstantMessageUsernameKey); 
          NSString* lNormalizedKey = [FastAddressBook normalizeSipURI:(NSString*)lValue]; 
          if(lNormalizedKey != NULL) { 
           addressBookMap[lNormalizedKey] = lPerson; 
          } else { 
           addressBookMap[(NSString*)lValue] = lPerson; 
          } 


          /* 
          NSString *lValue = 
          (__bridge NSString *)CFDictionaryGetValue(lDict, kABPersonInstantMessageUsernameKey); 
          NSString *lNormalizedKey = [FastAddressBook normalizeSipURI:lValue]; 
          if (lNormalizedKey != NULL) { 
           [addressBookMap setObject:(__bridge id)(lPerson)forKey:lNormalizedKey]; 
          } else { 
           [addressBookMap setObject:(__bridge id)(lPerson)forKey:lValue]; 
          } 

          */ 
         } 
         CFRelease(lDict); 
        } 
        CFRelease(lMap); 
       } 
      } 
     } 
     CFRelease(lContacts); 
    } 
    [[NSNotificationCenter defaultCenter] postNotificationName:kLinphoneAddressBookUpdate object:self]; 
} 


void sync_address_book (ABAddressBookRef addressBook, CFDictionaryRef info, void *context) { 
    FastAddressBook* fastAddressBook = (FastAddressBook*)context; 
    [fastAddressBook loadData]; 
} 

- (void)dealloc { 
    ABAddressBookUnregisterExternalChangeCallback(addressBook, sync_address_book, self); 
    CFRelease(addressBook); 
    [addressBookMap release]; 
    [super dealloc]; 
} 

@end 

PS:

-i使用非弧形p roject

-zombie启用也没有改变。

- 值是会和那是因为崩溃发生。

调试控制台: 警告:无法执行支持代码来读取进程中的Objective-C类数据。这可能会降低可用类型信息的质量。

enter image description hereenter image description here

+2

这是基本调试我的朋友。你正试图访问一个0指针。查看代码,看看它为什么是0并修复它。 –

回答

0
LinphoneAddress* linphoneAddress = linphone_core_interpret_url([LinphoneManager getLc], [address UTF8String]); 

address为零。弄清楚为什么是这样,你已经得到了你的崩溃源。它可能应该是零,因为它可能是原始记录中的可选字段。

这段代码有点乱,顺便说一句。它不遵循标准模式(例如,以get为前缀的许多方法)。它确实应该现代化,并启用ARC。

+0

(IValue为零,但IDict有价值。)此行返回零,但我不知道为什么? CFStringRef lValue = CFDictionaryGetValue(lDict,kABPersonInstantMessageUsernameKey); –

+0

因为该键没有值。用户没有即时消息用户名。 – bbum

+0

为什么代码在模拟器中可以正常工作,但不能在真实的device.Mybe它有内存问题。 –

相关问题