Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

jhershauer

macrumors member
Original poster
Feb 3, 2003
61
0
Gilbert, AZ
Hi,
I've created a simple list application, starting out with a custom datasource class that simply returns a hard-wired list of data. With that working, I'm now attempting to alter my datasource class to pull data from the address book. I've added a reference to AddressBook/ABAddressBook.h and created an ABAddressBookRef variable. The application compiles fine with that, and I'm able to get Code Sense into the ABAddressBook API. However, if I attempt to initialize my ABAddressBookRef variable by calling ABAddressBookCreate(), I get a link error like this:

"_ABAddressBookCreate", referenced from:
-[TestTableDataSource init] in TestTableDataSource.o
symbol(s) not found
collect2: id returned 1 exit status

I'm new to this environment, so there may be something obvious I'm missing here in terms of setting this up. Has anybody successfully initialized/accessed the Address Book API with the iPhone SDK yet? Any quick samples of how to get the ball rolling with that API?

Thanks,
Jeff
 

jhershauer

macrumors member
Original poster
Feb 3, 2003
61
0
Gilbert, AZ
Did you link in the entire framework?

Wow...quick response! I was just coming back to answer myself. No, I hadn't linked in that framework. I was just poking around and noticed the "Linked Frameworks" node in the Groups and Files pane. All is well now.

Thanks!

Jeff
 

jhershauer

macrumors member
Original poster
Feb 3, 2003
61
0
Gilbert, AZ
Follow-up question

OK, I've got a follow-up question that's more of a beginner Objective-C question:

I wanted to create a couple of class-level variables ("ivars" I suppose they're called). One would be a pointer to the AddressBook itself, and the other would point to the array of all people in the Address Book (NSArray *). This was so I wouldn't have to keep re-getting these things in the other methods of my class.

I was looking for the equivalent of a "constructor" in Objective-C and found the -init() method, so I overrode that as follows:

Code:
-(id)init
{
	self = [super init];
	addressBook = <SDKMehtodToGetAddressBook>();
	allPeople = (NSArray *)<SDKMethodToGetArrayOfPeople>(addressBook);
	return self;
}

This didn't work. When I got into my other methods, addressBook and allPeople were always nil. I got around this by turning addressBook and allPeople into properties, and implementing getters like this:


Code:
- (<SDKTypeThatReferencesAnAddressBook>)_getAddressBook {
	if (nil == addressBook)
	{
		addressBook = <SDKMethodToReturnAnAddressBook>();
	}
	return addressBook;
}
- (NSArray *)_getAllPeople {
	if (nil == allPeople)
	{
		allPeople = (NSArray *)<SDKMethodToGetArrayOfPeople>(self.addressBook);
	}
	return allPeople;
}


This works fine, and my application is happily running in the simulator, returning a list of people from the address book. However, I'm curious as to why the assignments to the allPeople and addressBook variables didn't "stick" when I tried to do it through the init method. I've done some google searching, and that seems like it's supposed to be the appropriate place to initialize ivars for the class. Any insight would be appreciated.


Here's the interface for my class:

Code:
#import <SDK UI Kit>
#import <SDK Address Book>


@interface TestTableDataSource : NSObject <UITableViewDataSource, UITableViewDelegate> {
<SDKAddressBookReferenceType> addressBook;
NSArray *allPeople;
}

@property (getter=_getAddressBook,assign) <SDKTypeThatReferencesAnAddressBook> addressBook;
@property (getter=_getAllPeople,assign) NSArray *allPeople;
- (NSString *)stringValueForRow:(NSInteger)row;

@end

Thanks,
Jeff

[Edit]: Hmm...I see other references to NDA, and although this thing is publicly available now, I know I agreed to something (didn't actually read it) when I downloaded the SDK, so I've gone back and attempted to kind of obfuscate the code so as not to give any SDK "secrets" away. :)
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
Your init method may not be getting called. You can NSLog() it to see if it is.

How is your class being created?
 

jhershauer

macrumors member
Original poster
Feb 3, 2003
61
0
Gilbert, AZ
Your init method may not be getting called. You can NSLog() it to see if it is.

How is your class being created?

Doh! I feel like an idiot. You're right...the init wasn't being called. I could have sworn I put a breakpoint in my init method to make sure the variables were getting set, but I must not have (taking in a lot of new stuff all at once, and probably getting a bit discombobulated).

Your tip was enough to point me to my problem. I was creating my class instance like this:

Code:
    //Set up data source
    testDs = [TestTableDataSource alloc];

Now I'm creating it like this, and it's working:

Code:
    //Set up data source
    testDs = [[TestTableDataSource alloc] init];

I was assuming that simply doing an alloc on the class was the equivalent of doing a New in C#, and thought my init (which I was thinking of as a constructor) would automatically be called.

At least I learned how to create custom property accessors in the process. :)

Thanks again!

Jeff
 

nick718

macrumors newbie
Jul 2, 2007
16
0
Hey, I'm trying to do something similar. How did you find usages for the ABAddressBookRef class? I looked at the library ref on the developer center, but it had no example code and nothing about how to create the instance. I feel like I must be missing a large amount of reference documentation somewhere.

Thanks
 

netik

macrumors newbie
Mar 11, 2008
6
0
Hey, I'm trying to do something similar. How did you find usages for the ABAddressBookRef class? I looked at the library ref on the developer center, but it had no example code and nothing about how to create the instance. I feel like I must be missing a large amount of reference documentation somewhere.

Thanks

All of the reference documentation is available in the research assistant, and apple has squirreled away tons of example code inside of the documentation bundle. Go to Help, and then "Show research assistant".

Search in the SDK and you should be set.
 

netik

macrumors newbie
Mar 11, 2008
6
0
Doh! I feel like an idiot. You're right...the init wasn't being called. I could have sworn I put a breakpoint in my init method to make sure the variables were getting set, but I must not have (taking in a lot of new stuff all at once, and probably getting a bit discombobulated).

I have a similar problem to yours, but it seems that the compiler is not finding any of the header files. I have errors like:

Code:
/Users/jna/Documents/Iphone App Dev/WhatHappened/Classes/../RootViewController.m:194: error: 'ABPerson' undeclared (first use in this function)
/Users/jna/Documents/Iphone App Dev/WhatHappened/Classes/../RootViewController.m:194: error: 'aPerson' undeclared (first use in this function)
/Users/jna/Documents/Iphone App Dev/WhatHappened/Classes/../RootViewController.m:194: error: 'ABAddressBook' undeclared (first use in this function)
/Users/jna/Documents/Iphone App Dev/WhatHappened/Classes/../RootViewController.m:195: error: 'ABMutableMultiValue' undeclared (first use in this function)
/Users/jna/Documents/Iphone App Dev/WhatHappened/Classes/../RootViewController.m:195: error: 'anAddressList' undeclared (first use in this function)
/Users/jna/Documents/Iphone App Dev/WhatHappened/Classes/../RootViewController.m:196: error: 'kABAddressProperty' undeclared (first use in this function)
/Users/jna/Documents/Iphone App Dev/WhatHappened/Classes/../RootViewController.m:198: warning: unused variable 'primaryIndex'

and I have certainly put the framework in both the 'link binary with libraries' part of my target, as well as in the 'linked framework' part. What gives?

Why can't it see the header files?!
 

nick718

macrumors newbie
Jul 2, 2007
16
0
Thanks for the info.

I am still having an issue though. I show the Research Assistant, but mo matter what I click on, even non-iPhone SDK classes, I see nothing in the window. Is there something I'm missing? I tried just putting the cursor over the class name in the code, and also highlighting the name.

Thanks
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
and I have certainly put the framework in both the 'link binary with libraries' part of my target, as well as in the 'linked framework' part. What gives?

Why can't it see the header files?!

Did you #import <AddressBook/AddressBook.h> ?
 

nick718

macrumors newbie
Jul 2, 2007
16
0
So I've finally managed to get the Research Assistant working, but now I have a new question. This may be a dumb question but, how did you manage to get a list of all the records in the address book? In looking at the doc and the AddressBookh file, I see no functions for just getting a or all of the records.

Thanks!
 

jhershauer

macrumors member
Original poster
Feb 3, 2003
61
0
Gilbert, AZ
So I've finally managed to get the Research Assistant working, but now I have a new question. This may be a dumb question but, how did you manage to get a list of all the records in the address book? In looking at the doc and the AddressBookh file, I see no functions for just getting a or all of the records.

Thanks!

For that, you'll want to import the ABPerson header file and take a look at the available functions there. I believe it's also documented. There's an ABAddressBookCopyArrayOfAllPeople function that will get you all of the records. You'll need your address book reference as a parameter for the ABPerson functions.

Jeff
 

nick718

macrumors newbie
Jul 2, 2007
16
0
Awesome, thanks so much!

One more question to anybody who can answer. Am I missing something here, or are all the AddressBook libraries standard C libraries? I'm finding myself relying on all of these C functions that are passed object references and parameters, it seems to defeat the idea of using Objective C as an OO language for the SDK. Are there some sort of OC wrappers for all this functionality? Or are some of the APIs just standard C, no if an or buts?

Thanks,
Nick
 

netik

macrumors newbie
Mar 11, 2008
6
0
Did you #import <AddressBook/AddressBook.h> ?

Ahh, it was getting the headers but I was used to addressbook in cocoa and accessing it the wrong way.

The iPhone SDK is a bit different, so, to open the address book and get the contacts, it looks something like this:

Code:
// open the default address book. 
	ABAddressBookRef m_addressbook = ABAddressBookCreate();
    if (!m_addressbook) {
        NSLog(@"opening address book");
    }
	
	// can be cast to NSArray, toll-free
	CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(m_addressbook);
	CFIndex nPeople = ABAddressBookGetPersonCount(m_addressbook);

	// CFStrings can be cast to NSString!

	for (int i=0;i < nPeople;i++) { 
		ABRecordRef ref = CFArrayGetValueAtIndex(allPeople,i);
		... do something with ABRecordRef...
	}

	[region release];
 

netik

macrumors newbie
Mar 11, 2008
6
0
For that, you'll want to import the ABPerson header file and take a look at the available functions there. I believe it's also documented. There's an ABAddressBookCopyArrayOfAllPeople function that will get you all of the records. You'll need your address book reference as a parameter for the ABPerson functions.

Jeff

Importing <AddressBook/AddressBook.h> all of the other header files for you. You shouldn't import ABPerson.h directly.
 

nick718

macrumors newbie
Jul 2, 2007
16
0
Ahh, it was getting the headers but I was used to addressbook in cocoa and accessing it the wrong way.

The iPhone SDK is a bit different, so, to open the address book and get the contacts, it looks something like this:

Code:
// open the default address book. 
	ABAddressBookRef m_addressbook = ABAddressBookCreate();
    if (!m_addressbook) {
        NSLog(@"opening address book");
    }
	
	// can be cast to NSArray, toll-free
	CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(m_addressbook);
	CFIndex nPeople = ABAddressBookGetPersonCount(m_addressbook);

	// CFStrings can be cast to NSString!

	for (int i=0;i < nPeople;i++) { 
		ABRecordRef ref = CFArrayGetValueAtIndex(allPeople,i);
		... do something with ABRecordRef...
	}

	[region release];

Reassuring to see that, it's almost exactly what I have. Thanks for the tip on the casting though, I didn't realize those foundations classes could be cast into NS classes that easily.

Do you know how I could go about getting which indexes are for which Record properties? It seems like there should be a list somewhere, but I could not find one.
Thanks
 

drivefast

macrumors regular
Mar 13, 2008
128
0
Do you know how I could go about getting which indexes are for which Record properties? It seems like there should be a list somewhere, but I could not find one.
i think youre talking about how to get the values in the database fields...? something like this?
PHP:
NSString *contactFirstLast = [NSString stringWithFormat:@"%@,%@", 
  ABRecordCopyValue(ref, kABPersonFirstNameProperty), 
  ABRecordCopyValue(ref, kABPersonLastNameProperty)
];
the kABPersonBlahBlahProperty constants (or enums, i forgot what they are) are decribed in the ABPerson documentation pages. it's a little more difficult to get a hold of the multivalues, like addresses and phone numbers, ive got something working if you need it, but i feel it's not as nice as it could be.
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
Any values used from ABRecordCopyValue() need to be released when done, so that code above is leaking memory, and if you use that in a loop with every contact, that'd be a lot of memory to leak.

It should probably be something like this:

Code:
CFStringRef firstName = ABRecordCopyValue(ref, kABPersonFirstNameProperty);
CFStringRef lastName = ABRecordCopyValue(ref, kABPersonLastNameProperty);
NSString *contactFirstLast = [NSString stringWithFormat:@"%@,%@",
    firstName, lastName];
CFRelease(firstName);
CFRelease(lastName);
 

drivefast

macrumors regular
Mar 13, 2008
128
0
thanks for pointing that out. i should have said that in my previous post - i only started with obj-c a couple of days ago ;)

now anyone has any idea how to get the own phone's phone number?... on the iPhone it shows up on top of the "all contacts" list, but i couldnt find it anywhere in the address book database.
 

gifford

macrumors 6502
Jun 11, 2007
422
0
Miserable England
I have been trundling through the adressbook iphone framework all day looking for ways to receive "missed call" events, are an array of missed calls, or any info to do with missed calls.

Has anyone spotted any info on this anywhere?
 

netik

macrumors newbie
Mar 11, 2008
6
0
Any values used from ABRecordCopyValue() need to be released when done, so that code above is leaking memory, and if you use that in a loop with every contact, that'd be a lot of memory to leak.

It should probably be something like this:

Code:
CFStringRef firstName = ABRecordCopyValue(ref, kABPersonFirstNameProperty);
CFStringRef lastName = ABRecordCopyValue(ref, kABPersonLastNameProperty);
NSString *contactFirstLast = [NSString stringWithFormat:@"%@,%@",
    firstName, lastName];
CFRelease(firstName);
CFRelease(lastName);

I really don't have my head completely around references and what needs to be released and what doesn't yet.

I don't understand how you can copy something into a reference, and then release it, and still be able to use it. Got a reference for this that I can read?
 

netik

macrumors newbie
Mar 11, 2008
6
0
I have been trundling through the adressbook iphone framework all day looking for ways to receive "missed call" events, are an array of missed calls, or any info to do with missed calls.

Has anyone spotted any info on this anywhere?

I don't think you're going to get that from the address book.

There's no section of the SDK that I can find to get to call, calendar, or voice mail data, so I guess that's not available just yet. Maybe there's an NSDictionary someplace with this?
 

gifford

macrumors 6502
Jun 11, 2007
422
0
Miserable England
I don't think you're going to get that from the address book.

There's no section of the SDK that I can find to get to call, calendar, or voice mail data, so I guess that's not available just yet. Maybe there's an NSDictionary someplace with this?

I was told by one of the guy's from Apple that address book was where to look. So I kept on looking, and looking, and looking, and now I have given up.

I will have to wait I suppose, the application I want it for has already been put off for 3 years in anticipation of the iphone (and lack of patience to learn any other inevitably doomed mobile platform) so whats another couple of years gona make!
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.