iPhone – Access to AdressBook
Vytvoříme si jednoduchou aplikaci, která bude umožňovat přístup k telefonnímu seznamu telefnu a dokáže z něj načíst informace o vybraných kontaktech.
Aplikace bude umožňovat vybrat několik kontaktů, pro jejich vybrání se využije aktuální seznam z telefonu, a vybrané hodnoty se zobrazí v tabulce v aplikaci.
Přístup k telefonnímu seznamu v iPhone není nic složitého. Využijeme přímo součást frameworku Cocoa AddressBook, která nám práci s telefonním seznamem telefonu velmi usnadní.
Vytvoření aplikace
Jako první si vytvoříme novou aplikaci, můžeme ji nazvat například SimpleAdressBook (i když se ve výsledku nejedná o adresář, ale spíše jenom o ukázu přístupu k adresáři).
Aplikaci vytvoříme jako standartní View-based application:
Vytvoření interface
Interface celé aplikace si vytvoříme například v Interface Builderu, kde tohle bude otázkou několika málo minut.
Nejprve si ovšem doplníme potřebné proměnné do hlavičkového souboru aplikace (v tomto případě to bude SimpleAdressBookViewController.h)
1 2 3 4 5 6 7 8 |
@interface SimpleAdressBookViewController : UIViewController { IBOutlet UIButton *addButton; IBOutlet UIView *myView; IBOutlet UILabel *countLabel; } -(IBAction)addContact; @end |
Vytvořili jsme si jedno tlačítko – UIButton (bude vyvolávat akci pro výběr kontaktu), jeden UILabel (bude soužit pouze jako informační hodnota) a jeden UIView, do kterého budeme hodnoty zapisovat.
K tlačítku samozřejmě vytvoříme IBAction – v tomto případě jsme ji nazvali addContact.
Design s navázanými hodnotami může vypadat například následně:
Navíc navážeme událost na tlačítko (použijeme Touch UP Inside):
AdressBook
Abychom mohli využívat AdressBook z Cocoa, musíme si jej přidat do projektu. To uděláme jednoudše přes tlačítko Get Info v Targets projektu (proklik přes naši aplikaci):
V levém dolním rohu vidíme tlačítko + přes které si do projektu přídáme:
- AdressBook.framework
- AdressBookUI.framework
V případě že jsou knihovny správně přídány do projektu, můžeme je includovat, to provedeme v hlavičkovém souboru SimpleAdressBookViewController.h, který bude vypadat následovně:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#import <UIKit/UIKit.h> //include adressbook #import <AddressBook/AddressBook.h> #import <AddressBookUI/AddressBookUI.h> @interface SimpleAdressBookViewController : UIViewController { IBOutlet UIButton *addButton; IBOutlet UIView *myView; IBOutlet UILabel *countLabel; } -(IBAction)addContact; @end |
Implementace
Nyní je vše připraveno a můžeme se pustit do implementace.
Do projektu si přídáme několik konstant, které budeme v průběhu běhu potřebovat:
1 2 3 4 5 |
int lineHeight = 20; //line height int lineStart = 100; //start line position int columnWidth = 100; //width first column int count = 0; //actual count of items int maxCount = 5; //maximum items in list |
- lineHeight – výška jednoho řádku pro výpis kontaktu
- lineStart – pozice prvního řádku ve výpisu
- columnWidth – výška řádku s výpisem kontaktu
- count – aktuální počet vybraných kontaktů
- maxCount – maximální počet vybraných kontaktů
Připravíme si funkci, která nám bude vracet aktální pozici pro výpis řádku s hodnotou:
1 2 3 4 5 6 |
/** Get actual line position **/ -(int) getActPosition{ return lineStart + (count*lineHeight); } |
Funkce vrací pozici, která se vypočítá podle aktuálního počtu řádek.
Dále si připravíme funkci, která upraví popisek v UILabelu a zapíše sem aktální počet vybraných kontaktů:
1 2 3 4 5 6 |
/** Update count label **/ -(void)updateCountLabel{ [countLabel setText:[NSString stringWithFormat:@"%d/%d", count, maxCount]]; } |
Funkci rovnou spustíme při načtení aplikace ve funkci viewDidLoad:
1 2 3 |
- (void)viewDidLoad { [self updateCountLabel]; } |
Konečně si můžeme dopsat událost addContact, která se bude spouštět při kliknutí na tlačítko:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/** IBAction: event to select a contact from the directory **/ -(IBAction)addContact{ if (count < maxCount) { ABPeoplePickerNavigationController *adressbook = [[ABPeoplePickerNavigationController alloc] init]; // place the delegate of the adressbook to the controll adressbook.peoplePickerDelegate = self; // showing the adressbook [self presentModalViewController:adressbook animated:YES]; // releasing [adressbook release]; } else { //show alert message UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"You can't add another contact" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; [alert release]; } } |
Funkce nejprve zkontroluje, zda počet vybraných kontaktů je menší než maximální množství, pokud ne, bude nás o tom informovat v podobě UIAlertu.
Pokud je vše vpořádku, inicializuje ABPeoplePickerNavigationController a zobrazí kontakty.
Na tomto místě máme přepnut screen do kontaktů telefonu – nyní mohou nastat dva případy:
- Uživatel klikne na konkakt a tím jej vybere
- Uživatel klikne na tlačítko Cancel
Pro ošetření tlačítka Cancel dopíšeme funkci peoplePickerNavigationControllerDidCancel, která se v tomto případě bude volat:
1 2 3 4 5 6 7 |
/** Event cancel **/ - (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker { //return control back to the main controller [self dismissModalViewControllerAnimated:YES]; } |
Funkce se vrátí zpět do načí aplikace a skryje adresář kontaktů
Druhá možnost, kdy uživatel vybere kontakt, je konečně ta, kterou očekáváme a pro kterou si přetížíme funkci peoplePickerNavigationController, jež se bude v tomto případě volat
1 2 3 4 5 |
/** peoplePickerNavigationController - containt selected adress from adress book **/ - (BOOL)peoplePickerNavigationController: (ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person { } |
Co nás nejvíce zajímá je vstupní proměnná person, ze které budeme zjišťovat všechny informace.
Pro naše potřeby budeme potřebovat zjistit:
- Jméno
- Příjmení
- Telefonní číslo
Nejjednodušší je zjištění jména a příjmení, to můžeme udělat přímo:
1 2 3 |
NSString *firstName, *lastName; firstName = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty); lastName = (NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty); |
V případě dalších hodnot, jako je telefon a email, musíme myslet na to, že jich může být v iPhone uloženo více než jedna hodnota, z proměnné person takto dostaneme hodnotu typu ABMultiValueRef:
1 |
ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty); |
Dopíšeme si funkci, která nám z ABMultiValueRef vrátí pouze jednu hodnotu:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/** return first exists item from multivalue **/ - (NSString *)getItemFromMultiValue: (ABMultiValueRef)emails{ //if count if ( ABMultiValueGetCount( emails ) ) { for ( int i=0;i < ABMultiValueGetCount(emails);i++ ) { //if exists value if ( ABMultiValueCopyValueAtIndex(emails, i) ){ return (NSString *)ABMultiValueCopyValueAtIndex(emails, i); } } } //return nil return @""; } |
Nyní můžeme v peoplePickerNavigationController volat:
1 2 3 4 5 6 |
NSString *email, *number; ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty); email = [self getItemFromMultiValue:emails]; ABMultiValueRef numbers = ABRecordCopyValue(person, kABPersonPhoneProperty); number = [self getItemFromMultiValue:numbers]; |
Pokud bude v kontaktu uložen email nebo telefonní číslo, uloží se nám do proměnné.
Tím máme zjištěny všechny potřebné hodnoty a můžeme se vrátit zpět z Konktatů
1 |
[self dismissModalViewControllerAnimated:YES]; |
V poslední části musíme kontakt vypsat do obrazovky, uděláme si na to funkci addColumn, která bude vytažené hodnoty vykreslovat do tří sloupců:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/** Add new label into view **/ -(void) addColumn:(int )column: (NSString *)label{ //calculate left padding int leftPadding = 10 + ((int)column * (int)columnWidth); //create new label UILabel *cLabel = [[UILabel alloc] initWithFrame:CGRectMake(leftPadding, [self getActPosition], columnWidth, lineHeight)]; //set label text [cLabel setText:label]; //set label aligment [cLabel setTextAlignment:UITextAlignmentLeft]; //set label font cLabel.font = [UIFont fontWithName:@"Helvetica" size: 10.0]; //actPrice.textColor = [UIColor grayColor]; [myView addSubview:cLabel]; [cLabel release]; } |
Vstupní parametry jsou číslo sloupce (indexovány od 0) a hodnota, kterou má na daný sloupec vypsat (doplníme do funkce peoplePickerNavigationController):
1 2 3 |
[self addColumn:0 : [NSString stringWithFormat:@"%@ %@", firstName, lastName] ]; [self addColumn:1 : [NSString stringWithFormat:@"%@", email] ]; [self addColumn:2 : [NSString stringWithFormat:@"%@", number] ]; |
Nakonec inkrementujeme hodnotu proměnné count a voláme funkci updateCountLabel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
/** peoplePickerNavigationController - containt selected adress from adress book **/ - (BOOL)peoplePickerNavigationController: (ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person { //create static variables NSString *firstName, *lastName, *email, *number; //get first name from adress book firstName = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty); //get last name from adress book lastName = (NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty); //get emails from adress book //emails are MultiValue!!!!!! ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty); //get email from MultiValue of emails email = [self getItemFromMultiValue:emails]; //get number - similar to emails ABMultiValueRef numbers = ABRecordCopyValue(person, kABPersonPhoneProperty); number = [self getItemFromMultiValue:numbers]; // remove the controller [self dismissModalViewControllerAnimated:YES]; //add values into view [self addColumn:0 : [NSString stringWithFormat:@"%@ %@", firstName, lastName] ]; [self addColumn:1 : [NSString stringWithFormat:@"%@", email] ]; [self addColumn:2 : [NSString stringWithFormat:@"%@", number] ]; //increment count count++; //update count label [self updateCountLabel]; return NO; } |
Shrnutí implementace
Ještě jednou si uvedeme celou implementaci SimpleAdressBookViewController:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
// // SimpleAdressBookViewController.m // SimpleAdressBook // // Created by jiri Zachar on 8/10/11. // Copyright 2011 Jiri Zachar. All rights reserved. // #import "SimpleAdressBookViewController.h" @implementation SimpleAdressBookViewController int lineHeight = 20; //line height int lineStart = 100; //start line position int columnWidth = 100; //width first column int count = 0; //actual count of items int maxCount = 5; //maximum items in list /** Get actual line position **/ -(int) getActPosition{ return lineStart + (count*lineHeight); } /** Add new label into view **/ -(void) addColumn:(int )column: (NSString *)label{ //calculate left padding int leftPadding = 10 + ((int)column * (int)columnWidth); //create new label UILabel *cLabel = [[UILabel alloc] initWithFrame:CGRectMake(leftPadding, [self getActPosition], columnWidth, lineHeight)]; //set label text [cLabel setText:label]; //set label aligment [cLabel setTextAlignment:UITextAlignmentLeft]; //set label font cLabel.font = [UIFont fontWithName:@"Helvetica" size: 10.0]; //actPrice.textColor = [UIColor grayColor]; [myView addSubview:cLabel]; [cLabel release]; } /** IBAction: event to select a contact from the directory **/ -(IBAction)addContact{ if (count < maxCount) { ABPeoplePickerNavigationController *adressbook = [[ABPeoplePickerNavigationController alloc] init]; // place the delegate of the adressbook to the controll adressbook.peoplePickerDelegate = self; // showing the adressbook [self presentModalViewController:adressbook animated:YES]; // releasing [adressbook release]; } else { //show alert message UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"You can't add another contact" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; [alert release]; } } /** Event cancel **/ - (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker { //return control back to the main controller [self dismissModalViewControllerAnimated:YES]; } /** return first exists item from multivalue **/ - (NSString *)getItemFromMultiValue: (ABMultiValueRef)emails{ //if count if ( ABMultiValueGetCount( emails ) ) { for ( int i=0;i < ABMultiValueGetCount(emails);i++ ) { //if exists value if ( ABMultiValueCopyValueAtIndex(emails, i) ){ return (NSString *)ABMultiValueCopyValueAtIndex(emails, i); } } } //return nil return @""; } /** Update count label **/ -(void)updateCountLabel{ [countLabel setText:[NSString stringWithFormat:@"%d/%d", count, maxCount]]; } /** peoplePickerNavigationController - containt selected adress from adress book **/ - (BOOL)peoplePickerNavigationController: (ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person { //create static variables NSString *firstName, *lastName, *email, *number; //get first name from adress book firstName = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty); //get last name from adress book lastName = (NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty); //get emails from adress book //emails are MultiValue!!!!!! ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty); //get email from MultiValue of emails email = [self getItemFromMultiValue:emails]; //get number - similar to emails ABMultiValueRef numbers = ABRecordCopyValue(person, kABPersonPhoneProperty); number = [self getItemFromMultiValue:numbers]; // remove the controller [self dismissModalViewControllerAnimated:YES]; //add values into view [self addColumn:0 : [NSString stringWithFormat:@"%@ %@", firstName, lastName] ]; [self addColumn:1 : [NSString stringWithFormat:@"%@", email] ]; [self addColumn:2 : [NSString stringWithFormat:@"%@", number] ]; //increment count count++; //update count label [self updateCountLabel]; return NO; } - (void)didReceiveMemoryWarning { // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; // Release any cached data, images, etc that aren't in use. } - (void)viewDidUnload { } - (void)viewDidLoad { [self updateCountLabel]; } - (void)dealloc { [super dealloc]; } @end |
Výsledek
Výsledná aplikace tedy umožní přes tlačítko vybrat konktaty ze seznamu kontaktů a tyto kontakty zobrazit, jak bylo uvedeno na začátku: