Get a random name and number (same contact) from an iPhone users address book - iphone-sdk-3.0

I have had only very little experience using the address book in the iPhone SDK.
Does anyone have a code snippet or knows the code to get a persons name and number Eg 'Fred Smith - 027 292 2112". I haven't had much luck with the stuff I've tried.
I want to achieve this programmatically, and not let the user decide (random pick of the person). I also don't want to display the contact picker either
any tutorial links, or anything would be appreciated.
Thanks in advance
Sam

This code will get a random contact from your address book. And then it will add the first name and the last name, and the first phone number to UILabel properties (first, last and phone).
To make this work, you must first import these header files:
#import <AddressBook/AddressBook.h>
#import <stdlib.h>
stdlib.h is imported to be able to use arc4random.
- (IBAction)randomContact:(id)sender {
ABAddressBookRef addressBook = ABAddressBookCreate();
NSArray *people = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
// randomize an index
NSInteger i = [people count];
i = arc4random() % i;
// get first and last name
first.text = (NSString *)ABRecordCopyValue([people objectAtIndex:i], kABPersonFirstNameProperty);
last.text = (NSString *)ABRecordCopyValue([people objectAtIndex:i], kABPersonLastNameProperty);
// get first phonenumber
ABMultiValueRef multi = ABRecordCopyValue([people objectAtIndex:i], kABPersonPhoneProperty);
phone.text = (NSString*)ABMultiValueCopyValueAtIndex(multi, 0);
[people release];
}

Related

PHPhotoLibrary getting album and photo info

I am trying to get info on all the albums/photos using the PHPhotoLibrary. I barely know objective C, and i've looked at some tutorial/sample but couldn't find everything that I needed.
Here is a link to the sample code I based my code on.
https://developer.apple.com/library/ios/samplecode/UsingPhotosFramework/Introduction/Intro.html#//apple_ref/doc/uid/TP40014575-Intro-DontLinkElementID_2
So far I was able to get the albums name and identifier. And I am getting a list of photos, I am able to get their identifier as well, but not the filename. But if I put a break point in my fonction and look at my PHAsset pointer values, I can see the filename there (inside _filename), but if I try to call the variable with the filename in it, the variable does not exist.
So if anyone can provide a sample code to get all info on albums/photos/thumbnail that would be awesome. Or just getting the filename would be a good help.
Here is the code I have tried so far:
-(void)awakeFromNib{
NSMutableArray *allPhotos = self.getAllPhotos;
for (int x = 0; x < allPhotos.count; x ++)
{
PHAsset *photo = [self getPhotoAtIndex:x];
PHAssetSourceType source = photo.sourceType;
NSString *id = photo.localIdentifier;
NSString *description = photo.description;
NSUInteger height = photo.pixelHeight;
NSUInteger width = photo.pixelWidth;
NSLog(#"Test photo info");
}
}
-(PHAsset*) getPhotoAtIndex:(NSInteger) index
{
return [self.getAllPhotos objectAtIndex:index];
}
-(NSMutableArray *) getAllPhotos
{
NSMutableArray *photos = [[NSMutableArray alloc] init];
PHFetchOptions *allPhotosOptions = [[PHFetchOptions alloc] init];
allPhotosOptions.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"creationDate" ascending:YES]];
PHFetchResult *allPhotos = [PHAsset fetchAssetsWithOptions:allPhotosOptions];
PHFetchResult *fetchResult = #[allPhotos][0];
for (int x = 0; x < fetchResult.count; x ++) {
PHAsset *asset = fetchResult[x];
photos[x] = asset;
}
return photos;
}
As you can see, I can get the image height and width, its id, but cannot get the url to it.
I have found a way to get the url of my photo.
-(void)getImageURL:(PHAsset*) asset
{
PHContentEditingInputRequestOptions *options = [[PHContentEditingInputRequestOptions alloc] init];
[options setCanHandleAdjustmentData:^BOOL(PHAdjustmentData *adjustmentData) {
return [adjustmentData.formatIdentifier isEqualToString:AdjustmentFormatIdentifier] && [adjustmentData.formatVersion isEqualToString:#"1.0"];
}];
[asset requestContentEditingInputWithOptions:options completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info)
{
NSURL* url = contentEditingInput.fullSizeImageURL;
}];
}
Filenames in the Photos library are an implementation detail and subject to change. There are various private API for discovering them (or ways to use valueForKey or other public introspection APIs to find where they're hidden), they aren't something to be relied upon. In particular, an asset that's been edited is likely to have a different filename than the original.
What do you need a filename/URL for? If you're just uniquely identifying the asset across launches of your app, use localIdentifier. If you're showing it to the user... why? Something like IMG_0234.jpg vs IMG_5672.jpg has little meaning to the average user.
To fetch the assets in a specific album, use fetchAssetsInAssetCollection:options:. To fetch the album(s) containing a specific asset, use fetchAssetCollectionsContainingAsset:withType:options:. To discover the list(s) of albums, use other APIs on PHAssetCollection and its superclass PHCollection.

Objective-C: Comparing user input with object's instance variable

I have been learning Objective-C for a while, and I decided to try and take on a little bigger project without any real "guidelines" as in the learning books but now I have got stuck.
What I'm trying to do is helping a friend digitalising a few documents he have, by creating a searchable commandline-tool for these documents.
I think I have gotten pretty far, I have created a custom class for documents with three variable; name of the author, number of the article and the path to the file on my computer (which I of course will change to the place he have the documents stored on his computer). I have then created two example documents with all the variables filled in. Since the documents have two properties, numbers and name of the author, the user may search for one of these properties. I therefore separated the input of the user to either be a string or a int (with help of a stack overflow post: How to determine if the first character of a NSString is a letter ) I also created an array with the 'author'-variable's of the different documents.
This is were I have hit a bump: I want to run through the array of the 'author' and if the author's name match with what the user have put in, it will open the document which is at the path given at 'UrlToDoc'. The problem is, the instance variable 'UrlToDoc' is not "connected" to the 'leadAuthor'-variable in some kind of way (as far as I can tell). My question is therefore, how do I, after I have found a match in in the array with what the user written, describe the 'UrlToDoc'-variable for that specific object? (If the user typed in jamesson, for instance, how do I describe the UrlToDoc variable with the value: /Users/pinkRobot435/Desktop/test1.pdf )
Also, if the user writes in a number, the else-statement on the bottom (which would do the same thing) should be used. I haven't written it yet though, but I guess the code for it would be pretty much the same, when describing the 'UrlToDoc'-variable.
Here is my code:
My custom class SMADoc:
SMADoc.h
#import <Foundation/Foundation.h>
#interface SMADoc : NSObject
//Two strings, and a pathway to the documnt, with the purpose of describing the document
#property (nonatomic) int number;
#property (nonatomic) NSString *authour;
#property (nonatomic) NSString *urlToDoc;
#end
SMADoc.m
#import "SMADoc.h"
#implementation SMADoc
#end
main.m
#import <Foundation/Foundation.h>
#import "SMADoc.h"
#include <readline/readline.h>
#include <stdlib.h>
int main(int argc, const char * argv[]) {
#autoreleasepool {
SMADoc *one = [[SMADoc alloc] init];
[one setnumber:123];
[one setauthour:#"jamesson"];
[one setUrlToDoc:#"/Users/pinkRobot435/Desktop/test1.pdf"];
SMADoc *two = [[SMADoc alloc] init];
[two setnumber:124];
[two setauthour:#"marc"];
[two setUrlToDoc:#"/Users/pinkRobot435/Desktop/test2.pdf"];
NSMutableArray *authours = [[NSMutableArray alloc] initWithObjects: [one authour], [two authour], nil];
NSLog(#"Enter what you want to search for: ");
const char *searchC = readline(NULL);
NSString *searchOrg = [NSString stringWithUTF8String:searchC];
NSString *search = [searchOrg lowercaseString];
NSRange first = [search rangeOfComposedCharacterSequenceAtIndex:0];
NSRange match = [search rangeOfCharacterFromSet:[NSCharacterSet letterCharacterSet] options:0 range:first];
if (match.location != NSNotFound) {
//The string starts with a letter and the array of authour names should be searched through
for (SMADoc *nSearch in authours) {
if ([search isEqualToString:nSearch]) {
**//Open the file that is represented by UrlToDoc for that specific object**
} else {
NSLog(#"The authour was not found, please try again");
}
}
} else {
//The string starts with a number and should be converted to an int and then the array of numbers (which I have not yet created) should be searched through
int number = atoi(searchC);
}
}
return 0;
}
Thanks in avance!
Instead of your authours array, create an array of SMADoc objects.
Then, in your loop, each object from the array will have an authour or number you can match. When the right one is found, you can just pick the urlToDoc out of the same object.
Currently, you're calling each object in the array a SMADoc * when you examine it, but that's wrong. You created an array of NSString * (and you're comparing it as a string correctly) but what you need there is a real SMADoc *.

Sync Contacts disabling facebook contacts in ios 6

I have a problem.
I'm making an app in ios 6 that get contacts from my address book but if i have enabled the contacts option with facebook get all my contacts from my address book and from facebook and i would like if there is possible with code dont get facebook contacts.
Only solutions that i thougth is or merge contacts with the same name or delete the contacts that have an email with #facebook.com.
Other solution?
Checking for a #facebook.com email address is not reliable. Users can choose to not publish that and non-facebook address book entries could have that as their email address.
There is a special field in the address book called ExternalRepresentation that seems to carry some extra info about synced from facebook contacts. The first part of this always seems to be the same.
WARNING: This may not work all the time and probably will break someday in the future. This is undocumented.
static NSData *facebookExtRepPrefix = [NSData dataWithBytes:"bplist00\xd4\x01\x02\x03" length:12];
#define kABPersonExternalRepresentationProperty 39
then
NSData *extRep = (__bridge NSData *)ABRecordCopyValue(theRecord, kABPersonExternalRepresentationProperty);
BOOL isFacebook = [[extRep subdataWithRange:NSMakeRange(0, facebookExtRepPrefix.length)] isEqualToData:facebookExtRepPrefix];
you can then read the kABPersonPersonLinkProperty (#42) - that value will be the same on the native contact that is linked to it.
Using the default source i.e ABAddressBookCopyDefaultSource in ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering gave me the phone contacts (not Facebook contacts).
Rather than taking the count of people in the address book as ABAddressBookGetPersonCount, I used the allPeople array (from above) to get the number of people.
if (accessGranted) {
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByFirstName);
CFIndex nPeople = CFArrayGetCount(allPeople);//Not ABAddressBookGetPersonCount(addressBook) as that returns all contacts, Facebook included;
items = [NSMutableArray arrayWithCapacity:nPeople];
for (int i = 0; i < MIN(nPeople, 20); i++)
{
ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
//Do something with this person
}
}
Ref: Get all contacts: https://stackoverflow.com/a/17976915/1349663

Getting subarray of Address Book

I'm trying to get just the first 100 of contacts from the Address Book.
What I've done is getting all the contacts and then tried to get only the first 100. For some reason that doesn't work (code below).
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef allContacts = ABAddressBookCopyArrayOfAllPeople(addressBook);
NSRange theRange;
theRange.location = 0;
theRange.length = 100;
CFArrayRef allContactsNew = (CFArrayRef)[(NSMutableArray *)allContacts subarrayWithRange:theRange];//This gets an error
Would appreciate help here. Also, If you know any other method to get only the first 100 or so directly from the Address Book that could be very helpful.
It worked correctly when I made these changes:
theRange.length = MIN(100, CFArrayGetCount(allContacts)); //avoid array out of bounds errors
CFArrayRef allContactsNew = CFBridgingRetain([(NSArray *)CFBridgingRelease(allContacts) subarrayWithRange:theRange]); //Add CFBridging functions recommended by Xcode

Cannot Get Data from Custom Class

I looked around for an answer to this because it seems simple but I could not seem to find something that suffised. I am trying to test a program I have with fake data. I created a StudentData class that possesses a attributes for a student and also has an array to hold them all.
When another class needs them they call a getStudent method (which is the only public part of this class thus far) and sends an ID number to get the name of that student back.
My problem is that I cannot figure out how to parse through the student array to match the student ID numbers with the one that was passed in. Holding the same problem, I cannot figure out how to pull the name out of a student object either.
Here is my code so far:
// StudentData.m
#import "StudentData.h"
#interface StudentData() {
NSString *ID;
NSString *firstName;
}
#property (nonatomic, strong) NSMutableArray *studentArray;
#end
#implementation StudentData
#synthesize studentArray = _studentArray;
- (NSMutableArray *)studentArray {
if(!_studentArray) _studentArray = [[NSMutableArray alloc] init];
return _studentArray;
}
- (void)awakeFromNib {
NSArray *idA = [NSArray arrayWithObjects:#"111", #"685", nil];
NSArray *fnA = [NSArray arrayWithObjects:#"Mark", #"Sam", nil];
for(int i = 0; i < idA.count; i++) {
StudentData *tempCurrentStudent = [[StudentData alloc] init];
ID = [idA objectAtIndex:i];
firstName = [fnA objectAtIndex:i];
[self.studentArray addObject:tempCurrentStudent];
}
}
- (NSString *)getStudentsFirstName:(NSString *)studentID {
NSString *firstName;
for(int i = 0; i < self.studentArray.count; i++) {
if([studentID isEqualToString:[[self.studentArray objectAtIndex:i] self.firstName]]) { // ERROR
fN = [[self.studentArray objectAtIndex:i] self.firstName]; // ERROR
}
}
return firstName;
}
#end
The Error I keep getting is: Expect ']' and the error is pointing to the "self.firstName" lines.
If I use "[self.studentArray objectAtIndex:i].firstName;" I get the error: Property 'firstName' not found on object of type 'id' I even get this error if I make "firstName" a property (both local or public). This makes sense because the array is technically filled with 'id' types. I also know that unlike java I cannot use generics or anything like that.
Any help would be much appreciated and if it needs clarification please let me know! By the way this is for an ipod/ipad app if that helps at all.
Thanks!
Two things :
You're having a name conflict here. You are having a local variable called firstName and the parameter passed to your problem function has the same name.
firstNameis NOT a property unless you define it as one. In this case it's just a normal local variabel. Means that you can't access it using self.firstName but just by firstName. That's one of the reason the coding guidelines say that you should name local variables starting with an underscore ( as you are already doing in the studentArrayproperty). This way you can distinguish if it is a local variable or a property.
Best,
Flo