Formacion en movilidad: Conceptos de desarrollo en iOS (IV)

413 views

Published on

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 Testing

Published in: Technology, Business
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
413
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
3
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Formacion en movilidad: Conceptos de desarrollo en iOS (IV)

  1. 1. Televisió de CatalunyaFormación en movilidadConceptos de desarrollo en iOS4ª sesión mayo 20131
  2. 2. Qué veremos hoyAlertSearch BarAction SheetActivityCustomizingTesting2
  3. 3. AlertUIAlertView“Use the UIAlertView class to display an alertmessage to the user”3
  4. 4. 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:nilcancelButtonTitle:@"OK"otherButtonTitles:nil, nil];[notice show];}4
  5. 5. 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:nilcancelButtonTitle:@"OK"otherButtonTitles:nil, nil];[notice show];}5
  6. 6. 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:nilcancelButtonTitle:@"OK"otherButtonTitles:@"Deshacer", nil];[notice show];}6
  7. 7. 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:nilcancelButtonTitle:@"OK"otherButtonTitles:@"Deshacer", nil];[notice show];}7
  8. 8. “The UISearchBar object does not actuallyperform any searches.You use theUISearchBarDelegate protocol to implementthe actions when text is entered and buttonsare clicked”Search Bar8
  9. 9. Search BarUISearchBar9
  10. 10. Search BarUISearchBarPlaceholder ‘Buscar por título o autor’Marcar ‘Shows Cancel Button’Seleccionar ‘Correction: No’Conectar ‘Search Bar’ delegate con ‘MasterView Controller’10
  11. 11. Search BarUISearchBarDelegate// MasterViewController.m@interface MasterViewController ()- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;- (void)performSearch:(NSString *)searchText;@end11
  12. 12. Search BarUISearchBarDelegate// MasterViewController.m@interface MasterViewController ()- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;- (void)performSearch:(NSString *)searchText;@endDeclarar método privado performSearch:12
  13. 13. 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:fetchRequestmanagedObjectContext:self.managedObjectContextsectionNameKeyPath:nilcacheName:nil];// ...}13
  14. 14. 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:fetchRequestmanagedObjectContext:self.managedObjectContextsectionNameKeyPath:nilcacheName:nil];// ...}Anular uso de caché en initWithFetchRequest:14
  15. 15. 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 texto15
  16. 16. 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
  17. 17. 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
  18. 18. 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
  19. 19. 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
  20. 20. 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 insensitive20
  21. 21. 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 todos21
  22. 22. Search BarUISearchBarDelegate22
  23. 23. “Use the UIActionSheet class to present theuser with a set of alternatives for how toproceed with a given task”Action Sheet23
  24. 24. Action Sheet24
  25. 25. Action SheetSeleccionar ‘Identifier:Action’25
  26. 26. Action SheetSeleccionar ‘Identifier:Action’Conectar ‘Bar Button Item - Action’ con DetailView ControllerConnection:ActionName: shareByEmailType: id26
  27. 27. Action SheetTARGETS : MyVideos : Build Phases : Link With Binary LibrariesMessageUI.framework27
  28. 28. Action SheetUIActionSheet// DetailViewController.h#import <UIKit/UIKit.h>#import <MessageUI/MessageUI.h>#import <MessageUI/MFMailComposeViewController.h>@interface DetailViewController : UIViewController <UISplitViewControllerDelegate, UIWebViewDelegate,UIActionSheetDelegate, MFMailComposeViewControllerDelegate>// ...@endImportar MessageUI.h y MFMailComposeViewController.h28
  29. 29. Action SheetUIActionSheet// DetailViewController.h#import <UIKit/UIKit.h>#import <MessageUI/MessageUI.h>#import <MessageUI/MFMailComposeViewController.h>@interface DetailViewController : UIViewController <UISplitViewControllerDelegate, UIWebViewDelegate,UIActionSheetDelegate, MFMailComposeViewControllerDelegate>// ...@endUIActionSheetDelegate29
  30. 30. // DetailViewController.h#import <UIKit/UIKit.h>#import <MessageUI/MessageUI.h>#import <MessageUI/MFMailComposeViewController.h>@interface DetailViewController : UIViewController <UISplitViewControllerDelegate, UIWebViewDelegate,UIActionSheetDelegate, MFMailComposeViewControllerDelegate>// ...@endAction SheetUIActionSheetMFMailComposeViewControllerDelegate30
  31. 31. Action SheetUIActionSheet// DetailViewController.m- (IBAction)shareByEmail:(id)sender {UIActionSheet *actionSheet = [[UIActionSheet alloc]initWithTitle:@"Compartir"delegate:selfcancelButtonTitle:@"Cancelar"destructiveButtonTitle:nilotherButtonTitles:@"Email", nil];[actionSheet showInView:self.view];}initWithTitle:31
  32. 32. Action SheetUIActionSheetshowInView:// DetailViewController.m- (IBAction)shareByEmail:(id)sender {UIActionSheet *actionSheet = [[UIActionSheet alloc]initWithTitle:@"Compartir"delegate:selfcancelButtonTitle:@"Cancelar"destructiveButtonTitle:nilotherButtonTitles:@"Email", nil];[actionSheet showInView:self.view];}32
  33. 33. Action SheetUIActionSheetDelegate// DetailViewController.m#pragma mark - UIActionSheetDelegate- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {}@endImplementar actionSheet:clickedButtonAtIndex:33
  34. 34. 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 = @[ @"sergi.hernando@mobivery.com" ];NSString *url = self.webView.request.URL.absoluteString;NSString *body = [NSString stringWithFormat:@"Échale un ojo: %@", url];}}@endParámetros del email34
  35. 35. 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 = @[ @"sergi.hernando@mobivery.com" ];NSString *url = self.webView.request.URL.absoluteString;NSString *body = [NSString stringWithFormat:@"Échale un ojo: %@", url];MFMailComposeViewController *mailComposer = [[MFMailComposeViewController alloc] init];}}@endInstanciar mail compose view controller35
  36. 36. 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 = @[ @"sergi.hernando@mobivery.com" ];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];}}@endAsignar parámetros a mail compose view controller36
  37. 37. 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 = @[ @"sergi.hernando@mobivery.com" ];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];}}@endMostrar mail compose view controller37
  38. 38. Action SheetMFMailComposeViewControllerDelegateImplementar mailComposeController:didFinishWithResult:error:#pragma mark - MFMailComposeViewControllerDelegate- (void)mailComposeController:(MFMailComposeViewController *)controllerdidFinishWithResult:(MFMailComposeResult)result error:(NSError *)error{}38
  39. 39. Action SheetMFMailComposeViewControllerDelegateCerrar mail compose view controller* [mailComposer setMailComposeDelegate:self];#pragma mark - MFMailComposeViewControllerDelegate- (void)mailComposeController:(MFMailComposeViewController *)controllerdidFinishWithResult:(MFMailComposeResult)result error:(NSError *)error{! [self dismissViewControllerAnimated:YES completion:nil];}39
  40. 40. ActivityUIActivityViewController// DetailViewController.m- (IBAction)shareByEmail:(id)sender {}40
  41. 41. 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
  42. 42. 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
  43. 43. 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
  44. 44. 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
  45. 45. Coffee Break!45
  46. 46. CustomizingUIAppearance// AppDelegate.m- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions {// ...return YES;}application:didFinishLaunchingWithOptions:46
  47. 47. CustomizingUIAppearance// AppDelegate.m- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions {// ...[[UINavigationBar appearance] setTintColor:[UIColor blackColor]];return YES;}UINavigationBar47
  48. 48. CustomizingUIAppearance// AppDelegate.m- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions {// ...[[UINavigationBar appearance] setTintColor:[UIColor blackColor]];[[UIBarButtonItem appearance] setTintColor:[UIColor blackColor]];return YES;}UIBarButtonItem48
  49. 49. CustomizingUIAppearance// AppDelegate.m- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions {// ...[[UINavigationBar appearance] setTintColor:[UIColor blackColor]];[[UIBarButtonItem appearance] setTintColor:[UIColor blackColor]];[[UISearchBar appearance] setTintColor:[UIColor blackColor]];return YES;}UISearchBar49
  50. 50. Customizing→+Bar Button Item+Round Rect Button50
  51. 51. Customizing+Type: CustomTitle: vacíoImage: comun-back-button.png51
  52. 52. Customizing→52
  53. 53. Customizing53
  54. 54. Customizing54
  55. 55. Customizing// VideoCell.h#import <UIKit/UIKit.h>@interface VideoCell : UITableViewCell@property (nonatomic, strong) IBOutlet UILabel *titleLabel;@property (nonatomic, strong) IBOutlet UILabel *authorLabel;@end55
  56. 56. CustomizingTableView Cell - Style: CustomCustom Class - Class:VideoCell56
  57. 57. Customizing57
  58. 58. CustomizingConectar labels con titleLabel y authorLabel58
  59. 59. 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
  60. 60. 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
  61. 61. TestingOCUnit61
  62. 62. TestingOCUnitvalidate:“Devuelve ‘cierto’ si título, autor y URL estáninformadosy URL tiene el formato correcto.Devuelve ‘falso’ en caso contrario.”62
  63. 63. TestingOCUnit// MyVideosTests.m- (void)testValidateMandatoryFields {}63
  64. 64. TestingOCUnit// MyVideosTests.m- (void)testValidateMandatoryFields {MasterViewController *viewController = [MasterViewController new];NSDictionary *values = @{@"title": @"Murmuration",@"author": @"Islands & Rivers",@"url": @"http://vimeo.com/m/31158841"};}64
  65. 65. 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
  66. 66. 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
  67. 67. 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 false67
  68. 68. 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 false68
  69. 69. 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
  70. 70. 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]’ passed70
  71. 71. 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
  72. 72. 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 true72
  73. 73. 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
  74. 74. 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]’ passed74

×