Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Geleitwort
Vorwort
1 Hello iPhone
2 Die Reise nach iOS
3 Sehen und anfassen
4 Alles unter Kontrolle
5 Daten, Tabellen und Controller
6 Models, Layer, Animationen
7 Programmieren, aber sicher
8 Datenserialisierung und Internetzugriff
9 Multimedia
10 Jahrmarkt der Nützlichkeiten
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
Apps programmieren für iPhone und iPad von Klaus M. Rodewig, Clemens Wagner
Das umfassende Handbuch
Buch: Apps programmieren für iPhone und iPad

Apps programmieren für iPhone und iPad
Rheinwerk Computing
1172 S., geb., mit DVD
49,90 Euro, ISBN 978-3-8362-2734-6
Pfeil 5 Daten, Tabellen und Controller
Pfeil 5.1 Benachrichtigungen
Pfeil 5.1.1 Benachrichtigungen empfangen
Pfeil 5.1.2 Eigene Benachrichtigungen verschicken
Pfeil 5.2 Layoutanpassungen und Viewrotationen
Pfeil 5.2.1 Lang lebe das Rotationsprinzip!
Pfeil 5.2.2 Anpassung des Layouts
Pfeil 5.3 Core Data
Pfeil 5.3.1 Datenmodellierung
Pfeil 5.3.2 Implementierung von Entitätstypen
Pfeil 5.3.3 Dokumentenordner und Application-Support-Verzeichnis
Pfeil 5.3.4 Einbindung von Core Data
Pfeil 5.3.5 Der Objektkontext
Pfeil 5.3.6 Die Nachrichten des Objektkontexts
Pfeil 5.3.7 Anlegen und Ändern von Entitäten in der Praxis
Pfeil 5.4 Texte, Bilder und Töne verwalten
Pfeil 5.4.1 Viewanpassungen für die Systemleisten
Pfeil 5.4.2 Die Tastatur betritt die Bühne
Pfeil 5.4.3 Fotos aufnehmen
Pfeil 5.4.4 Töne aufnehmen und abspielen
Pfeil 5.5 Tableviews und Core Data
Pfeil 5.5.1 Tableviews
Pfeil 5.5.2 Tabellenzellen gestalten
Pfeil 5.5.3 Zellprototypen über das Storyboard definieren
Pfeil 5.5.4 Zellprototypen per Programmcode bereitstellen
Pfeil 5.5.5 Der Target-Action-Mechanismus und Tabellenzellen
Pfeil 5.5.6 Zellen löschen
Pfeil 5.6 Core Data II: Die Rückkehr der Objekte
Pfeil 5.6.1 Prädikate
Pfeil 5.6.2 Aktualisierung des Tableviews
Pfeil 5.6.3 Das Delegate des Fetched-Results-Controllers
Pfeil 5.6.4 Tabelleneinträge suchen
Pfeil 5.7 Inhalte teilen
Pfeil 5.7.1 Integration in das Fototagebuch
Pfeil 5.7.2 Eigene Aktivitäten bereitstellen
Pfeil 5.8 Collectionviews
Pfeil 5.8.1 Der Collectionviewcontroller
Pfeil 5.8.2 Gitterdarstellung
Pfeil 5.8.3 Zellen und die Datenquelle
Pfeil 5.8.4 Ergänzende Views
Pfeil 5.8.5 Freie Layouts
Pfeil 5.8.6 Freie Layouts und ergänzende Views
Pfeil 5.8.7 Decorationviews

Rheinwerk Computing - Zum Seitenanfang

5.7Inhalte teilenZur nächsten Überschrift

Mit iOS 6 hat Apple die Klasse UIActivityViewController eingeführt, die eine einheitliche Anbindung von sozialen Netzwerken wie Twitter, Facebook oder Sina Weibo [Anm.: Sina Weibo ist eine chinesische Microblogging-Plattform, ähnlich wie Twitter.] erlaubt. Außerdem können Sie darüber Mails, Nachrichten und SMS versenden oder Daten an den Drucker, die Zwischenablage sowie das Fotoalbum schicken. Damit der Nutzer die gewünschte Aktivität auswählen kann, zeigt der Controller zunächst eine Auswahl aller verfügbaren und sinnvollen Aktivitäten an (siehe Abbildung 5.27).

Abbildung

Abbildung 5.27 Auswahl der Aktivität über den Activity-Viewcontroller

Accountdaten

Damit ein Nutzer die sozialen Netzwerke über den Activity-Viewcontroller ansprechen kann, muss er seine Zugangsdaten in den Systemeinstellungen des Geräts hinterlegen. Der Controller zeigt in seiner Auswahl also nur die sozialen Netzwerke an, zu denen der Nutzer Zugangsdaten hinterlegt hat.


Rheinwerk Computing - Zum Seitenanfang

5.7.1Integration in das FototagebuchZur nächsten ÜberschriftZur vorigen Überschrift

Für die Verwendung des Activity-Viewcontrollers müssen Sie zunächst einmal die Daten in einem Array bereitstellen, die der Nutzer der App über den Controller teilen kann. Im Fototagebuch sind das der Text und das Bild eines Eintrags. Die Methode activityItems in der Klasse DiaryEntryViewController erstellt ein Array mit diesen Einträgen, wobei sie jedoch nur vorhandene Einträge einfügt.

- (NSArray *)activityItems {
NSMutableArray *theItems = [NSMutableArray array];
Medium *theMedium = [self.diaryEntry
mediumForType:kMediumTypeImage];
NSString *theText = self.diaryEntry.text;

if(theMedium != nil) {
CGFloat theScale = [[UIScreen mainScreen] scale];
UIImage *theImage = [UIImage imageWithData:
theMedium.data scale:theScale];

[theItems addObject:theImage];
}
if([theText length] > 0) {
[theItems addObject:theText];
}
return [theItems copy];
}

Listing 5.72 Bereitstellen der Daten für den Activity-Viewcontroller

Die Implementierung der Methode activityItems reicht als Basis für die Anzeige des Activity-Viewcontrollers aus. Sie übergeben dieses Array dazu bei der Erzeugung an die Initialisierungsmethode initWithActivityItems:applicationActivities: des Activity-Viewcontrollers, den Sie über die Methode presentViewController:animated:completion: anzeigen.

- (IBAction)shareDiaryEntry:(id)inSender {
NSArray *theItems = self.activityItems;
UIActivityViewController *theController =
[[UIActivityViewController alloc]
initWithActivityItems:theItems
applicationActivities:nil];

[self presentViewController:theController
animated:YES completion:NULL];
}

Listing 5.73 Anzeige des Activity-Viewcontrollers

Der Activity-Viewcontroller schränkt die Aktivitäten in der Auswahl auch abhängig von den zur Verfügung gestellten Einträgen ein. Wenn der Tagebucheintrag zum Beispiel kein Foto enthält, zeigt die Auswahl die Aktivitäten Bild sichern, Kontakt zuweisen [Anm.: Dieser Dienst weist ein Bild einem Eintrag im Adressbuch zu.] und Drucken nicht an, da diese Aktivitäten für Texte sinnlos sind.

Sie können die Aktivitäten in der Auswahl des Activity-Viewcontrollers über seine Property excludedActvityTypes auch einschränken. Dazu übergeben Sie dieser Property ein Array mit den Namen der Aktivitäten, die der Controller nicht anzeigen soll. Beispielsweise unterbinden Sie dem Controller aus Listing 5.73 das Kopieren in die Zwischenablage und das Drucken über die folgende Zeile:

theController.excludedActivityTypes = 
@[UIActivityTypeCopyToPasteboard, UIActivityTypePrint];

Listing 5.74 Kopieren in die Zwischenablage und Drucken ausschalten


Rheinwerk Computing - Zum Seitenanfang

5.7.2Eigene Aktivitäten bereitstellenZur vorigen Überschrift

Objekte der Klasse UIActivity repräsentieren die Aktivitäten in einem Activity-Viewcontroller. Zwar haben Sie keinen Zugriff auf die Systemaktivitäten, wie Twitter oder Drucken, dafür können Sie jedoch über Unterklassen von UIActivity Ihrer App applikationsspezifische Aktivitäten bereitstellen, um beispielsweise weitere soziale Netzwerke oder andere Dienste einzubinden.

Applikationsspezifische Aktivitäten

Sie können Ihre Apps mit beliebig vielen Aktivitäten erweitern. Allerdings ist es leider zurzeit nicht möglich, diese Aktivitäten auch anderen Apps zur Verfügung zu stellen oder spezielle Aktivitäten für andere Apps anzubieten; Sie können also beispielsweise keine Aktivität »Ins Fototagebuch einfügen« für andere Apps bereitstellen.

Das Fototagebuch enthält eine applikationsspezifische Aktivität: Der Nutzer kann Einträge aus dem Tagebuch in den Dokumentenordner der App exportieren. Die Implementierung dieser Aktivität übernimmt die Klasse DiaryEntryExportActivity, die Objekte der Klasse DiaryEntry als Einträge verwendet. Für die Einbindung müssen Sie die Methoden activityItems und shareDiaryEntry: aus Listing 5.72 und Listing 5.73 erweitern. Zu den Daten für den Activity-Viewcontroller fügen Sie zunächst den aktuellen Tagebucheintrag hinzu.

- (NSArray *)activityItems {
NSMutableArray *theItems = [NSMutableArray array];
Medium *theMedium = [self.diaryEntry
mediumForType:kMediumTypeImage];
NSString *theText = self.diaryEntry.text;

if(theMedium != nil) {
CGFloat theScale = [[UIScreen mainScreen] scale];
UIImage *theImage = [UIImage
imageWithData:theMedium.data scale:theScale];

[theItems addObject:theImage];
}
if([theText length] > 0) {
[theItems addObject:theText];
}
[theItems addObject:self.diaryEntry];
return [theItems copy];
}

Listing 5.75 Daten für den Activity-Viewcontroller erweitern

Außerdem muss der Activity-Viewcontroller eine Exportaktivität bei der Initialisierung übergeben bekommen. Der zweite Parameter der Methode initWithActivityItems:applicationActvities: dient zur Übergabe eines Arrays mit applikationsspezifischen Aktivitäten. Die Klasse DiaryEntryExportActivity besitzt eine Property storyboard, aus dem sie Viewcontroller der App nachlädt. Dieser Property müssen Sie vor der Anzeige des Activity-Viewcontrollers ein Storyboard zuweisen (siehe Listing 5.76).

- (IBAction)shareDiaryEntry:(id)inSender {
DiaryEntryExportActivity *theActivity =
[[DiaryEntryExportActvity alloc] init];
NSArray *theItems = self.activityItems;
UIActivityViewController *theController =
[[UIActivityViewController alloc]
initWithActivityItems:theItems
applicationActivities:@[theActivity]];

theActivity.storyboard = self.storyboard;

[self presentViewController:theController animated:YES
completion:NULL];
}

Listing 5.76 Einbindung einer applikationsspezifischen Aktivität

Jede applikationsspezifische Aktivität muss einen Typ, einen Titel und ein Bild über die Methoden activityType, activityTitle beziehungsweise activityImage bereitstellen. Dabei ist der Typ eine frei wählbare Zeichenkette, die allerdings nicht mit den Systemtypen übereinstimmen sollte.

NSString * const kActivityTypeExport = 
@"de.cocoaneheads.DiaryEntryExportActvity";

- (NSString *)activityType {
return kActivityTypeExport;
}

- (NSString *)activityTitle {
return NSLocalizedString(@"Export", @"Activity Title");
}

- (UIImage *)activityImage {
return [UIImage imageNamed:@"export"];
}

Listing 5.77 Bereitstellung von Typ, Titel und Bild

Der Activity-Viewcontroller fragt alle verfügbaren Aktivitäten über die Methode canPerformWithActivityItems:, ob sie seine Einträge verarbeiten können. Die Klasse DiaryEntryExportActivity verarbeitet nur Einträge mit der Klasse DiaryEntry. Sie können diese Überprüfung mit Hilfe der Methode isKindOfClass: über eine Schleife oder ein Prädikat realisieren. Die App verwendet die zweite Möglichkeit, um die Vielseitigkeit von Prädikaten zu demonstrieren.

Wenn Sie Prädikate über filteredArrayUsingPredicate: auswerten, dürfen Sie auch Methoden der Objekte in dem Array verwenden, die einen Aufrufparameter haben. Beispielsweise filtern Sie folgendermaßen alle Objekte der Klasse DiaryEntry aus dem Array inItems:

NSPredicate *thePredicate = [NSPredicate predicateWithFormat: 
@"self isKindOfClass:%@", [DiaryEntry class]];
NSArray *theEntries =
[inItems filteredArrayUsingPredicate:thePredicate];

Listing 5.78 Elemente nach ihrer Klasse filtern

Über die Methode evaluateWithObject: können Sie auch ein Prädikat auf einem Objekt auswerten; diese Methode liefert Ihnen das Ergebnis als booleschen Wert. Sie können mit Hilfe des ANY-Operators entscheiden, ob irgendein Element in dem Array die Klasse DiaryEntry implementiert. Damit lässt sich die Methode canPerformWithActivityItems: recht einfach umsetzen:

- (BOOL)canPerformWithActivityItems:(NSArray *)inItems {
NSPredicate *thePredicate = [NSPredicate
predicateWithFormat:@"ANY self isKindOfClass:%@",
[DiaryEntry class]];

return [thePredicate evaluateWithObject:inItems];
}

Listing 5.79 Kann die Aktivität einen Eintrag verarbeiten?

Wenn der Nutzer einen Tagebucheintrag exportieren will, soll ihn die Aktivität vorher fragen, welche Teile er exportieren möchte und unter welchem Namen er sie im Dokumentenordner ablegen möchte. Dazu muss die Aktivität einen Dialog anzeigen; dafür sieht Apple einen modalen Viewcontroller vor, den Sie über die Methode activityViewController bereitstellen können. Wenn die Methode activityViewController der Aktivität nil liefert, ruft Cocoa Touch stattdessen die Methode performActivity auf.

Die Export-Aktivität lädt einen Navigationcontroller mit einem Viewcontroller aus dem Storyboard nach. Diese Initialisierungsschritte finden Sie in der Methode prepareWithActivityItems: der Klasse DiaryEntryExportActivity. Außerdem ermittelt diese Methode den Tagebucheintrag aus den Einträgen und übergibt ihn an den Viewcontroller für die Exportparameter.

- (void)prepareWithActivityItems:(NSArray *)inItems {
DiaryEntryExportActvity *theActivity =
[[DiaryEntryExportActvity alloc] init];
NSArray *theItems = self.activityItems;
UIActivityViewController *theController =
[[UIActivityViewController alloc]
initWithActivityItems:theItems
applicationActivities:@[theActivity]];

theActivity.storyboard = self.storyboard;
[self presentViewController:theController animated:YES
completion:NULL];
}

Listing 5.80 Vorbereitung des Viewcontrollers für die Exportparameter

Der Export-Viewcontroller zeigt das Bild, den Text und einen Button für die Tonaufnahme an, sofern der Tagebucheintrag diese Elemente enthält. Zu jedem Element zeigt er außerdem einen Schalter an, über den der Nutzer festlegen kann, ob er das entsprechende Element exportieren möchte. Außerdem gibt es ein Textfeld, um den Namen für die exportierten Dateien festzulegen. Abbildung 5.28 zeigt den Export-Viewcontroller in Aktion.

Abbildung

Abbildung 5.28 Der Dialog für die Exportparameter

Nach der Methode prepareWithActivityItems: zeigt der Activity-Viewcontroller den Export-Viewcontroller an, und dieser übernimmt das Regiment. Er initialisiert die Views für die Elemente und aktiviert beziehungsweise deaktiviert die Export-Schalter. Da das alles auf bereits besprochenen Themen beruht, verzichten wir hier auf eine genauere Darstellung.

Der Nutzer kann nur dann Dateien exportieren, wenn er einen Namen im Textfeld angegeben hat und mindestens einen Schalter aktiviert hat. Der Export-Viewcontroller soll nur in dieser Situation den Button zum Sichern freigeben und diesen ansonsten sperren. Dazu muss der Controller mitbekommen, wann sich der Zustand des Textfeldes und der Schalter ändert. Im Falle der Schalter reicht eine Action-Methode, die auf das Value-Changed-Ereignis lauscht. Auch das Textfeld kann über das Editing-Changed-Ereignis die Action-Methode benachrichtigen. Die Implementierung der Action-Methode finden Sie in Listing 5.81.

 – (IBAction)updateSaveButton {
self.navigationItem.leftBarButtonItem.enabled =
self.nameField.text.length > 0 &&
(self.imageSwitch.on || self.textSwitch.on ||
self.soundSwitch.on);
}

Listing 5.81 Aktivierung des Sichern-Buttons

Wenn Sie das Textfeld antippen, öffnet Cocoa Touch es, und Sie können einen Namen eingeben. Sobald Sie ein Zeichen eingeben haben, aktiviert die Action-Methode auch den Button zum Sichern. Soweit funktioniert alles wie gewünscht. Allerdings können Sie die Tastatur nicht mehr schließen, auch nicht über die ¢-Taste.

Um die ¢-Taste zum Schließen der der Tastatur zu verwenden, müssen Sie die Methode textFiledShouldReturn: des Textfeld-Delegates implementieren. Dort können Sie über die Methode endEditing: die Tastatur schließen. Über den Rückgabewert dieser Methode legen Sie fest, ob Cocoa Touch noch das Standardverhalten für die ¢-Taste ausführen soll. Da das nicht notwendig ist, geben Sie hier NO zurück.

- (BOOL)textFieldShouldReturn:(UITextField *)inTextField {
[self updateSaveButton];
[self.view endEditing:YES];
return NO;
}

Listing 5.82 Schließen der Tastatur beim Drücken der Return-Taste

Für die Implementierung fehlen jetzt nur noch das Sichern der Daten und Schließen des Export-Viewcontrollers. Die Sicherung erfolgt in einem Unterverzeichnis des Dokumentenordners der App. Das Unterverzeichnis bekommt dabei den Namen, den der Nutzer in das Textfeld eingegeben hat. Dazu legt die App vor dem Sichern dieses Verzeichnis über die Methode createDirectoryAtPath:withIntermediateDirectories:attributes:error: der Klasse NSFileManager an.

NSFileManager *theManager = 
[NSFileManager defaultManager];
NSString *thePath =
[theManager applicationDocumentsDirectory];
NSError *theError = nil;

thePath = [thePath stringByAppendingPathComponent:
self.nameField.text];
if([theManager createDirectoryAtPath:thePath
withIntermediateDirectories:YES attributes:nil
error:&theError]) {
// Sichern der Daten
}
else {
NSLog(@"save: error=%@", theError);
}

Listing 5.83 Verzeichnis für den Export anlegen

Das Sichern ist für alle Einträge relativ ähnlich. Während der Viewcontroller die Daten der Medien über writeToFile:atomically: sichert, verwendet er für den Text die Methode writeToFile:atomically:encoding:error: der Klasse NSString. Bei beiden Methoden bewirkt der Wert YES für den Parameter atomically, dass die Methode die Daten atomar schreibt; dabei erzeugt die Methode erst eine Zwischendatei mit den Daten, und wenn sie das erfolgreich geschafft hat, benennt sie die Datei um, und zwar mit dem Namen im ersten Parameter.

DiaryEntry *theEntry = self.diaryEntry;

if(self.imageSwitch.on) {
NSData *theImage = [[theEntry
mediumForType:kMediumTypeImage] data];
NSString *theFile = [thePath
stringByAppendingPathComponent:@"image.jpg"];

[theImage writeToFile:theFile atomically:YES];
}
if(self.textSwitch.on) {
NSString *theFile = [thePath
stringByAppendingPathComponent:@"text.txt"];

[theEntry.text writeToFile:theFile atomically:YES
encoding:NSUTF8StringEncoding error:NULL];
}
if(self.soundSwitch.on) {
NSData *theAudio = [[theEntry
mediumForType:kMediumTypeAudio] data];
NSString *theFile = [thePath
stringByAppendingPathComponent:@"sound.caf"];

[theAudio writeToFile:theFile atomically:YES];
}
}

Listing 5.84 Sichern der Daten eines Tagebucheintrags

Das Schließen des Viewcontrollers muss über die Methode activityDidFinish: der Aktivität erfolgen, da diese Methode der Aktivität das Ende der Operation anzeigt. Dabei gibt der Parameter YES an, dass der Viewcontroller die Operation erfolgreich durchgeführt hat, und NO zeigt einen Fehler oder einen Abbruch an. Listing 5.85 zeigt die Integration der Aufrufe dieser Methode in die Action-Methoden save: und cancel: des Export-Viewcontrollers.

- (IBAction)save:(id)inSender {
...;
if([theManager createDirectoryAtPath:...]) {
...;
[self.activity activityDidFinish:YES];
}
else {
NSLog(@"save: error=%@", theError);
[self.activity activityDidFinish:NO];
}
}

- (IBAction)cancel:(id)inSender {

[self.activity activityDidFinish:NO];
}


Listing 5.85 Beenden der Aktivität

Damit haben Sie die wesentlichen Schritte für die Implementierung einer eigenen Aktivität kennengelernt, für die Sie eine Unterklasse der Klasse UIActivity erstellen müssen. Den Ablauf der Operation implementieren Sie dann auf Basis von Viewcontrollern. Alternativ können Sie über die Methode performActivity auch Implementierungen realisieren, bei denen keine Nutzinteraktionen notwendig sind.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.

>> Zum Feedback-Formular
<< zurück




Copyright © Rheinwerk Verlag GmbH, Bonn 2014
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de


  Zum Katalog
Zum Katalog: Apps programmieren für iPhone und iPad






Apps programmieren für iPhone und iPad
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Apps programmieren für iPhone und iPad






Apps programmieren für iPhone und iPad


Zum Katalog: Einstieg in Objective-C 2.0 und Cocoa






Einstieg in Objective-C 2.0 und Cocoa


Zum Katalog: Spieleprogrammierung mit Android Studio






Spieleprogrammierung mit Android Studio


Zum Katalog: Android 5






Android 5


Zum Katalog: iPhone und iPad-Apps entwickeln






iPhone und iPad-Apps entwickeln


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo