my app work very well on ios 9 and 10 ,but when i want to access contacts on ios 11 app crash (actually get Thread 8: signal SIGABRT when click tab to access contacts.)
malloc: * error for object 0x1c401b410: Invalid pointer dequeued from free list * set a breakpoint in malloc_error_break to debug
ContactsViewController.m
#import "ContactsViewController.h"
#import "PhoneMainView.h"
#import "Utils.h"
#import "Utility.h"
#import "Reachability.h"
#import "AddContactViewController.h"
#import <AddressBook/ABPerson.h>
@implementation ContactSelection
static ContactSelectionMode sSelectionMode = ContactSelectionModeNone;
static NSString* sAddAddress = nil;
static NSString* sSipFilter = nil;
static BOOL sEnableEmailFilter = FALSE;
static NSString* sNameOrEmailFilter;
+ (void)setSelectionMode:(ContactSelectionMode)selectionMode {
sSelectionMode = selectionMode;
}
+ (ContactSelectionMode)getSelectionMode {
return sSelectionMode;
}
+ (void)setAddAddress:(NSString*)address {
if(sAddAddress != nil) {
[sAddAddress release];
sAddAddress= nil;
}
if(address != nil) {
sAddAddress = [address retain];
}
}
+ (NSString*)getAddAddress {
return sAddAddress;
}
+ (void)setSipFilter:(NSString*)domain {
[sSipFilter release];
sSipFilter = [domain retain];
}
+ (NSString*)getSipFilter {
return sSipFilter;
}
+ (void)enableEmailFilter:(BOOL)enable {
sEnableEmailFilter = enable;
}
+ (BOOL)emailFilterEnabled {
return sEnableEmailFilter;
}
+ (void)setNameOrEmailFilter:(NSString*)fuzzyName {
[sNameOrEmailFilter release];
sNameOrEmailFilter = [fuzzyName retain];
}
+ (NSString*)getNameOrEmailFilter {
return sNameOrEmailFilter;
}
@end
@implementation ContactsViewController
@synthesize tableController;
@synthesize tableView;
@synthesize sysViewController;
@synthesize allButton;
@synthesize linphoneButton;
@synthesize backButton;
@synthesize addButton;
@synthesize toolBar;
typedef enum _HistoryView {
History_All,
History_Linphone,
History_Search,
History_MAX
} HistoryView;
bool noInternetConnection;
#pragma mark - Lifecycle Functions
- (id)init {
return [super initWithNibName:@"ContactsViewController" bundle:[NSBundle mainBundle]];
}
- (void)dealloc {
[tableController release];
[tableView release];
[allButton release];
[linphoneButton release];
[backButton release];
[addButton release];
[_searchBar release];
[_headerView release];
[super dealloc];
}
#pragma mark - UICompositeViewDelegate Functions
static UICompositeViewDescription *compositeDescription = nil;
+ (UICompositeViewDescription *)compositeViewDescription {
if(compositeDescription == nil) {
compositeDescription = [[UICompositeViewDescription alloc] init:@"Contacts"
content:@"ContactsViewController"
stateBar:nil
stateBarEnabled:false
tabBar:@"UIMainBar"
tabBarEnabled:true
fullscreen:false
landscapeMode:[LinphoneManager runningOnIpad]
portraitMode:true];
}
return compositeDescription;
}
#pragma mark - ViewController Functions
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
self.allButton.backgroundColor=self.headerView.backgroundColor;
self.linphoneButton.backgroundColor=self.headerView.backgroundColor;
[[NSNotificationCenter defaultCenter] removeObserver:self
name:kReachabilityChangedNotification
object:nil];
}
- (void)relayoutTableView {
CGRect subViewFrame= self.view.frame;
// let the toolBar be visible
subViewFrame.origin.y = self.searchBar.frame.size.height+self.searchBar.frame.origin.y;
subViewFrame.size.height -= (self.headerView.frame.size.height+self.searchBar.frame.size.height);
[UIView animateWithDuration:0.2 animations:^{
self.tableView.frame = subViewFrame;
}];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
//[self onSyncButton:nil];
Reachability *reachability = [Reachability reachabilityWithHostname:@"www.google.com"];
[self reactInternetConnection:reachability];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(reachabilityDidChange:)
name:kReachabilityChangedNotification
object:nil];
// cannot change search bar icon nor text font from the interface builder...
// [_searchBar setImage:[UIImage imageNamed:@"contact_search.png" ] forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];
// UITextField *searchText = [_searchBar valueForKey:@"_searchField"];
// [searchText setFont:[UIFont fontWithName:@"CustomFont" size:12]];
_searchBar.showsCancelButton = (_searchBar.text.length > 0);
BOOL use_system = [[LinphoneManager instance] lpConfigBoolForKey:@"use_system_contacts"];
if( use_system && !self.sysViewController){// use system contacts
ABPeoplePickerNavigationController* picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
picker.view.frame = self.view.frame;
[self.view addSubview:picker.view];
self.sysViewController = picker;
self.searchBar.hidden = TRUE;
} else if( !use_system && !self.tableController ){
self.tableController = [[[ContactsTableViewController alloc] init] autorelease];
self.tableView = [[[UITableView alloc] init] autorelease];
self.tableController.view = self.tableView;
[self relayoutTableView];
self.tableView.dataSource = self.tableController;
self.tableView.delegate = self.tableController;
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight |
UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleTopMargin |
UIViewAutoresizingFlexibleBottomMargin |
UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin;
[self.view addSubview:tableView];
[self update];
}
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if(![FastAddressBook isAuthorized]) {
UIAlertView* error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Address book",nil)
message:NSLocalizedString(@"You must authorize the application to have access to address book.\n"
"Toggle the application in Settings > Privacy > Contacts",nil)
delegate:nil
cancelButtonTitle:NSLocalizedString(@"Continue",nil)
otherButtonTitles:nil];
[error show];
[error release];
//me
// [[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]];
}
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self changeView:History_All];
// Set selected+over background: IB lack !
[linphoneButton setBackgroundImage:[UIImage imageNamed:@"buttonR"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[linphoneButton setTitle:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]
forState:UIControlStateNormal];
[LinphoneUtils buttonFixStates:linphoneButton];
// Set selected+over background: IB lack !
[allButton setBackgroundImage:[UIImage imageNamed:@"buttonch2"]
forState:(UIControlStateHighlighted | UIControlStateSelected)];
[LinphoneUtils buttonFixStates:allButton];
[tableController.tableView setBackgroundColor:[UIColor clearColor]]; // Can't do it in Xib: issue with ios4
[tableController.tableView setBackgroundView:nil]; // Can't do it in Xib: issue with ios4
}
#pragma mark -
- (void)reachabilityDidChange:(NSNotification *)notification {
Reachability *reachability = (Reachability *)[notification object];
[self reactInternetConnection:reachability];
}
- (void)reactInternetConnection:(Reachability*)reachability {
if ([reachability isReachable]) {
noInternetConnection = false;
} else {
noInternetConnection = true;
}
}
- (void)changeView:(HistoryView)view {
if(view == History_All) {
[ContactSelection setSipFilter:nil];
[ContactSelection enableEmailFilter:FALSE];
[tableController loadData];
allButton.selected = TRUE;
} else {
allButton.selected = FALSE;
}
if(view == History_Linphone) {
[ContactSelection setSipFilter:[LinphoneManager instance].contactFilter];
[ContactSelection enableEmailFilter:FALSE];
[tableController loadData];
linphoneButton.selected = TRUE;
} else {
linphoneButton.selected = FALSE;
}
}
- (void)changeAvafoneView {
[self changeView: History_Linphone];
}
- (void)update {
switch ([ContactSelection getSelectionMode]) {
case ContactSelectionModePhone:
case ContactSelectionModeMessage:
[addButton setHidden:TRUE];
[backButton setHidden:FALSE];
break;
default:
[addButton setHidden:FALSE];
[backButton setHidden:TRUE];
break;
}
if([ContactSelection getSipFilter]) {
allButton.selected = FALSE;
linphoneButton.selected = TRUE;
} else {
allButton.selected = TRUE;
linphoneButton.selected = FALSE;
}
[tableController loadData];
}
#pragma mark - Action Functions
- (IBAction)onAllClick:(id)event {
[self changeView: History_All];
}
- (IBAction)onLinphoneClick:(id)event {
[self changeView: History_Linphone];
}
- (IBAction)onAddContactClick:(id)event {
// Go to Contact details view
// ContactDetailsViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[ContactDetailsViewController compositeViewDescription] push:TRUE], ContactDetailsViewController);
// if(controller != nil) {
// if([ContactSelection getAddAddress] == nil) {
// [controller newContact];
// } else {
// [controller newContact:[ContactSelection getAddAddress]];
// }
// }
AddContactViewController *add = [[UIStoryboard storyboardWithName:@"DialerStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:@"addContacts"];
[self presentViewController:add animated:YES completion:^{
}];
}
- (IBAction)onBackClick:(id)event {
[[PhoneMainView instance] popCurrentView];
}
- (IBAction)onSyncButton:(id)sender {
if (!noInternetConnection) {
[Utility showProgressBar:@"Synchronize" message:nil];
dispatch_queue_t jogvoiceCheckingQueue = dispatch_queue_create("JogvoiceContactListChecking",NULL);
dispatch_async(jogvoiceCheckingQueue, ^{
[[LinphoneManager instance].fastAddressBook checkContactListForJogvoiceList];
[Utility stopProgressBar];
NSLog(@"Finish checking jogvoice contact list!");
});
} else {
UIAlertView* error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Network is unreachable",nil)
message:NSLocalizedString(@"",nil)
delegate:nil
cancelButtonTitle:NSLocalizedString(@"OK",nil)
otherButtonTitles:nil];
[error show];
[error release];
}
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[self searchBar:searchBar textDidChange:nil];
[searchBar resignFirstResponder];
}
#pragma mark - Rotation handling
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
// the searchbar overlaps the subview in most rotation cases, we have to re-layout the view manually:
[self relayoutTableView];
}
#pragma mark - ABPeoplePickerDelegate
-(void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker
{
[[PhoneMainView instance] popCurrentView];
return;
}
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person {
return true;
}
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
property:(ABPropertyID)property
identifier:(ABMultiValueIdentifier)identifier {
CFTypeRef multiValue = ABRecordCopyValue(person, property);
CFIndex valueIdx = ABMultiValueGetIndexForIdentifier(multiValue,identifier);
NSString *phoneNumber = (NSString *)ABMultiValueCopyValueAtIndex(multiValue, valueIdx);
// Go to dialer view
DialerViewController *controller = DYNAMIC_CAST([[PhoneMainView instance] changeCurrentView:[DialerViewController compositeViewDescription]], DialerViewController);
if(controller != nil) {
[controller call:phoneNumber displayName:[(NSString*)ABRecordCopyCompositeName(person) autorelease]];
}
[phoneNumber release];
CFRelease(multiValue);
return false;
}
#pragma mark - searchBar delegate
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
// display searchtext in UPPERCASE
// searchBar.text = [searchText uppercaseString];
searchBar.showsCancelButton = (searchText.length > 0);
[ContactSelection setNameOrEmailFilter:searchText];
[tableController loadData];
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
[searchBar setShowsCancelButton:FALSE animated:TRUE];
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
[searchBar setShowsCancelButton:TRUE animated:TRUE];
}
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[searchBar resignFirstResponder];
}
- (void)viewDidUnload {
[self setToolBar:nil];
[super viewDidUnload];
}
@end
p.s.:when i off access to contact in privacy, app won’t crash but fetch contact fail
You can verify two things
1.Allow user to give permission for contact details
2.Plist.Info file has Description for NSContactsUsageDescription.