formacion en movilidad: conceptos de desarrollo en ios (iv)
DESCRIPTION
En esta cuarta sesión formativa, impartida por Sergi Hernando, CTO de Mobivery, se trataron los siguientes conceptos: Alert, Search Bar, Action Sheet, Activity, Customizing y TestingTRANSCRIPT
![Page 1: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/1.jpg)
Televisió de CatalunyaFormación en movilidad
Conceptos de desarrollo en iOS4ª sesión mayo 2013
1
![Page 2: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/2.jpg)
Qué veremos hoy
AlertSearch Bar
Action SheetActivity
Customizing
Testing
2
![Page 3: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/3.jpg)
AlertUIAlertView
“Use the UIAlertView class to display an alert message to the user”
3
![Page 4: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/4.jpg)
AlertUIAlertView
// MasterViewController.m
- (void)insertNewObject:(NSDictionary *)values{ // ... if (![context save:&error]) { // ... } else { UIAlertView *notice = [[UIAlertView alloc] initWithTitle:@"Nuevo vídeo" message:@"Se a creado un nuevo vídeo correctamente" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
[notice show];}
4
![Page 5: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/5.jpg)
AlertUIAlertView
// MasterViewController.m
- (void)insertNewObject:(NSDictionary *)values{ // ... if (![context save:&error]) { // ... } else { UIAlertView *notice = [[UIAlertView alloc] initWithTitle:@"Nuevo vídeo" message:@"Se a creado un nuevo vídeo correctamente" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
[notice show];}
5
![Page 6: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/6.jpg)
AlertUIAlertView
// MasterViewController.m
- (void)insertNewObject:(NSDictionary *)values{ // ... if (![context save:&error]) { // ... } else { UIAlertView *notice = [[UIAlertView alloc] initWithTitle:@"Nuevo vídeo" message:@"Se a creado un nuevo vídeo correctamente" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:@"Deshacer", nil];
[notice show];}
6
![Page 7: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/7.jpg)
AlertUIAlertView
// MasterViewController.m
- (void)insertNewObject:(NSDictionary *)values{ // ... if (![context save:&error]) { // ... } else { UIAlertView *notice = [[UIAlertView alloc] initWithTitle:@"Nuevo vídeo" message:@"Se a creado un nuevo vídeo correctamente" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:@"Deshacer", nil];
[notice show];}
7
![Page 8: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/8.jpg)
“The UISearchBar object does not actually perform any searches. You use the
UISearchBarDelegate protocol to implement the actions when text is entered and buttons
are clicked”
Search Bar
8
![Page 9: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/9.jpg)
Search BarUISearchBar
9
![Page 10: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/10.jpg)
Search BarUISearchBar
Placeholder ‘Buscar por título o autor’Marcar ‘Shows Cancel Button’Seleccionar ‘Correction: No’
Conectar ‘Search Bar’ delegate con ‘Master View Controller’
10
![Page 11: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/11.jpg)
Search BarUISearchBarDelegate
// MasterViewController.m
@interface MasterViewController ()
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;- (void)performSearch:(NSString *)searchText;
@end
11
![Page 12: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/12.jpg)
Search BarUISearchBarDelegate
// MasterViewController.m
@interface MasterViewController ()
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;- (void)performSearch:(NSString *)searchText;
@end
Declarar método privado performSearch:
12
![Page 13: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/13.jpg)
Search BarUISearchBarDelegate
// MasterViewController.m
@interface MasterViewController ()
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;- (void)performSearch:(NSString *)searchText;
@end
- (NSFetchedResultsController *)fetchedResultsController { // ...
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
// ...}
13
![Page 14: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/14.jpg)
Search BarUISearchBarDelegate
// MasterViewController.m
@interface MasterViewController ()
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;- (void)performSearch:(NSString *)searchText;
@end
- (NSFetchedResultsController *)fetchedResultsController { // ...
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
// ...}
Anular uso de caché en initWithFetchRequest:
14
![Page 15: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/15.jpg)
Search BarUISearchBarDelegate
// MasterViewController.m
#pragma mark - UISearchBarDelegate
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
}
Acciones parabotones ‘Search’ y ‘Cancel’ e introducción de texto
15
![Page 16: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/16.jpg)
Search BarUISearchBarDelegate
// MasterViewController.m
#pragma mark - UISearchBarDelegate
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar { [self performSearch:searchBar.text]; [searchBar resignFirstResponder]; [self.tableView reloadData];}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
}
searchBarSearchButtonClicked:
16
![Page 17: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/17.jpg)
Search BarUISearchBarDelegate
// MasterViewController.m
#pragma mark - UISearchBarDelegate
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar { [self performSearch:searchBar.text]; [searchBar resignFirstResponder]; [self.tableView reloadData];}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { [searchBar resignFirstResponder];}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
}
searchBarCancelButtonClicked:
17
![Page 18: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/18.jpg)
Search BarUISearchBarDelegate
// MasterViewController.m
#pragma mark - UISearchBarDelegate
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar { [self performSearch:searchBar.text]; [searchBar resignFirstResponder]; [self.tableView reloadData];}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { [searchBar resignFirstResponder];}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { [self performSearch:searchText];}
searchBar:textDidChange:
18
![Page 19: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/19.jpg)
Search BarUISearchBarDelegate + Core Data
// MasterViewController.m
#pragma mark - Private
- (void)performSearch:(NSString *)searchText { NSPredicate *predicate; NSError *error = nil;
if(searchText && searchText.length > 0) { predicate = [NSPredicate predicateWithFormat: @"title contains[cd] %@ or author contains[cd] %@", searchText, searchText]; [self.fetchedResultsController.fetchRequest setPredicate:predicate]; } else { [self.fetchedResultsController.fetchRequest setPredicate:nil]; }
if(![self.fetchedResultsController performFetch:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } [self.tableView reloadData];}
Implementar método privado performSearch:
19
![Page 20: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/20.jpg)
Search BarUISearchBarDelegate + Core Data
// MasterViewController.m
#pragma mark - Private
- (void)performSearch:(NSString *)searchText { NSPredicate *predicate; NSError *error = nil;
if(searchText && searchText.length > 0) { predicate = [NSPredicate predicateWithFormat: @"title contains[cd] %@ or author contains[cd] %@", searchText, searchText]; [self.fetchedResultsController.fetchRequest setPredicate:predicate]; } else { [self.fetchedResultsController.fetchRequest setPredicate:nil]; }
if(![self.fetchedResultsController performFetch:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } [self.tableView reloadData];}
contains[cd] is case and diacritic insensitive
20
![Page 21: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/21.jpg)
Search BarUISearchBarDelegate + Core Data
// MasterViewController.m
#pragma mark - Private
- (void)performSearch:(NSString *)searchText { NSPredicate *predicate; NSError *error = nil;
if(searchText && searchText.length > 0) { predicate = [NSPredicate predicateWithFormat: @"title contains[cd] %@ or author contains[cd] %@", searchText, searchText]; [self.fetchedResultsController.fetchRequest setPredicate:predicate]; } else { [self.fetchedResultsController.fetchRequest setPredicate:nil]; }
if(![self.fetchedResultsController performFetch:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } [self.tableView reloadData];}
Anular criterios = Buscar todos
21
![Page 22: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/22.jpg)
Search BarUISearchBarDelegate
22
![Page 23: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/23.jpg)
“Use the UIActionSheet class to present the user with a set of alternatives for how to
proceed with a given task”
Action Sheet
23
![Page 24: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/24.jpg)
Action Sheet
24
![Page 25: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/25.jpg)
Action Sheet
Seleccionar ‘Identifier : Action’
25
![Page 26: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/26.jpg)
Action Sheet
Seleccionar ‘Identifier : Action’
Conectar ‘Bar Button Item - Action’ con Detail View ControllerConnection: ActionName: shareByEmail
Type: id
26
![Page 27: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/27.jpg)
Action Sheet
TARGETS : MyVideos : Build Phases : Link With Binary LibrariesMessageUI.framework
27
![Page 28: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/28.jpg)
Action SheetUIActionSheet
// DetailViewController.h
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>#import <MessageUI/MFMailComposeViewController.h>
@interface DetailViewController : UIViewController < UISplitViewControllerDelegate, UIWebViewDelegate, UIActionSheetDelegate, MFMailComposeViewControllerDelegate>
// ...
@end
Importar MessageUI.h y MFMailComposeViewController.h
28
![Page 29: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/29.jpg)
Action SheetUIActionSheet
// DetailViewController.h
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>#import <MessageUI/MFMailComposeViewController.h>
@interface DetailViewController : UIViewController < UISplitViewControllerDelegate, UIWebViewDelegate, UIActionSheetDelegate, MFMailComposeViewControllerDelegate>
// ...
@end
UIActionSheetDelegate
29
![Page 30: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/30.jpg)
// DetailViewController.h
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>#import <MessageUI/MFMailComposeViewController.h>
@interface DetailViewController : UIViewController < UISplitViewControllerDelegate, UIWebViewDelegate, UIActionSheetDelegate, MFMailComposeViewControllerDelegate>
// ...
@end
Action SheetUIActionSheet
MFMailComposeViewControllerDelegate
30
![Page 31: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/31.jpg)
Action SheetUIActionSheet
// DetailViewController.m
- (IBAction)shareByEmail:(id)sender { UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Compartir" delegate:self cancelButtonTitle:@"Cancelar" destructiveButtonTitle:nil otherButtonTitles:@"Email", nil];
[actionSheet showInView:self.view];}
initWithTitle:
31
![Page 32: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/32.jpg)
Action SheetUIActionSheet
showInView:
// DetailViewController.m
- (IBAction)shareByEmail:(id)sender { UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Compartir" delegate:self cancelButtonTitle:@"Cancelar" destructiveButtonTitle:nil otherButtonTitles:@"Email", nil];
[actionSheet showInView:self.view];}
32
![Page 33: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/33.jpg)
Action SheetUIActionSheetDelegate
// DetailViewController.m
#pragma mark - UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {}
@end
Implementar actionSheet:clickedButtonAtIndex:
33
![Page 34: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/34.jpg)
Action SheetUIActionSheetDelegate
// DetailViewController.m
#pragma mark - UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { if(buttonIndex == 0 && [MFMailComposeViewController canSendMail]) { NSString *subject = @"Mira este vídeo!"; NSArray *recipients = @[ @"[email protected]" ]; NSString *url = self.webView.request.URL.absoluteString; NSString *body = [NSString stringWithFormat:@"Échale un ojo: %@", url]; }}
@end
Parámetros del email
34
![Page 35: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/35.jpg)
Action SheetUIActionSheetDelegate
// DetailViewController.m
#pragma mark - UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { if(buttonIndex == 0 && [MFMailComposeViewController canSendMail]) { NSString *subject = @"Mira este vídeo!"; NSArray *recipients = @[ @"[email protected]" ]; NSString *url = self.webView.request.URL.absoluteString; NSString *body = [NSString stringWithFormat:@"Échale un ojo: %@", url]; MFMailComposeViewController *mailComposer = [[MFMailComposeViewController alloc] init]; }}
@end
Instanciar mail compose view controller
35
![Page 36: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/36.jpg)
Action SheetUIActionSheetDelegate
// DetailViewController.m
#pragma mark - UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { if(buttonIndex == 0 && [MFMailComposeViewController canSendMail]) { NSString *subject = @"Mira este vídeo!"; NSArray *recipients = @[ @"[email protected]" ]; NSString *url = self.webView.request.URL.absoluteString; NSString *body = [NSString stringWithFormat:@"Échale un ojo: %@", url]; MFMailComposeViewController *mailComposer = [[MFMailComposeViewController alloc] init]; [mailComposer setSubject:subject]; [mailComposer setToRecipients:recipients]; [mailComposer setMessageBody:body isHTML:YES]; [mailComposer setMailComposeDelegate:self]; }}
@end
Asignar parámetros a mail compose view controller
36
![Page 37: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/37.jpg)
Action SheetUIActionSheetDelegate
// DetailViewController.m
#pragma mark - UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { if(buttonIndex == 0 && [MFMailComposeViewController canSendMail]) { NSString *subject = @"Mira este vídeo!"; NSArray *recipients = @[ @"[email protected]" ]; NSString *url = self.webView.request.URL.absoluteString; NSString *body = [NSString stringWithFormat:@"Échale un ojo: %@", url]; MFMailComposeViewController *mailComposer = [[MFMailComposeViewController alloc] init]; [mailComposer setSubject:subject]; [mailComposer setToRecipients:recipients]; [mailComposer setMessageBody:body isHTML:YES]; [mailComposer setMailComposeDelegate:self]; [self presentViewController:mailComposer animated:YES completion:nil]; }}
@end
Mostrar mail compose view controller
37
![Page 38: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/38.jpg)
Action SheetMFMailComposeViewControllerDelegate
Implementar mailComposeController :didFinishWithResult:error :
#pragma mark - MFMailComposeViewControllerDelegate
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error{
}
38
![Page 39: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/39.jpg)
Action SheetMFMailComposeViewControllerDelegate
Cerrar mail compose view controller* [mailComposer setMailComposeDelegate:self];
#pragma mark - MFMailComposeViewControllerDelegate
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error{! [self dismissViewControllerAnimated:YES completion:nil];}
39
![Page 40: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/40.jpg)
ActivityUIActivityViewController
// DetailViewController.m
- (IBAction)shareByEmail:(id)sender {
}
40
![Page 41: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/41.jpg)
ActivityUIActivityViewController
// DetailViewController.m
- (IBAction)shareByEmail:(id)sender { NSString *url = self.webView.request.URL.absoluteString; NSString *body = [NSString stringWithFormat:@"Échale un ojo a este vídeo: %@", url];}
41
![Page 42: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/42.jpg)
ActivityUIActivityViewController
// DetailViewController.m
- (IBAction)shareByEmail:(id)sender { NSString *url = self.webView.request.URL.absoluteString; NSString *body = [NSString stringWithFormat:@"Échale un ojo a este vídeo: %@", url];
UIActivityViewController *activity; activity = [[UIActivityViewController alloc] initWithActivityItems:@[body] applicationActivities:nil];}
42
![Page 43: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/43.jpg)
ActivityUIActivityViewController
// DetailViewController.m
- (IBAction)shareByEmail:(id)sender { NSString *url = self.webView.request.URL.absoluteString; NSString *body = [NSString stringWithFormat:@"Échale un ojo a este vídeo: %@", url];
UIActivityViewController *activity; activity = [[UIActivityViewController alloc] initWithActivityItems:@[body] applicationActivities:nil];
activity.excludedActivityTypes = @[UIActivityTypeMessage, UIActivityTypeMail, UIActivityTypePostToWeibo];}
43
![Page 44: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/44.jpg)
ActivityUIActivityViewController
// DetailViewController.m
- (IBAction)shareByEmail:(id)sender { NSString *url = self.webView.request.URL.absoluteString; NSString *body = [NSString stringWithFormat:@"Échale un ojo a este vídeo: %@", url];
UIActivityViewController *activity; activity = [[UIActivityViewController alloc] initWithActivityItems:@[body] applicationActivities:nil];
activity.excludedActivityTypes = @[UIActivityTypeMessage, UIActivityTypeMail, UIActivityTypePostToWeibo];
[self presentViewController:activity animated:YES completion:nil];}
44
![Page 45: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/45.jpg)
Coffee Break!
45
![Page 46: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/46.jpg)
CustomizingUIAppearance
// AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // ...
return YES;}
application:didFinishLaunchingWithOptions:
46
![Page 47: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/47.jpg)
CustomizingUIAppearance
// AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // ...
[[UINavigationBar appearance] setTintColor:[UIColor blackColor]];
return YES;}
UINavigationBar
47
![Page 48: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/48.jpg)
CustomizingUIAppearance
// AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // ...
[[UINavigationBar appearance] setTintColor:[UIColor blackColor]]; [[UIBarButtonItem appearance] setTintColor:[UIColor blackColor]];
return YES;}
UIBarButtonItem
48
![Page 49: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/49.jpg)
CustomizingUIAppearance
// AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // ...
[[UINavigationBar appearance] setTintColor:[UIColor blackColor]]; [[UIBarButtonItem appearance] setTintColor:[UIColor blackColor]]; [[UISearchBar appearance] setTintColor:[UIColor blackColor]];
return YES;}
UISearchBar
49
![Page 50: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/50.jpg)
Customizing
→
+
Bar Button Item+
Round Rect Button
50
![Page 51: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/51.jpg)
Customizing
→
+
Type: CustomTitle: vacío
Image: comun-back-button.png
51
![Page 52: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/52.jpg)
Customizing
→
52
![Page 53: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/53.jpg)
Customizing
53
![Page 54: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/54.jpg)
Customizing
54
![Page 55: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/55.jpg)
Customizing
// VideoCell.h
#import <UIKit/UIKit.h>
@interface VideoCell : UITableViewCell
@property (nonatomic, strong) IBOutlet UILabel *titleLabel;@property (nonatomic, strong) IBOutlet UILabel *authorLabel;
@end
55
![Page 56: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/56.jpg)
Customizing
Table View Cell - Style: CustomCustom Class - Class: VideoCell
56
![Page 57: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/57.jpg)
Customizing
57
![Page 58: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/58.jpg)
Customizing
Conectar labels con titleLabel y authorLabel
58
![Page 59: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/59.jpg)
Customizing// MasterViewController.m
#import "VideoCell.h"
// ...
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath{ NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath]; cell.textLabel.text = [object valueForKey:@"title"];}
59
![Page 60: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/60.jpg)
Customizing// MasterViewController.m
#import "VideoCell.h"
// ...
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath{ NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath]; if([cell isKindOfClass:[VideoCell class]]) { VideoCell *videoCell = (VideoCell *)cell; videoCell.titleLabel.text = [object valueForKey:@"title"]; videoCell.authorLabel.text = [object valueForKey:@"author"]; } else { cell.textLabel.text = [object valueForKey:@"title"]; }}
60
![Page 61: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/61.jpg)
Testing
OCUnit
61
![Page 62: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/62.jpg)
TestingOCUnit
validate:
“Devuelve ‘cierto’ si título, autor y URL están informados
y URL tiene el formato correcto.Devuelve ‘falso’ en caso contrario.”
62
![Page 63: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/63.jpg)
TestingOCUnit
// MyVideosTests.m
- (void)testValidateMandatoryFields {}
63
![Page 64: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/64.jpg)
TestingOCUnit
// MyVideosTests.m
- (void)testValidateMandatoryFields { MasterViewController *viewController = [MasterViewController new]; NSDictionary *values = @{ @"title": @"Murmuration", @"author": @"Islands & Rivers", @"url": @"http://vimeo.com/m/31158841" };}
64
![Page 65: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/65.jpg)
TestingOCUnit
// MyVideosTests.m
- (void)testValidateMandatoryFields { MasterViewController *viewController = [MasterViewController new]; NSDictionary *values = @{ @"title": @"Murmuration", @"author": @"Islands & Rivers", @"url": @"http://vimeo.com/m/31158841" }; BOOL result = [viewController validate:values];}
65
![Page 66: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/66.jpg)
TestingOCUnit
// MyVideosTests.m
- (void)testValidateMandatoryFields { MasterViewController *viewController = [MasterViewController new]; NSDictionary *values = @{ @"title": @"Murmuration", @"author": @"Islands & Rivers", @"url": @"http://vimeo.com/m/31158841" }; BOOL result = [viewController validate:values];! STAssertTrue(result, @"validate: returned false");}
66
![Page 67: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/67.jpg)
TestingOCUnit
// MyVideosTests.m
- (void)testValidateMandatoryFields { MasterViewController *viewController = [MasterViewController new]; NSDictionary *values = @{ @"title": @"Murmuration", @"author": @"Islands & Rivers", @"url": @"http://vimeo.com/m/31158841" }; BOOL result = [viewController validate:values];! STAssertTrue(result, @"validate: returned false");}
“result” should be true. validate: returned false
67
![Page 68: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/68.jpg)
TestingOCUnit
// MyVideosTests.m
- (void)testValidateMandatoryFields { MasterViewController *viewController = [MasterViewController new]; NSDictionary *values = @{ @"title": @"Murmuration", @"author": @"Islands & Rivers", @"url": @"http://vimeo.com/m/31158841" }; BOOL result = [viewController validate:values];! STAssertTrue(result, @"validate: returned false");}
// MasterViewController.m
- (BOOL)validate:(NSDictionary *)values {! return NO;}
“result” should be true. validate: returned false
68
![Page 69: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/69.jpg)
TestingOCUnit
// MyVideosTests.m
- (void)testValidateMandatoryFields { MasterViewController *viewController = [MasterViewController new]; NSDictionary *values = @{ @"title": @"Murmuration", @"author": @"Islands & Rivers", @"url": @"http://vimeo.com/m/31158841" }; BOOL result = [viewController validate:values];! STAssertTrue(result, @"validate: returned false");}
// MasterViewController.m
- (BOOL)validate:(NSDictionary *)values { return([values objectForKey:@"title"] && [values objectForKey:@"author"] && [values objectForKey:@"url"]);}
69
![Page 70: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/70.jpg)
TestingOCUnit
// MyVideosTests.m
- (void)testValidateMandatoryFields { MasterViewController *viewController = [MasterViewController new]; NSDictionary *values = @{ @"title": @"Murmuration", @"author": @"Islands & Rivers", @"url": @"http://vimeo.com/m/31158841" }; BOOL result = [viewController validate:values];! STAssertTrue(result, @"validate: returned false");}
// MasterViewController.m
- (BOOL)validate:(NSDictionary *)values { return([values objectForKey:@"title"] && [values objectForKey:@"author"] && [values objectForKey:@"url"]);}
Test Case ‘-[MyVideosTests testValidateMandatoryFields]’ passed
70
![Page 71: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/71.jpg)
TestingOCUnit
// MyVideosTests.m
- (void)testValidatetMalformedURL { MasterViewController *viewController = [MasterViewController new]; NSDictionary *values = @{ @"title": @"Murmuration", @"author": @"Islands & Rivers", @"url": @"not an url" }; BOOL result = [viewController validate:values];! STAssertFalse(result, @"validate: returned true");}
71
![Page 72: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/72.jpg)
TestingOCUnit
// MyVideosTests.m
- (void)testValidatetMalformedURL { MasterViewController *viewController = [MasterViewController new]; NSDictionary *values = @{ @"title": @"Murmuration", @"author": @"Islands & Rivers", @"url": @"not an url" }; BOOL result = [viewController validate:values];! STAssertFalse(result, @"validate: returned true");}
“result” should be false. validate: returned true
72
![Page 73: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/73.jpg)
TestingOCUnit
// MyVideosTests.m
- (void)testValidatetMalformedURL { MasterViewController *viewController = [MasterViewController new]; NSDictionary *values = @{ @"title": @"Murmuration", @"author": @"Islands & Rivers", @"url": @"not an url" }; BOOL result = [viewController validate:values];! STAssertFalse(result, @"validate: returned true");}
// MasterViewController.m
- (BOOL)validate:(NSDictionary *)values { return([values objectForKey:@"title"] && [values objectForKey:@"author"] && [values objectForKey:@"url"] && [NSURL URLWithString:[values objectForKey:@"url"]]);}
73
![Page 74: Formacion en movilidad: Conceptos de desarrollo en iOS (IV)](https://reader036.vdocument.in/reader036/viewer/2022062511/54bb81c54a7959647a8b45fb/html5/thumbnails/74.jpg)
TestingOCUnit
// MyVideosTests.m
- (void)testValidatetMalformedURL { MasterViewController *viewController = [MasterViewController new]; NSDictionary *values = @{ @"title": @"Murmuration", @"author": @"Islands & Rivers", @"url": @"not an url" }; BOOL result = [viewController validate:values];! STAssertFalse(result, @"validate: returned true");}
// MasterViewController.m
- (BOOL)validate:(NSDictionary *)values { return([values objectForKey:@"title"] && [values objectForKey:@"author"] && [values objectForKey:@"url"] && [NSURL URLWithString:[values objectForKey:@"url"]]);}
Test Case ‘-[MyVideosTests testValidateMalformedURL]’ passed
74