Az adatbázis a /private/var/root/Library/AddressBook/AddressBook.sqlitedb file-ban található. Zárójelben említem meg, hogy a /private/var/root/Library könyvtárban további adatbázisokat fedezhetünk fel. Talán későbbi post(ok)ban megkísérlem feltárni a szerkezetüket. Egyelőre maradjunk az alapoknál.
A UITextView mintegy log írásra használandó; kiegészítettem az osztályt egy metódussal.
- (void) appendLogMessage: (NSString *) message
{
[tvMessage setText:[[tvMessage text] stringByAppendingString: message]];
}
Ez csupán a meglevő szöveg végéhez csatolja az új üzenetet (sortörésekre magunknak kell ügyelnünk).{
[tvMessage setText:[[tvMessage text] stringByAppendingString: message]];
}
Mielőtt elfelejteném, importok között meg kell említeni az sqlite3 header-jét is.
#import <sqlite3.h>
Ezen túl a make file-ban is meg kell ejteni a szükséges kiegészítést. LDFLAGS=-lobjc -framework CoreFoundation -framework Foundation -framework UIKit /usr/lib/libsqlite3.0.dylib
A UI inicializálása után bele is vágunk az adatbázis megnyitásába és ha sikerült, lefuttatjuk az első lekérdezést és bezárjuk dolgunk végeztével. sqlite3* db;
char* errmsg;
int retval = sqlite3_open([@"/private/var/root/Library/AddressBook/AddressBook.sqlitedb" UTF8String], &db);
if (retval == SQLITE_OK){
retval = sqlite3_exec(db,[@"select First, Last from ABPerson" UTF8String],&sqlite3_cb,nil,&errmsg);
sqlite3_close(db);
}else{
[self appendLogMessage: [NSString stringWithCString: sqlite3_errmsg(db)]];
}
Tudom, a hibakezelést lehetne még cizellálni, de példának és bemutatni megteszi. Az sqlite3_open metódus UTF8-as karakterláncot vár és szerencsénkre az NSString osztálynak van konverziós metódusa, ezt használjuk. Ha nem járunk sikerrel, akkor kiírjuk a hibaüzenetet, hátha okosabbak leszünk tőle. Sikeres megnyitás után indítjuk a lekérdezést (minden tételből a kereszt és vezetéknevet olvassuk). Érdekessége az sqlite3_exec függvénynek, hogy második paraméterként egy úgynevezett callback típusú függvény címét kell átadnunk. Ez a függvény nem Object-C stílusú, hanem standard C. Egy ideig gondolkoztam, hogy vajon ezt hogyan kellene megoldani és végül a következő függvényt definiáltam. char* errmsg;
int retval = sqlite3_open([@"/private/var/root/Library/AddressBook/AddressBook.sqlitedb" UTF8String], &db);
if (retval == SQLITE_OK){
retval = sqlite3_exec(db,[@"select First, Last from ABPerson" UTF8String],&sqlite3_cb,nil,&errmsg);
sqlite3_close(db);
}else{
[self appendLogMessage: [NSString stringWithCString: sqlite3_errmsg(db)]];
}
int sqlite3_cb(void* usrpar,int count,char** data, char** colnames)
{
NSString* firstname = data[0] == nil ? @"" : [NSString stringWithUTF8String:data[0]];
NSString* lastname = data[1] == nil ? @"" : [NSString stringWithUTF8String:data[1]];
[tvMessage setText:[[tvMessage text] stringByAppendingFormat: @"%@ %@\n",lastname,firstname]];
return 0;
}
Fontos megjegyezni, hogy a callback függvény az eredményhalmaz minden sorára egyenként hívódik meg. A függvény paraméterként egy saját, bármilyen értéket ad áz első helyen (ez a mi esetünkben nil, ezt adtam meg az sqlite3_exec függvényhívásnál). Második paraméter az eredmény oszlopainak száma.Harmadik paraméter az értékek tömbje és végül az oszlopok nevét is megkapjuk.{
NSString* firstname = data[0] == nil ? @"" : [NSString stringWithUTF8String:data[0]];
NSString* lastname = data[1] == nil ? @"" : [NSString stringWithUTF8String:data[1]];
[tvMessage setText:[[tvMessage text] stringByAppendingFormat: @"%@ %@\n",lastname,firstname]];
return 0;
}
Némi varázslat az UTF8-as karaktersor és nil érték körül és formázottan hozzákapcsolom a az eddigi log-hoz. Azt is észrevehetjük, hogy itt nem használtam az appendLogMessage függvényemet. Ennek prózai magyarázata, hogy sem self, sem this referenciával nem tudtam hivatkozni az aktuális példányra.