<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Fasty&#039;s Coding Blog</title>
	<atom:link href="http://www.fasty.de/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.fasty.de</link>
	<description>Meine Coding Knowledge-Base</description>
	<lastBuildDate>Tue, 28 Feb 2012 12:49:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>CoreData-Tutorial Teil 2: Verwalten der Anreden</title>
		<link>http://www.fasty.de/2012/01/coredata-tutorial-teil-2-verwalten-der-anreden/</link>
		<comments>http://www.fasty.de/2012/01/coredata-tutorial-teil-2-verwalten-der-anreden/#comments</comments>
		<pubDate>Sun, 29 Jan 2012 13:30:32 +0000</pubDate>
		<dc:creator>Fasty</dc:creator>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[CoreData]]></category>

		<guid isPermaLink="false">http://www.fasty.de/?p=314</guid>
		<description><![CDATA[Im ersten Teil der Tutorial-Serie haben wir den Grund-Aufbau der App vorgenommen, nun beschreibe ich wie das Programm erweitert wird um die Anreden zu verwalten. Hier werden wir auch zum ersten mal Daten in CoreData lesen und schreiben. Erstellen der &#8230; <a href="http://www.fasty.de/2012/01/coredata-tutorial-teil-2-verwalten-der-anreden/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Im ersten Teil der Tutorial-Serie haben wir den Grund-Aufbau der App vorgenommen, nun beschreibe ich wie das Programm erweitert wird um die Anreden zu verwalten. Hier werden wir auch zum ersten mal Daten in CoreData lesen und schreiben.</p>
<p><strong>Erstellen der Listen-Ansicht für Anreden</strong></p>
<p>Wir erstellen nun einfach eine neue Subklasse von &#8220;UITableViewController&#8221; namens &#8220;AnredenListeViewController&#8221;. Hier werden später die Anreden verwaltet.</p>
<p>Zunächst erweitern wir den HauptMenuViewController.m dahingehend dass bei einem Klick auf &#8220;Anreden&#8221; der &#8220;AnredenListeViewController&#8221; geladen wird:</p>
<pre class="brush: objc; title: ; notranslate">#import &quot;AnredenListeViewController.h&quot;

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == 1) {
        AnredenListeViewController *alvc = [[AnredenListeViewController alloc] initWithStyle:UITableViewStylePlain];
        [self.navigationController pushViewController:alvc animated:YES];
    }
}</pre>
<p>Wenn man das Programm startet kann man im Hauptmenü auf &#8220;Anreden&#8221; klicken und landet in einer leeren Liste.</p>
<p><strong>AnredenListeViewController.h erweitern</strong></p>
<p>Wir erweitern nun mal den Listen-Controller für Anreden im Header-File (AnredenListeViewController.h) und fügen einige Variablen und Methoden hinzu:</p>
<pre class="brush: objc; title: ; notranslate">@interface AnredenListeViewController : UITableViewController &lt;UIAlertViewDelegate&gt;

@property (nonatomic, retain) NSArray *anreden;

- (void)anredenLaden;
- (void)anredeHinzufuegen;
- (void)anredeLoeschen;

@end</pre>
<ul>
<li>In dem Array &#8220;anreden&#8221; werden alle Anreden aus der Datenbank/CoreData gespeichert.</li>
<li>Die Methode &#8220;anredenLaden&#8221; wird zuständig sein um die Anreden aus CoreData in das Array &#8220;anreden&#8221; zu laden</li>
<li>Die Methode &#8220;anredeHinzufuegen&#8221; wird aufgerufen wenn man auf einen Button für das Hinzufügen von Anreden klickt</li>
<li>Die Methode &#8220;anredeLoeschen&#8221; wird aufgerufen wenn auf den &#8220;Löschen&#8221; Button geklickt wird. Die Tabelle schaltet sich dann in den Modus zum Löschen von Einträgen</li>
</ul>
<p><strong>Button für das Hinzufügen und Löschen einfügen</strong></p>
<p>In dem ViewController sollen obren rechts zwei Button erscheinen. Einer zum Löschen und einer zum Hinzufügen von Anreden. Wir erweitern hierfür den AnredenListeViewController.m:</p>
<pre class="brush: objc; title: ; notranslate">#import &quot;AppDelegate.h&quot;

@implementation AnredenListeViewController

@synthesize anreden;

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        self.anreden = [[NSMutableArray alloc] init];
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Titel setzen
    self.title = @&quot;Anreden&quot;;

    UIBarButtonItem *loeschButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemTrash
                                                                                  target:self
                                                                                  action:@selector(anredeLoeschen)];

    UIBarButtonItem *hinzufButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
                                                                                  target:self
                                                                                  action:@selector(anredeHinzufuegen)];

    self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:loeschButton, hinzufButton, nil];
}</pre>
<p>Oben rechts erscheinen nun die Buttons mit dem &#8220;Löschen&#8221; und &#8220;Hinzufügen&#8221; Symbol. Klickt man auf &#8220;Hinzufügen&#8221; wird folgende Methode aufgerufen:</p>
<pre class="brush: objc; title: ; notranslate">- (void)anredeHinzufuegen
{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@&quot;Neue Anrede&quot;
                                                    message:@&quot;Wie lautet die neue Anrede ?&quot;
                                                   delegate:self
                                          cancelButtonTitle:@&quot;Abbruch&quot;
                                          otherButtonTitles:@&quot;OK&quot;, nil];
    alert.alertViewStyle = UIAlertViewStylePlainTextInput;
    [alert show];
}</pre>
<p>In dieser Methode wird einach nur ein AlertView mit einem Text-Eingabefeld angezeigt. Wird dies bestätigt wird folgende Methode aufgerufen:</p>
<pre class="brush: objc; title: ; notranslate">#pragma mark - UIAlertView Delegate Methoden

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex != [alertView cancelButtonIndex]) {
        NSString *neueAnredeText = [[alertView textFieldAtIndex:0] text];
        if ([neueAnredeText length] &gt; 0) {
            // Nun kommt der erste Kontakt mit CoreData <img src='http://www.fasty.de/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> 

            // Context aus dem AppDelegate holen
            AppDelegate *delegate = [UIApplication sharedApplication].delegate;
            NSManagedObjectContext *context = delegate.managedObjectContext;

            // Neues Managed Objekt erstellen
            NSManagedObject *neueAnrede = [NSEntityDescription insertNewObjectForEntityForName:@&quot;Anrede&quot;
                                                                        inManagedObjectContext:context];

            // Wert setzen
            [neueAnrede setValue:neueAnredeText forKey:@&quot;name&quot;];

            // Speichern
            NSError *error;
            if (![context save:&amp;error])
            {
                NSLog(@&quot;Konnte nicht speichern: %@&quot;, [error localizedDescription]);
            }
            else
            {
                [self anredenLaden];
                [self.tableView reloadData];
            }
        }
    }
}</pre>
<p>Wuhuuu, hier nun endlich Action mit CoreData! Nacheinander wird folgendes getan:</p>
<ul>
<li>Wir holen uns den CoreData &#8220;Kontext&#8221; aus dem AppDelegate. Dieser Kontext ist für alle Aktionen wie Laden/Speichern zuständig. Diese Programmzeile wird uns noch öfters begegnen.</li>
<li>Danach wird ein neues Objekt &#8220;NSManagedObject&#8221; erzeugt mit der &#8220;Schablone&#8221; namens &#8220;Anrede&#8221; welches wir durch den grafischen CoreData-Model-Editor definiert haben</li>
<li>Dann wird der Wert/Attribut &#8220;name&#8221; gesetzt mit dem Inhalt des Textfeldes aus dem AlertView</li>
<li>Mittels [context save:&#038;error] wird dann die neue Anrede im CoreData-Kontext gespechert</li>
</ul>
<p>Zuguterletzt werden wieder alle Anreden neu geladen, aber diese Methode haben wir noch nicht geschrieben.</p>
<p><strong>Laden der Anreden</strong></p>
<p>In dieser Methode werden alle Anreden von CoreData in das Array &#8220;anreden&#8221; geladen:</p>
<pre class="brush: objc; title: ; notranslate">-(void)anredenLaden
{
    // Laden der Anreden von Core Data
    // Zuerst Context holen
    AppDelegate *delegate = [UIApplication sharedApplication].delegate;
    NSManagedObjectContext *context = delegate.managedObjectContext;

    // Wir erstellen ein FetchRequest
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    // Dann holen wir uns die Beschreibung für eine Anrede
    NSEntityDescription *anredeEntity = [NSEntityDescription entityForName:@&quot;Anrede&quot;
                                                    inManagedObjectContext:context];

    // Setzen die Entity für den FetchRequest
    fetchRequest.entity = anredeEntity;

    // FetchRequest &quot;absenden&quot;
    NSError *error;
    self.anreden = [context executeFetchRequest:fetchRequest error:&amp;error];
}</pre>
<ul>
<li>Wir holen uns als erstes wieder den Kontext</li>
<li>Dann erstellen wir uns einen FetchRequest. Dieses Objekt ist zuständig um Objekte von CoreData zu laden</li>
<li>Wir erstellen die &#8220;NSEntityDescription&#8221; und setzen diese im FetchRequest. Das bedeutet dass unser FetchRequest Entitäten vom Typ &#8220;Anrede&#8221; holen soll.</li>
<li>Zuguterletzt wird der FetchRequest &#8220;abgeschickt&#8221; und das Resultat ist ein Array von NSManagedObjects welche in self.anreden gespeichert wird</li>
</ul>
<p>Nun haben wir den Code um alle Anreden aus CoreData in ein Array zu laden, aber angezeigt wird noch nix. Wir erweitern nun den Code mit den UITableViewDataSource-Methoden.</p>
<p><strong>Methoden zur Anzeige von Anreden (UITableViewDataSource)</strong></p>
<p>Wir erweitern den Code wie folgt:</p>
<pre class="brush: objc; title: ; notranslate">#pragma mark - Table view data source

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [anreden count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @&quot;Cell&quot;;

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    // Configure the cell...
    NSManagedObject *anredeObjekt = [self.anreden objectAtIndex:indexPath.row];
    cell.textLabel.text = [anredeObjekt valueForKey:@&quot;name&quot;];

    return cell;
}</pre>
<p>Hier sollte nicht viel Neues zu sehen sein. In tableView:numberOfRowsInSection: wird die Anzahl der Anreden zurückgegeben. So viele Zeilen sollen angezeigt werden.</p>
<p>In tableView:cellForRowAtIndexPath: wird die Anrede (NSManagedObject) aus self.anreden herausgeholt und der Name in das TextLabel der Zelle geschrieben.</p>
<p><strong>Löschen von Anreden</strong></p>
<p>Bisher hat unser &#8220;Löschen&#8221; Button noch keine Funktion. Beim Klick auf diesen wird ja nur die bisher leere Methode &#8220;anredeLoeschen&#8221; aufgerufen. Diese bekommt ein wenig &#8220;Leben&#8221;:</p>
<pre class="brush: objc; title: ; notranslate">- (void)anredeLoeschen
{
    self.tableView.editing = !self.tableView.editing;
}</pre>
<p>Gaaaaanz einfach: es wird lediglich der &#8220;Editing&#8221; Modus ein/ausgeschaltet. Ihr könnt das mal ausprobieren: man sieht dann einfach nur die Steuerung zum Löschen von Einträgen (roter Punkt vorne, wenn man darauf klickt das &#8220;Lösch&#8221;-Feld rechts).</p>
<p>Klickt man jedoch auf Löschen passiert noch nix. Hierfür muss man folgende Methode erweitern:</p>
<pre class="brush: objc; title: ; notranslate">- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {

        // Das  zu löschende Objekt holen
        NSManagedObject *loeschObjekt = [self.anreden objectAtIndex:indexPath.row];

        // Das Managed Objekt löschen, zuerst aber wieder den Context holen
        AppDelegate *delegate = [UIApplication sharedApplication].delegate;
        NSManagedObjectContext *context = delegate.managedObjectContext;

        // Objekt aus Context löschen
        [context deleteObject:loeschObjekt];

        // In Datenbank speichern
        NSError *error;
        if (![context save:&amp;error])
        {
            NSLog(@&quot;Konnte nicht löschen: %@&quot;, [error localizedDescription]);
        }
        else
        {
            [self anredenLaden];
            [self.tableView reloadData];
        }
    }
}</pre>
<ul>
<li>Zuerst holen wir das Objekt welches zum Löschen markiert wurde</li>
<li>Dann wird wieder der &#8220;Kontext&#8221; geholt</li>
<li>Mittels [context deleteObject:loeschObjekt] wird dieses Objekt aus dem Kontext gelöscht</li>
<li>Und zuguterletzt speichern wird dies mit [context save:&#038;error] im Kontext</li>
</ul>
<p><strong>Zusammenfassung</strong></p>
<p>Das war es zum zweiten Teil unseres Tutorials. Wir haben bis jetzt: Daten aus CoreData gelesen, neue hinzugefügt und Daten wieder heraus gelöscht.</p>
<p>Bisher haben wir nur ganz einfach Daten bearbeitet, um genau zu sein nur eine Entität namens &#8220;Anrede&#8221; welche auch nur ein &#8220;Attribut&#8221; namens &#8220;name&#8221; vom Typ String.</p>
<p>Im nächsten Teil gehen wir an komplexere Masken über zum Bearbeiten von Kontakten.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fasty.de/2012/01/coredata-tutorial-teil-2-verwalten-der-anreden/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>CoreData-Tutorial Teil 1: Grund-Aufbau der App</title>
		<link>http://www.fasty.de/2012/01/coredata-tutorial-teil-1-grund-aufbau-der-app/</link>
		<comments>http://www.fasty.de/2012/01/coredata-tutorial-teil-1-grund-aufbau-der-app/#comments</comments>
		<pubDate>Sun, 29 Jan 2012 13:22:37 +0000</pubDate>
		<dc:creator>Fasty</dc:creator>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[CoreData]]></category>

		<guid isPermaLink="false">http://www.fasty.de/?p=312</guid>
		<description><![CDATA[So&#8230; seit langem mal wieder ein Tutorial. Diesmal geht es um das Thema &#8220;CoreData&#8221;. Wenn Ihr Euch auch für dieses Thema interessiert könnte dieses Tutorial interessant sein. In der folgenden Tutorial-Serie versuche ich eine kleine App aufzubauen mit der man &#8230; <a href="http://www.fasty.de/2012/01/coredata-tutorial-teil-1-grund-aufbau-der-app/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>So&#8230; seit langem mal wieder ein Tutorial. Diesmal geht es um das Thema &#8220;CoreData&#8221;. Wenn Ihr Euch auch für dieses Thema interessiert könnte dieses Tutorial interessant sein.</p>
<p>In der folgenden Tutorial-Serie versuche ich eine kleine App aufzubauen mit der man &#8220;Kontak-Daten&#8221; verwalten kann. Eine einfache Datenbank mit Kontakten welche aus Vorname, Nachname, E-Mail-Adresse, Geburtstag und einer Anrede besteht. In jedem Teil wird die App etwas erweitert, ich hoffe so erleichtere ich den schrittweisen Einstieg in die Materie <img src='http://www.fasty.de/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Los geht&#8217;s, wir starten XCode und erstellen ein Projekt mit dem Template &#8220;Master Detail Application&#8221;. Wir nennen das Projekt &#8220;CoreDataAdressen&#8221; und haken unten an &#8220;Use CoreData&#8221; und &#8220;Use Automatic Reference Counting&#8221;:</p>
<p><a href="http://www.fasty.de/wp-content/uploads/2012/01/cd-1-projekt-optionen.jpg"><img src="http://www.fasty.de/wp-content/uploads/2012/01/cd-1-projekt-optionen.jpg" alt="" title="CodeData Projekt Optionen" width="406" height="363" class="alignleft size-full wp-image-321" /></a></p>
<div style="clear: both;"></div>
<p>Als nächstes den &#8220;MasterViewController&#8221; und &#8220;DetailViewController&#8221; komplett löschen, wir wollen &#8220;blankes&#8221; Projekt haben. Durch das Template wurden im AppDelegate aber alle CoreData-relevanten Infos erstellt die wir im späteren Verlauf benötigen um auf die Daten zuzugreifen.</p>
<p><strong>Erstellen des Hauptmenüs</strong></p>
<p>Die erste Maske in unserem Projekt soll eine einfach TableView sein, in der man 2 Menüpunkte auswählen kann: &#8220;Kontakte&#8221; und &#8220;Anreden&#8221;. Wir erstellen also einen neuen ViewController als Unterklasse von &#8220;UITableViewController&#8221; (ohne XIB File) namens HauptMenuViewController:</p>
<p><a href="http://www.fasty.de/wp-content/uploads/2012/01/cd-2-hauptmenuviewcontroller.jpg"><img src="http://www.fasty.de/wp-content/uploads/2012/01/cd-2-hauptmenuviewcontroller.jpg" alt="" title="Erstellen des HauptMenuViewController" width="512" height="109" class="alignleft size-full wp-image-326" /></a></p>
<div style="clear: both;"></div>
<p>Das Projekt sollte bis jetzt ungefähr so aussehen:</p>
<p><a href="http://www.fasty.de/wp-content/uploads/2012/01/cd-3-projekt-so-far.jpg"><img src="http://www.fasty.de/wp-content/uploads/2012/01/cd-3-projekt-so-far.jpg" alt="" title="Das Projekt bis nun ..." width="249" height="196" class="alignleft size-full wp-image-327" /></a></p>
<div style="clear: both;"></div>
<p><strong>Änderung des AppDelegates</strong></p>
<p>Bisher noch nichts spannendes. Unser Template hat ja normalerweise vorgesehen dass der MasterViewController geladen wird. In unserem Projekt soll aber als erstes der &#8220;HauptMenuViewController&#8221; geladen werden. Im AppDelegate.m folgende Änderung vornehmen:</p>
<pre class="brush: objc; title: ; notranslate">#import &quot;HauptMenuViewController.h&quot;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.

    HauptMenuViewController *hauptmenu = [[HauptMenuViewController alloc] initWithStyle:UITableViewStylePlain];
    self.navigationController = [[UINavigationController alloc] initWithRootViewController:hauptmenu];
    self.window.rootViewController = self.navigationController;
    [self.window makeKeyAndVisible];
    return YES;
}</pre>
<p><strong>Menüpunkte in HauptMenuViewController einfügen</strong></p>
<p>Nun wird beim Start der &#8220;HauptMenuViewController&#8221; geladen, welcher aber im Moment nur ein leerer TableViewController ist. Hier wollen wir ja 2 Auswahlmöglichkeiten haben: &#8220;Kontakte&#8221; und &#8220;Anreden&#8221;. Also ändern wir den HauptMenuViewController.m:</p>
<pre class="brush: objc; title: ; notranslate">- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 2;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @&quot;Cell&quot;;

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    if (indexPath.row == 0) {
        cell.textLabel.text = @&quot;Adressen&quot;;
    }
    else if (indexPath.row == 1) {
        cell.textLabel.text = @&quot;Anreden&quot;;
    }
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

    return cell;
}</pre>
<p><strong>Erster Kontakt mit CoreData, dem CoreData Model Editor</strong></p>
<p>Nun kommen wir zu unserem ersten Kontakt mit dem Modellieren der CoreData-Entitäten / Objekten. In unserem Projekt gibt es ja eine Datei namens &#8220;CoreDataAdressen.xcdatamodeld&#8221;. Dies stellt unsere &#8220;Beschreibung&#8221; für unsere Daten-Objekte dar welche man mittels eines grafischen Editors bearbeiten kann.</p>
<p><a href="http://www.fasty.de/wp-content/uploads/2012/01/cd-6-ausgangspunkt-model.jpg"><img src="http://www.fasty.de/wp-content/uploads/2012/01/cd-6-ausgangspunkt-model.jpg" alt="" title="Model Editor" width="541" height="361" class="alignleft size-full wp-image-330" /></a></p>
<div style="clear: both;"></div>
<p>Standardmässig ist eine Beispiel-Entität namens &#8220;Event&#8221; dort aufgeführt, diese kann man löschen oder ignorieren. Wir legen 2 weitere Entitäten an, zu erst einmal &#8220;Anrede&#8221;:</p>
<p><a href="http://www.fasty.de/wp-content/uploads/2012/01/cd-7-anrede-entity.jpg"><img src="http://www.fasty.de/wp-content/uploads/2012/01/cd-7-anrede-entity.jpg" alt="" title="Entität: Anrede" width="533" height="235" class="alignleft size-full wp-image-329" /></a></p>
<div style="clear: both;"></div>
<p>Bei dieser neuen Enität fügt Ihr einfach nur ein Feld &#8220;name&#8221; vom Typ &#8220;String&#8221; hinzu, Anreden bestehen in unserem Daten-Modell nur aus diesem einen Attribut.</p>
<p>Und dann die Entität welche unsere Kontakte beschreibt (namens &#8220;Kontakt&#8221;):</p>
<p><a href="http://www.fasty.de/wp-content/uploads/2012/01/cd-8-kontakt-entity.jpg"><img src="http://www.fasty.de/wp-content/uploads/2012/01/cd-8-kontakt-entity.jpg" alt="" title="Entity: Kontakte" width="567" height="228" class="alignleft size-full wp-image-331" /></a></p>
<div style="clear: both;"></div>
<p>Ein Kontakt besteht in unserem Beispiel aus &#8220;vorname&#8221;, &#8220;nachname&#8221; und &#8220;email&#8221; vom Typ &#8220;String&#8221; und ein Feld namens &#8220;geburtstag&#8221; vom Typ &#8220;Date&#8221;. Desweiteren fügen wir noch ein &#8220;Beziehung&#8221;, also Relationship zur Tabelle &#8220;Anrede&#8221; hinzu (s. Screenshot).</p>
<p><strong>Nun könnte es krachen</strong></p>
<p>Wenn Ihr das Programm mehrmals gestartet habt und dann das DataModel ändert kann es beim Start zu folgendem Fehler kommen:</p>
<p><code>2012-01-21 13:44:24.858 CoreDataAdressen[17284:fb03] Unresolved error Error Domain=NSCocoaErrorDomain Code=134100 "The operation couldn’t be completed. (Cocoa error 134100.)" UserInfo=0x6d9c790 {metadata=<CFBasicHash 0x6d9c350 [0x171db38]>{type = immutable dict, count = 7,<br />
entries =><br />
	2 : <CFString 0x6d9be60 [0x171db38]>{contents = "NSStoreModelVersionIdentifiers"} = <CFArray 0x6d9bf40 [0x171db38]>{type = immutable, count = 1, values = (<br />
	0 : <CFString 0x1718cd8 [0x171db38]>{contents = ""}<br />
)}<br />
	4 : <CFString 0x6d9be90 [0x171db38]>{contents = "NSPersistenceFrameworkVersion"} = <CFNumber 0x6d9b050 [0x171db38]>{value = +386, type = kCFNumberSInt64Type}<br />
	6 : <CFString 0x6d9bec0 [0x171db38]>{contents = "NSStoreModelVersionHashes"} = <CFBasicHash 0x6d9bfb0 [0x171db38]>{type = immutable dict, count = 1,<br />
entries =><br />
	0 : <CFString 0x6d8f050 [0x171db38]>{contents = "Event"} = <CFData 0x6d9bf60 [0x171db38]>{length = 32, capacity = 32, bytes = 0x5431c046d30e7f32c2cc809958add1e7 ... 846e97d7af01cc79}<br />
}</p>
<p>	7 : <CFString 0x10daaa8 [0x171db38]>{contents = "NSStoreUUID"} = <CFString 0x6d9c150 [0x171db38]>{contents = "D51A5A5F-1122-4CB1-8064-80236FD48CC5"}<br />
	8 : <CFString 0x10da948 [0x171db38]>{contents = "NSStoreType"} = <CFString 0x10da958 [0x171db38]>{contents = "SQLite"}<br />
	9 : <CFString 0x6d9bef0 [0x171db38]>{contents = "_NSAutoVacuumLevel"} = <CFString 0x6d776d0 [0x171db38]>{contents = "2"}<br />
	10 : <CFString 0x6d9bf10 [0x171db38]>{contents = "NSStoreModelVersionHashesVersion"} = <CFNumber 0x6a31970 [0x171db38]>{value = +3, type = kCFNumberSInt32Type}<br />
}<br />
, reason=The model used to open the store is incompatible with the one used to create the store}, {<br />
    metadata =     {<br />
        NSPersistenceFrameworkVersion = 386;<br />
        NSStoreModelVersionHashes =         {<br />
            Event = <5431c046 d30e7f32 c2cc8099 58add1e7 579ad104 a3aa8fc4 846e97d7 af01cc79>;<br />
        };<br />
        NSStoreModelVersionHashesVersion = 3;<br />
        NSStoreModelVersionIdentifiers =         (<br />
            ""<br />
        );<br />
        NSStoreType = SQLite;<br />
        NSStoreUUID = "D51A5A5F-1122-4CB1-8064-80236FD48CC5";<br />
        "_NSAutoVacuumLevel" = 2;<br />
    };<br />
    reason = "The model used to open the store is incompatible with the one used to create the store";<br />
}</code></p>
<p>Dieser Fehler sagt aus dass das DataModel bei den vorherigen Starts anders ausgesehen hat. Inzwischen haben wir ja die Entities &#8220;Anrede&#8221; und &#8220;Kontakt&#8221; hinzugefügt. Wenn man das Programm danach startet hat sich das DataModel geändert und damit kommt CoreData im Moment noch nicht klar.</p>
<p>Dies lässt sich aber mit einer einfach Anpassung im AppDelegate korrigieren. Das Ganze fällt unter das Stichwort &#8220;CoreData Data Migration / Versioning&#8221;: jedes Mal wenn was am Daten-Modell geändert wird müssen wir CoreData sagen wie sich die Daten ändern. Wenn aber nur leichte Änderungen am Daten-Modell hinzugefügt werden kann man dies durch folgende Änderung am AppDelegate beheben:</p>
<pre class="brush: objc; title: ; notranslate">- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (__persistentStoreCoordinator != nil)
    {
        return __persistentStoreCoordinator;
    }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@&quot;CoreDataAdressen.sqlite&quot;];

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

    NSError *error = nil;
    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                    configuration:nil
                                                              URL:storeURL
                                                          options:options
                                                            error:&amp;error])
    {
...</pre>
<p>Beim Erstellen des Objekts &#8220;persistentStoreCoordinator&#8221; geschieht dies nun mit den Optionen &#8220;NSMigratePersistentStoresAutomaticallyOption&#8221; und &#8220;NSInferMappingModelAutomaticallyOption&#8221;. Wenn man das Programm nun startet kommt es nicht mehr zu einem Absturz.</p>
<p>Im nächsten Teil der Tutorial-Serie erweitern wir das Programm so dass man Anreden hinzufügen, löschen und anzeigen kann.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fasty.de/2012/01/coredata-tutorial-teil-1-grund-aufbau-der-app/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symbol not found: __NSConcreteStackBlock</title>
		<link>http://www.fasty.de/2012/01/symbol-not-found-__nsconcretestackblock/</link>
		<comments>http://www.fasty.de/2012/01/symbol-not-found-__nsconcretestackblock/#comments</comments>
		<pubDate>Mon, 02 Jan 2012 12:39:03 +0000</pubDate>
		<dc:creator>Fasty</dc:creator>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[XCode]]></category>

		<guid isPermaLink="false">http://www.fasty.de/?p=307</guid>
		<description><![CDATA[Dieser Fehler kann auftreten wenn Ihr eine App auf einem älteren iPhone mit iOS 3.1.3 compilieren wollt. Vermutlich kommt der Fehler daher weil Ihr irgendwo im Code &#8220;Blocks&#8221; nutzt. Die Lösung ist sehr einfach: Einfach unter &#8220;Build Phases&#8221; bei &#8220;Link &#8230; <a href="http://www.fasty.de/2012/01/symbol-not-found-__nsconcretestackblock/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Dieser Fehler kann auftreten wenn Ihr eine App auf einem älteren iPhone mit iOS 3.1.3 compilieren wollt. Vermutlich kommt der Fehler daher weil Ihr irgendwo im Code &#8220;Blocks&#8221; nutzt.</p>
<p>Die Lösung ist sehr einfach: Einfach unter &#8220;Build Phases&#8221; bei &#8220;Link Binary with Libraries&#8221; die Library &#8220;libSystem.B.dylib&#8221; als &#8220;Optional&#8221; hinzufügen.</p>
<p>Ergänzung: Nachdem ich dies so genutzt habe lies sich die App unter Xcode4 ganz normal für iOS Geräte compilieren, brachte aber einen Compiler-Fehler wenn ich sie im Simulator compilieren wollten.</p>
<p>Die Lösung gab es natürlich auf <a href="http://stackoverflow.com/questions/5320788/xcode-4-final-version-error-when-building/6549418#6549418" title="Stack Overflow"></a>.</p>
<p>Ins deutsche übersetzt müsst Ihr folgendes machen:</p>
<ul>
<li>Das Terminal aufrufen und in den Ordner /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk/usr/lib wechseln</li>
<li>Einen symbolischen Link anlegen mittels: sudo ln -s libSystem.dylib libSystem.B.dylib</li>
<li>Dann sollte die App wieder im Simulator laufen <img src='http://www.fasty.de/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </li>
</ul>
<p><strong>Nachtrag für Xcode 4.3</strong></p>
<p>Ab XCode 4.3 befindet sich XCode im Programme-Verzeichnis. Der Pfad zu den Bibliotheken ist dann /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk/usr/lib</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fasty.de/2012/01/symbol-not-found-__nsconcretestackblock/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TabBarItem programmatisch entfernen</title>
		<link>http://www.fasty.de/2011/09/tabbaritem-programmatisch-entfernen/</link>
		<comments>http://www.fasty.de/2011/09/tabbaritem-programmatisch-entfernen/#comments</comments>
		<pubDate>Thu, 22 Sep 2011 11:47:18 +0000</pubDate>
		<dc:creator>Fasty</dc:creator>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[UITabBarController]]></category>
		<category><![CDATA[UITabItem]]></category>

		<guid isPermaLink="false">http://www.fasty.de/?p=304</guid>
		<description><![CDATA[Wenn man in seinem XIB-File einen UITabBarController hinzugefügt hat kann es ja sein dass man gewissen Tab-Items doch nicht angezeigt haben möchte. Programmatisch kann man nicht einfach die items-Property der UITabBar modifizieren falls die TabBar einem TabBarController angehört. Dies muss &#8230; <a href="http://www.fasty.de/2011/09/tabbaritem-programmatisch-entfernen/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Wenn man in seinem XIB-File einen UITabBarController hinzugefügt hat kann es ja sein dass man gewissen Tab-Items doch nicht angezeigt haben möchte. Programmatisch kann man nicht einfach die items-Property der UITabBar modifizieren falls die TabBar einem TabBarController angehört. Dies muss dann wie folgt gemacht werden (Wir gehen davon aus dass tabController ein gültiger UITabBarController ist):</p>
<pre class="brush: objc; title: ; notranslate">NSMutableArray *neueVC = [NSMutableArray arrayWithArray:tabController.viewControllers];
[neueVC removeObjectAtIndex:2];
tabController.viewController = neueVC;</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.fasty.de/2011/09/tabbaritem-programmatisch-entfernen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8220;Normale&#8221; und &#8220;Lite&#8221; Version einer App im gleichen Projekt erstellen</title>
		<link>http://www.fasty.de/2011/09/normale-und-lite-version-einer-app-im-gleichen-projekt-erstellen/</link>
		<comments>http://www.fasty.de/2011/09/normale-und-lite-version-einer-app-im-gleichen-projekt-erstellen/#comments</comments>
		<pubDate>Wed, 21 Sep 2011 13:00:43 +0000</pubDate>
		<dc:creator>Fasty</dc:creator>
				<category><![CDATA[iOS]]></category>

		<guid isPermaLink="false">http://www.fasty.de/?p=297</guid>
		<description><![CDATA[Ab und an kommt es vor dass man im gleichen Projekt ohne großes Duplizieren von Code zwei unterschiedliche Versionen einer App erstellen möchte. Beispiel hier: eine App mit dem vollen Funktionsumfang und eine &#8220;Lite&#8221; Version der App (mit eingeschränkter Funktionalität, &#8230; <a href="http://www.fasty.de/2011/09/normale-und-lite-version-einer-app-im-gleichen-projekt-erstellen/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Ab und an kommt es vor dass man im gleichen Projekt ohne großes Duplizieren von Code zwei unterschiedliche Versionen einer App erstellen möchte. Beispiel hier: eine App mit dem vollen Funktionsumfang und eine &#8220;Lite&#8221; Version der App (mit eingeschränkter Funktionalität, dafür evtl. aber kostenlos.</p>
<p>Eine Möglichkeit dies zu realisiern ist z.B. mit Pre-Processor-Makros und einer einfachen Abfrage im Programmcode.</p>
<p>Hier die Vorgehensweise:</p>
<p>- Duplizieren des vorhandenen &#8220;Targets&#8221;, so dass man ein 2. Target namens &#8220;App copy&#8221; hat.<br />
- In diesem neuen Target kann man komplett anderer Bundle Identifier etc. nutzen um die App unter einem anderen Namen im App-Store zu vertreiben<br />
- Unter &#8220;Build Settings&#8221; des Targets einfach nach &#8220;other c&#8221; filtern und auf &#8220;Other C Flags&#8221; klicken:<br />
<a href="http://www.fasty.de/wp-content/uploads/2011/09/preprocessor.jpg"><img src="http://www.fasty.de/wp-content/uploads/2011/09/preprocessor.jpg" alt="" title="preprocessor" width="801" height="513" class="alignleft size-full wp-image-299" /></a><br />
- Hier einfach &#8220;-DKUNDE_VERSION&#8221; oder &#8220;-DLITE_VERSION&#8221; einfügen<br />
- Das war&#8217;s auch schon <img src='http://www.fasty.de/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Im Programmcode an sich kann man ganz einfach zwischen beiden Versionen unterscheiden, in dem man z.B. folgenden Programmcode verwendet:</p>
<pre class="brush: objc; title: ; notranslate">#ifdef KUNDE_VERSION
// Code welcher in der LITE-Version ausgeführt werden soll
#else
// Code welcher in der &quot;normalen&quot; Version ausgeführt werden soll
#endif</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.fasty.de/2011/09/normale-und-lite-version-einer-app-im-gleichen-projekt-erstellen/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHPMailer: Fehler in MAC OS-Mail-Clients bei Mails mit eingebetteten Bildern und normalen Attachments</title>
		<link>http://www.fasty.de/2011/07/phpmailer-fehler-in-mac-mail-clients-bei-mails-mit-eingebetteten-bildern-und-normalen-attachments/</link>
		<comments>http://www.fasty.de/2011/07/phpmailer-fehler-in-mac-mail-clients-bei-mails-mit-eingebetteten-bildern-und-normalen-attachments/#comments</comments>
		<pubDate>Thu, 07 Jul 2011 12:13:17 +0000</pubDate>
		<dc:creator>Fasty</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHPMailer]]></category>

		<guid isPermaLink="false">http://www.fasty.de/?p=274</guid>
		<description><![CDATA[Dieser Fehler hat mich Nerven gekostet, aber nach langer Suche im Internet bin ich auf ein paar brauchbare Resultate gestossen. Zuerst der Fehler: Wenn Ihr mit der Library/Klasse &#8220;PHPMailer&#8221; in PHP arbeitet und Mails damit versendet, so kommen Mails mit &#8230; <a href="http://www.fasty.de/2011/07/phpmailer-fehler-in-mac-mail-clients-bei-mails-mit-eingebetteten-bildern-und-normalen-attachments/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Dieser Fehler hat mich Nerven gekostet, aber nach langer Suche im Internet bin ich auf ein paar brauchbare Resultate gestossen.</p>
<p>Zuerst der Fehler:<br />
Wenn Ihr mit der Library/Klasse &#8220;PHPMailer&#8221; in PHP arbeitet und Mails damit versendet, so kommen Mails mit scheinbar &#8220;fehlendem Attachment&#8221; im Apple Mail-Client an wenn Ihr in der gleichen Mail auch mit eingebetteten Bildern (&#8220;Embedded Images&#8221;) arbeitet.</p>
<p>Lösung:<br />
- Ihr benötigt zuerst die aktuelle Version vom PHPMailer, Version 5.1, diese könne Ihr <a href="http://sourceforge.net/projects/phpmailer/files/phpmailer%20for%20php5_6/PHPMailer%20v5.1/">hier</a> herunterladen<br />
- Es gibt zu diesem Problem ein extra Patch-File welches unter <a href="http://sourceforge.net/tracker/index.php?func=detail&#038;aid=3185821&#038;group_id=26031&#038;atid=385709">hier</a> herunterzuladen ist<br />
- Wendet einfach den Patch auf die Datei an (Unter MAC OS hierfür das Terminal öffnen, beide Dateien in ein Verzeichnis verschieben und in der Kommandozeile &#8220;patch class.phpmailer.php phpmailer.patch&#8221; ausführen)</p>
<p>Nun werden die Boundaries wieder korrekt verschachtelt und die Mail sollte im Apple-Mail-Client und anderen Mail-Clients wieder korrekt lesbar sein (inkl. aller Attachments)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fasty.de/2011/07/phpmailer-fehler-in-mac-mail-clients-bei-mails-mit-eingebetteten-bildern-und-normalen-attachments/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mehr als ein UIBarButtonItem als rightNavigationItem nutzen</title>
		<link>http://www.fasty.de/2011/06/mehr-als-ein-uibarbuttonitem-als-rightnavigationitem-nutzen/</link>
		<comments>http://www.fasty.de/2011/06/mehr-als-ein-uibarbuttonitem-als-rightnavigationitem-nutzen/#comments</comments>
		<pubDate>Tue, 07 Jun 2011 07:35:43 +0000</pubDate>
		<dc:creator>Fasty</dc:creator>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[UIBarButtonItem]]></category>

		<guid isPermaLink="false">http://www.fasty.de/?p=262</guid>
		<description><![CDATA[In einigen Projekten habe ich gesehen dass in der rechten oberen Ecke (im NagigationBar) zwei Buttons vorhanden sind, auch mit schön &#8220;abgerundeten Ecken&#8221;. Mittels des navigationItem.rightBarButtonItem kann man ja leider nur ein UIBarButtonItem zuweisen. Wenn Ihr mehrere Buttons haben wollt &#8230; <a href="http://www.fasty.de/2011/06/mehr-als-ein-uibarbuttonitem-als-rightnavigationitem-nutzen/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In einigen Projekten habe ich gesehen dass in der rechten oberen Ecke (im NagigationBar) zwei Buttons vorhanden sind, auch mit schön &#8220;abgerundeten Ecken&#8221;. Mittels des navigationItem.rightBarButtonItem kann man ja leider nur ein UIBarButtonItem zuweisen.</p>
<p>Wenn Ihr mehrere Buttons haben wollt könnt Ihr ein UISegmentedControll erstellen und dies quasi als UIBarButtonItem nutzen. Hier der Beispiel-Code:</p>
<pre class="brush: objc; title: ; notranslate">    // Segmented Control erstellen
    UISegmentedControl* segmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray array]];

    // Man soll nicht sehen dass ein Segment selektiert wurde
    [segmentedControl setMomentary:YES];

    // Fügt Segmente hinzu, alternativ kann man auch insertSegmentWithImage:atIndex:animated: nutzen um Bilder zu benutzen
    [segmentedControl insertSegmentWithTitle:@&quot;Historie&quot; atIndex:0 animated:NO];
    [segmentedControl insertSegmentWithTitle:@&quot;Bearbeiten&quot; atIndex:1 animated:NO];

    // Wird für Autoresizing genutzt
    segmentedControl.autoresizingMask = UIViewAutoresizingFlexibleWidth;

    // Setzt des Stil der SegmentedControl
    segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;

    // Aktion welche erfolgt wenn man auf die SegmentedControl klickt
    [segmentedControl addTarget:self action:@selector(eineAktion:) forControlEvents:UIControlEventValueChanged];

    // Erstellt ein BarButtonItem und fügt es als rightBarButtonItem hinzu
    UIBarButtonItem *segmentBarItem = [[UIBarButtonItem alloc] initWithCustomView: segmentedControl];
    self.navigationItem.rightBarButtonItem = segmentBarItem;

    // Objekt releasen
    [segmentedControl release];</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.fasty.de/2011/06/mehr-als-ein-uibarbuttonitem-als-rightnavigationitem-nutzen/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Fehler beim compilen: Duplicate symbol _OBJC_IVAR</title>
		<link>http://www.fasty.de/2011/06/fehler-beim-compilen-duplicate-symbol-_objc_ivar/</link>
		<comments>http://www.fasty.de/2011/06/fehler-beim-compilen-duplicate-symbol-_objc_ivar/#comments</comments>
		<pubDate>Tue, 07 Jun 2011 07:32:09 +0000</pubDate>
		<dc:creator>Fasty</dc:creator>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[XCode]]></category>

		<guid isPermaLink="false">http://www.fasty.de/?p=264</guid>
		<description><![CDATA[Heute hatte ich einen Fehler beim compilieren meines Projektes: Duplicate symbol _OBJC_IVAR. Ich hatte dummerweise ein .m-File mittels #import ins Projekt eingebunden. Kann ja mal aufgrund der Auto-Completion passieren]]></description>
			<content:encoded><![CDATA[<p>Heute hatte ich einen Fehler beim compilieren meines Projektes: <strong>Duplicate symbol _OBJC_IVAR</strong>.</p>
<p>Ich hatte dummerweise ein .m-File mittels #import ins Projekt eingebunden. Kann ja mal aufgrund der Auto-Completion passieren <img src='http://www.fasty.de/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.fasty.de/2011/06/fehler-beim-compilen-duplicate-symbol-_objc_ivar/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Kontakte aus dem Adressbuch auswählen</title>
		<link>http://www.fasty.de/2011/05/kontakte-aus-dem-adressbuch-auswahlen/</link>
		<comments>http://www.fasty.de/2011/05/kontakte-aus-dem-adressbuch-auswahlen/#comments</comments>
		<pubDate>Thu, 26 May 2011 15:21:03 +0000</pubDate>
		<dc:creator>Fasty</dc:creator>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[ABPeoplePickerNavigationController]]></category>

		<guid isPermaLink="false">http://www.fasty.de/?p=249</guid>
		<description><![CDATA[Ich habe etwas herumprobiert wie man sich mit Hilfe des &#8220;AddressBook&#8220;-Frameworks Adressen aus dem Adressbuch herausholen kann. Hier ein kurzes Beispiel welches den Vorgang dokumentiert. Ich habe ein neues Projekt (view-based Application) angelegt und ein ganz einfaches Interface gestaltet: Auf &#8230; <a href="http://www.fasty.de/2011/05/kontakte-aus-dem-adressbuch-auswahlen/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Ich habe etwas herumprobiert wie man sich mit Hilfe des &#8220;<strong>AddressBook</strong>&#8220;-Frameworks Adressen aus dem Adressbuch herausholen kann. Hier ein kurzes Beispiel welches den Vorgang dokumentiert.</p>
<p>Ich habe ein neues Projekt (view-based Application) angelegt und ein ganz einfaches Interface gestaltet: Auf den View habe ich einen Button angelegt &#8211; und wenn man auf diesen klickt wird die Action <strong>getAddress:</strong> aufgerufen.<br />
So sieht das Header-File meines ViewControllers aus:</p>
<pre class="brush: objc; title: ; notranslate">#import &lt;UIKit/UIKit.h&gt;
#import &lt;AddressBook/AddressBook.h&gt;
#import &lt;AddressBookUI/AddressBookUI.h&gt;

@interface ABPickerTestViewController : UIViewController &lt;ABPeoplePickerNavigationControllerDelegate&gt; {

}
- (IBAction)getAddress:(id)sender;</pre>
<p>Man muss also das Protokoll &#8220;<strong>ABPeoplePickerNavigationControllerDelegate</strong>&#8221; implementieren. Hier der komplett Code der .m-Files. Ich erkläre diesen später:</p>
<pre class="brush: objc; title: ; notranslate">- (IBAction)getAddress:(id)sender {
    ABPeoplePickerNavigationController *pp = [[ABPeoplePickerNavigationController alloc] init];
    pp.peoplePickerDelegate = self;
    [self presentModalViewController:pp animated:YES];
    [pp release];
}

#pragma mark -
#pragma mark ABPeoplePickerNavigationControllerDelegate

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
      shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
    // &quot;Normale&quot; Infos
    NSString *vorname = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
    NSString *nachname = (NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
    NSString *firma = (NSString *)ABRecordCopyValue(person, kABPersonOrganizationProperty);

    NSLog(@&quot;Vorname: %@&quot;, vorname);
    NSLog(@&quot;Nachname: %@&quot;, nachname);
    NSLog(@&quot;Firma: %@&quot;, firma);

    [vorname release];
    [nachname release];
    [firma release];

    // Infos zu Telefonnummern
    ABMultiValueRef multi = ABRecordCopyValue(person, kABPersonPhoneProperty);
    for (CFIndex i = 0; i &lt; ABMultiValueGetCount(multi); i++) {

        NSString *telLabel = (NSString *)ABMultiValueCopyLabelAtIndex(multi, i);
        NSString *telNr = (NSString *)ABMultiValueCopyValueAtIndex(multi, i);

        NSString *typ = @&quot;&quot;;
        if ([telLabel rangeOfString:@&quot;Work&quot;].location != NSNotFound) {
            typ = @&quot;Arbeit&quot;;
        }
        else if ([telLabel rangeOfString:@&quot;Mobile&quot;].location != NSNotFound) {
            typ = @&quot;Mobil&quot;;
        }
        else if ([telLabel rangeOfString:@&quot;Home&quot;].location != NSNotFound) {
            typ = @&quot;Heim&quot;;
        }
        else {
            typ = @&quot;unbekannt&quot;;
        }

        NSLog(@&quot;Label: %@ Nr: %@ Typ: %@&quot;, telLabel, telNr, typ);

        [telLabel release];
        [telNr release];
    }
    CFRelease(multi);

    // Infos zu Adressen
    ABMultiValueRef address = ABRecordCopyValue(person, kABPersonAddressProperty);
    for (CFIndex i = 0; i &lt; ABMultiValueGetCount(address); i++) {

        NSString *addrLabel = (NSString *)ABMultiValueCopyLabelAtIndex(address, i);
        NSDictionary *addrDict = (NSDictionary *)ABMultiValueCopyValueAtIndex(address, i);

        NSString *strasse = [addrDict objectForKey:@&quot;Street&quot;];
        NSString *plz = [addrDict objectForKey:@&quot;ZIP&quot;];
        NSString *ort = [addrDict objectForKey:@&quot;City&quot;];

        NSLog(@&quot;Label: %@ Str: %@, PLZ: %@, Ort: %@&quot;, addrLabel, strasse, plz, ort);

        [addrLabel release];
        [addrDict release];
    }
    CFRelease(address);

    // ModalViewController dismissen
    [self dismissModalViewControllerAnimated:YES];
    return NO;
}

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
     shouldContinueAfterSelectingPerson:(ABRecordRef)person
                               property:(ABPropertyID)property
                             identifier:(ABMultiValueIdentifier)identifier
{
    return NO;
}

- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker
{
    [self dismissModalViewControllerAnimated:YES];
}</pre>
<p>Nehmen wir uns zuerst einmal die Action vor die aufgerufen wird wenn der Button geklickt wird:</p>
<pre class="brush: objc; title: ; notranslate">- (IBAction)getAddress:(id)sender {
    ABPeoplePickerNavigationController *pp = [[ABPeoplePickerNavigationController alloc] init];
    pp.peoplePickerDelegate = self;
    [self presentModalViewController:pp animated:YES];
    [pp release];
}</pre>
<p>Hier wird zuerst ein Objekt initialisiert welches im Framework &#8220;<strong>AddressBookUI</strong>&#8221; vorkommt, nämlich den &#8220;<strong>ABPeoplePickerNavigationController</strong>&#8220;. Ihr kennt diesen Controller, das ist der gleiche wenn man das Adressbuch öffnet und in den Kontakten sucht.<br />
Diesem Controller wird ein Delegate bekannt gemacht, der Einfachheit halber nehmen wir das gleiche Objekt (self), im Interface haben wir ja auch gesagt dass das Protokoll &#8220;<strong>ABPeoplePickerNavigationControllerDelegate</strong>&#8221; eingehalten wird.<br />
Zuguterletzt wird der Controller als &#8220;ModalView&#8221; angezeigt.</p>
<p>Das Verhalten des &#8220;<strong>ABPeoplePickerNavigationController</strong>&#8221; richtet sich nach den <strong>Delegate-Methoden</strong> welche wir eingeführt haben.</p>
<p>Fangen wir mit den einfachsten an:</p>
<pre class="brush: objc; title: ; notranslate">- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker
{
    [self dismissModalViewControllerAnimated:YES];
}</pre>
<p>Diese Delegate-Methode wird aufgerufen wenn der &#8220;Abbruch&#8221; Button geklickt wird, in unserem Falle entfernen wir einfach den ModalView.</p>
<pre class="brush: objc; title: ; notranslate">- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
     shouldContinueAfterSelectingPerson:(ABRecordRef)person
                               property:(ABPropertyID)property
                             identifier:(ABMultiValueIdentifier)identifier
{
    return NO;
}</pre>
<p>Diese Delegate Methode wird aufgerufen wenn der User eine der User-Eigenschaften anklickt. In unserem Fall tritt dies nicht ein da die nächste Delegate-Methode gar nicht zulässt dass man in einen Benutzer reinspringt:</p>
<pre class="brush: objc; title: ; notranslate">- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
      shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
    // Jede Menge Code hier, s. oben

    // ModalViewController dismissen
    [self dismissModalViewControllerAnimated:YES];
    return NO;
}</pre>
<p>Diese Delegate-Methode wird aufgerufen sobald man in der Kontakt-Liste einen Kontakt anklickt. Die Rückgabe NO gibt an dass nicht in den Benutzer reingesprungen wird sondern er direkt ausgewählt wird. Im Quellcode sind einige Beispiele aufgeführt wie man an Informationen des Eintrags kommt, ich hoffe Ihr könnt damit was anfangen <img src='http://www.fasty.de/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.fasty.de/2011/05/kontakte-aus-dem-adressbuch-auswahlen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Prüfen ob Substring in einem String vorkommt</title>
		<link>http://www.fasty.de/2011/05/prufen-ob-substring-in-einem-string-vorkommt/</link>
		<comments>http://www.fasty.de/2011/05/prufen-ob-substring-in-einem-string-vorkommt/#comments</comments>
		<pubDate>Thu, 26 May 2011 15:16:44 +0000</pubDate>
		<dc:creator>Fasty</dc:creator>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[NSString]]></category>

		<guid isPermaLink="false">http://www.fasty.de/?p=247</guid>
		<description><![CDATA[Hier eine einfach Methode um zu prüfen ob ein String in einem anderen STring vorkommt:]]></description>
			<content:encoded><![CDATA[<p>Hier eine einfach Methode um zu prüfen ob ein String in einem anderen STring vorkommt:</p>
<pre class="brush: objc; title: ; notranslate">if ([haystackString rangeOfString:@&quot;needle&quot;].location != NSNotFound) {
    // Das Wort &quot;needle&quot; kommt in dem String haystackString vor!
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.fasty.de/2011/05/prufen-ob-substring-in-einem-string-vorkommt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

