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í.
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 :
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 )
@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 ):
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:
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ě:
#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
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:
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
Připravíme si funkci, která nám bude vracet aktální pozici pro výpis řádku s hodnotou:
/**
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ů:
/**
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:
- (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:
/**
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:
Pro ošetření tlačítka Cancel dopíšeme funkci peoplePickerNavigationControllerDidCancel, která se v tomto případě bude volat:
/**
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
/**
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:
Nejjednodušší je zjištění jména a příjmení, to můžeme udělat přímo:
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 :
ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);
Dopíšeme si funkci, která nám z ABMultiValueRef vrátí pouze jednu hodnotu:
/**
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:
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ů
[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ů:
/**
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):
[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
/**
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;
}
Ještě jednou si uvedeme celou implementaci SimpleAdressBookViewController:
//
// 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ýsledná aplikace tedy umožní přes tlačítko vybrat konktaty ze seznamu kontaktů a tyto kontakty zobrazit, jak bylo uvedeno na začátku: