Más contenido relacionado La actualidad más candente (20) Similar a Formacion en movilidad: Conceptos de desarrollo en iOS (IV) (20) Formacion en movilidad: Conceptos de desarrollo en iOS (IV) 8. “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
13. Search Bar
UISearchBarDelegate
// 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
14. Search Bar
UISearchBarDelegate
// 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
15. Search Bar
UISearchBarDelegate
// MasterViewController.m
#pragma mark - UISearchBarDelegate
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
}
Acciones para
botones ‘Search’ y ‘Cancel’ e introducción de texto
15
16. Search Bar
UISearchBarDelegate
// 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. Search Bar
UISearchBarDelegate
// 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. Search Bar
UISearchBarDelegate
// 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. Search Bar
UISearchBarDelegate + 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. Search Bar
UISearchBarDelegate + 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
21. Search Bar
UISearchBarDelegate + 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
23. “Use the UIActionSheet class to present the
user with a set of alternatives for how to
proceed with a given task”
Action Sheet
23
28. Action Sheet
UIActionSheet
// 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
29. Action Sheet
UIActionSheet
// DetailViewController.h
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
#import <MessageUI/MFMailComposeViewController.h>
@interface DetailViewController : UIViewController <
UISplitViewControllerDelegate, UIWebViewDelegate,
UIActionSheetDelegate, MFMailComposeViewControllerDelegate>
// ...
@end
UIActionSheetDelegate
29
30. // DetailViewController.h
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
#import <MessageUI/MFMailComposeViewController.h>
@interface DetailViewController : UIViewController <
UISplitViewControllerDelegate, UIWebViewDelegate,
UIActionSheetDelegate, MFMailComposeViewControllerDelegate>
// ...
@end
Action Sheet
UIActionSheet
MFMailComposeViewControllerDelegate
30
31. Action Sheet
UIActionSheet
// 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
32. Action Sheet
UIActionSheet
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
34. Action Sheet
UIActionSheetDelegate
// 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];
}
}
@end
Parámetros del email
34
35. Action Sheet
UIActionSheetDelegate
// 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];
}
}
@end
Instanciar mail compose view controller
35
36. Action Sheet
UIActionSheetDelegate
// 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];
}
}
@end
Asignar parámetros a mail compose view controller
36
37. Action Sheet
UIActionSheetDelegate
// 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];
}
}
@end
Mostrar mail compose view controller
37
39. Action Sheet
MFMailComposeViewControllerDelegate
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
43. Activity
UIActivityViewController
// 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. Activity
UIActivityViewController
// 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
49. Customizing
UIAppearance
// 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
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
66. Testing
OCUnit
// 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. Testing
OCUnit
// 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
68. Testing
OCUnit
// 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
69. Testing
OCUnit
// 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. Testing
OCUnit
// 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
71. Testing
OCUnit
// 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. Testing
OCUnit
// 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
73. Testing
OCUnit
// 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. Testing
OCUnit
// 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