SlideShare une entreprise Scribd logo
1  sur  82
Télécharger pour lire hors ligne
What I’ve learned when
                     developing
                  BlockAlertViews
                            Gustavo Ambrozio
                             360iDev 2012



Tuesday, September 11, 12
About me
                    • Developing professionally since age of 15




Tuesday, September 11, 12
About me
                    • Developing professionally since age of 15
                    • For iOS since the official SDK came out




Tuesday, September 11, 12
About me
                    • Developing professionally since age of 15
                    • For iOS since the official SDK came out
                    • Did some apps and contracts as an
                            independent developer in Brazil




Tuesday, September 11, 12
About me
                    • Developing professionally since age of 15
                    • For iOS since the official SDK came out
                    • Did some apps and contracts as an
                            independent developer in Brazil
                    • Writter for raywenderlich.com


Tuesday, September 11, 12
About me
                    • Developing professionally since age of 15
                    • For iOS since the official SDK came out
                    • Did some apps and contracts as an
                            independent developer in Brazil
                    • Writter for raywenderlich.com
                    • Hired by PocketGems to code games in SF

Tuesday, September 11, 12
About me
                    • Developing professionally since age of 15
                    • For iOS since the official SDK came out
                    • Did some apps and contracts as an
                            independent developer in Brazil
                    • Writter for raywenderlich.com
                    • Hired by PocketGems to code games in SF
                    • Hate engligh prepositions
Tuesday, September 11, 12
What’s BlockAlertView




Tuesday, September 11, 12
What’s BlockAlertView




Tuesday, September 11, 12
What’s BlockAlertView




Tuesday, September 11, 12
My love and hate story with
                                    UIAlertView
                    •       (apparently) Easy to use   •   Delegates

                                                       •   Switches

                                                       •   Tags

                                                       •   Constants




Tuesday, September 11, 12
@interface MyViewController : UIViewController <UIAlertViewDelegate>


                       #define kRemoveConfirmAlertView 1
                       #define kSendAlertView         2
                       #define kLogoutConfirmAlertView 3

                       - (IBAction)sendItem:(id)sender
                       {
                          UIAlertView *view = [[UIAlertView alloc] initWithTitle:@”Send to”
                                                message:@”Send message using:”
                                                delegate:self
                                        cancelButtonTitle:@”Cancel”
                                        otherButtonTitles:@”Twitter”, @”Facebook”, @”Email”, nil];
                          view.tag = kSendAlertView;
                          [view show];
                          [view release];
                       }




Tuesday, September 11, 12
@interface MyViewController : UIViewController <UIAlertViewDelegate>


                       #define kRemoveConfirmAlertView 1
                       #define kSendAlertView         2
                       #define kLogoutConfirmAlertView 3

                       - (IBAction)sendItem:(id)sender
                       {
                          UIAlertView *view = [[UIAlertView alloc] initWithTitle:@”Send to”
                                                message:@”Send message using:”
                                                delegate:self
                                        cancelButtonTitle:@”Cancel”
                                        otherButtonTitles:@”Twitter”, @”Facebook”, @”Email”, nil];
                          view.tag = kSendAlertView;
                          [view show];
                          [view release];
                       }




Tuesday, September 11, 12
@interface MyViewController : UIViewController <UIAlertViewDelegate>


                       #define kRemoveConfirmAlertView 1
                       #define kSendAlertView         2
                       #define kLogoutConfirmAlertView 3

                       - (IBAction)sendItem:(id)sender
                       {
                          UIAlertView *view = [[UIAlertView alloc] initWithTitle:@”Send to”
                                                message:@”Send message using:”
                                                delegate:self
                                        cancelButtonTitle:@”Cancel”
                                        otherButtonTitles:@”Twitter”, @”Facebook”, @”Email”, nil];
                          view.tag = kSendAlertView;
                          [view show];
                          [view release];
                       }




Tuesday, September 11, 12
@interface MyViewController : UIViewController <UIAlertViewDelegate>


                       #define kRemoveConfirmAlertView 1
                       #define kSendAlertView         2
                       #define kLogoutConfirmAlertView 3

                       - (IBAction)sendItem:(id)sender
                       {
                          UIAlertView *view = [[UIAlertView alloc] initWithTitle:@”Send to”
                                                message:@”Send message using:”
                                                delegate:self
                                        cancelButtonTitle:@”Cancel”
                                        otherButtonTitles:@”Twitter”, @”Facebook”, @”Email”, nil];
                          view.tag = kSendAlertView;
                          [view show];
                          [view release];
                       }




Tuesday, September 11, 12
- (void)alertView:(UIAlertView *)alertView
                 clickedButtonAtIndex:(NSInteger)buttonIndex
              {
                        switch (alertView.tag)
                        {
                             case kRemoveConfirmAlertView:
                                  if (buttonIndex == 1)
                                        [self removeItem];
                                  break;

                            case kSendAlertView:
                            {
                                 switch (buttonIndex)
                                 {
                                      case 0:     // Cancel
                                          break;
                                      case 1:      // Twitter
                                          [self sendWith:kTwitter];
                                          break;
                                      case 2:       // Facebook
                                          [self sendWith:kFacebook];
                                          break;
                                      case 3:      // email
                                          MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init];
                                          view.mailComposeDelegate = self;
                                          [self.navigationController presentModalViewController:view animated:YES];
                                          break;
                                 }
                            }
                            break;
                        }
              }


Tuesday, September 11, 12
- (void)alertView:(UIAlertView *)alertView
                 clickedButtonAtIndex:(NSInteger)buttonIndex
              {
                        switch (alertView.tag)
                        {
                             case kRemoveConfirmAlertView:
                                  if (buttonIndex == 1)
                                        [self removeItem];
                                  break;

                            case kSendAlertView:
                            {
                                 switch (buttonIndex)
                                 {
                                      case 0:     // Cancel
                                          break;
                                      case 1:      // Twitter
                                          [self sendWith:kTwitter];
                                          break;
                                      case 2:       // Facebook
                                          [self sendWith:kFacebook];
                                          break;
                                      case 3:      // email
                                          MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init];
                                          view.mailComposeDelegate = self;
                                          [self.navigationController presentModalViewController:view animated:YES];
                                          break;
                                 }
                            }
                            break;
                        }
              }


Tuesday, September 11, 12
- (void)alertView:(UIAlertView *)alertView
                 clickedButtonAtIndex:(NSInteger)buttonIndex
              {
                        switch (alertView.tag)
                        {
                             case kRemoveConfirmAlertView:
                                  if (buttonIndex == 1)
                                        [self removeItem];
                                  break;

                            case kSendAlertView:
                            {
                                 switch (buttonIndex)
                                 {
                                      case 0:     // Cancel
                                          break;
                                      case 1:      // Twitter
                                          [self sendWith:kTwitter];
                                          break;
                                      case 2:       // Facebook
                                          [self sendWith:kFacebook];
                                          break;
                                      case 3:      // email
                                          MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init];
                                          view.mailComposeDelegate = self;
                                          [self.navigationController presentModalViewController:view animated:YES];
                                          break;
                                 }
                            }
                            break;
                        }
              }


Tuesday, September 11, 12
- (void)alertView:(UIAlertView *)alertView
                 clickedButtonAtIndex:(NSInteger)buttonIndex
              {
                        switch (alertView.tag)
                        {
                             case kRemoveConfirmAlertView:
                                  if (buttonIndex == 1)
                                        [self removeItem];
                                  break;

                            case kSendAlertView:
                            {
                                 switch (buttonIndex)
                                 {
                                      case 0:     // Cancel
                                          break;
                                      case 1:      // Twitter
                                          [self sendWith:kTwitter];
                                          break;
                                      case 2:       // Facebook
                                          [self sendWith:kFacebook];
                                          break;
                                      case 3:      // email
                                          MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init];
                                          view.mailComposeDelegate = self;
                                          [self.navigationController presentModalViewController:view animated:YES];
                                          break;
                                 }
                            }
                            break;
                        }
              }


Tuesday, September 11, 12
- (void)alertView:(UIAlertView *)alertView
                 clickedButtonAtIndex:(NSInteger)buttonIndex
              {
                        switch (alertView.tag)
                        {
                             case kRemoveConfirmAlertView:
                                  if (buttonIndex == 1)
                                        [self removeItem];
                                  break;

                            case kSendAlertView:
                            {
                                 switch (buttonIndex)
                                 {
                                      case 0:     // Cancel
                                          break;
                                      case 1:      // Twitter
                                          [self sendWith:kTwitter];
                                          break;
                                      case 2:       // Facebook
                                          [self sendWith:kFacebook];
                                          break;
                                      case 3:      // email
                                          MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init];
                                          view.mailComposeDelegate = self;
                                          [self.navigationController presentModalViewController:view animated:YES];
                                          break;
                                 }
                            }
                            break;
                        }
              }


Tuesday, September 11, 12
- (void)alertView:(UIAlertView *)alertView
                 clickedButtonAtIndex:(NSInteger)buttonIndex
              {
                        switch (alertView.tag)
                        {
                             case kRemoveConfirmAlertView:
                                  if (buttonIndex == 1)
                                        [self removeItem];
                                  break;

                            case kSendAlertView:
                            {
                                 switch (buttonIndex)
                                 {
                                      case 0:     // Cancel
                                          break;
                                      case 1:      // Twitter
                                          [self sendWith:kTwitter];
                                          break;
                                      case 2:       // Facebook
                                          [self sendWith:kFacebook];
                                          break;
                                      case 3:      // email
                                          MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init];
                                          view.mailComposeDelegate = self;
                                          [self.navigationController presentModalViewController:view animated:YES];
                                          break;
                                 }
                            }
                            break;
                        }
              }


Tuesday, September 11, 12
How blocks ended my
                          hatred
                    • PSFoundation (https://github.com/steipete/
                            PSFoundation/tree/master/Utils)

                    • Peter Steinberger



Tuesday, September 11, 12
How blocks ended my
                          hatred
                    • PSFoundation (https://github.com/steipete/
                            PSFoundation/tree/master/Utils)

                    • Peter Steinberger
                    • PSAlertView e PSActionSheet


Tuesday, September 11, 12
How blocks ended my
                          hatred
                    • PSFoundation (https://github.com/steipete/
                            PSFoundation/tree/master/Utils)

                    • Peter Steinberger
                    • PSAlertView e PSActionSheet
                    • Renamed to BlockAlertView and
                            BlockActionSheet


Tuesday, September 11, 12
@interface MyViewController : UIViewController <UIAlertViewDelegate>

                       #define kRemoveConfirmAlertView 1
                       #define kSendAlertView         2
                       #define kLogoutConfirmAlertView 3

                       - (IBAction)sendItem:(id)sender
                       {
                          BlockAlertView *view = [BlocAlertView alertWithTitle:@”Send to”
                                                 message:@”Send message using:”];
                          [view setCancelButtonWithTitle:@”Cancel” block:nil];
                          [view addButtonWithTitle:@”Twitter”, block:^{
                             [self sendWith:kTwitter];
                          }];
                          [view addButtonWithTitle:@”Facebook”, block:^{
                             [self sendWith:kFacebook];
                          }];
                          [view addButtonWithTitle:@”Email”, block:^{
                             MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init];
                                              view.mailComposeDelegate = self;
                                              [self.navigationController presentModalViewController:view animated:YES];
                            }];
                            view .tag = kSendAlertView;
                            [view show];
                       }

Tuesday, September 11, 12
@interface MyViewController : UIViewController <UIAlertViewDelegate>

                       #define kRemoveConfirmAlertView 1
                       #define kSendAlertView         2
                       #define kLogoutConfirmAlertView 3

                       - (IBAction)sendItem:(id)sender
                       {
                          BlockAlertView *view = [BlocAlertView alertWithTitle:@”Send to”
                                                 message:@”Send message using:”];
                          [view setCancelButtonWithTitle:@”Cancel” block:nil];
                          [view addButtonWithTitle:@”Twitter”, block:^{
                             [self sendWith:kTwitter];
                          }];
                          [view addButtonWithTitle:@”Facebook”, block:^{
                             [self sendWith:kFacebook];
                          }];
                          [view addButtonWithTitle:@”Email”, block:^{
                             MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init];
                                              view.mailComposeDelegate = self;
                                              [self.navigationController presentModalViewController:view animated:YES];
                            }];
                            view .tag = kSendAlertView;
                            [view show];
                       }

Tuesday, September 11, 12
@interface MyViewController : UIViewController <UIAlertViewDelegate>

                       #define kRemoveConfirmAlertView 1
                       #define kSendAlertView         2
                       #define kLogoutConfirmAlertView 3

                       - (IBAction)sendItem:(id)sender
                       {
                          BlockAlertView *view = [BlocAlertView alertWithTitle:@”Send to”
                                                 message:@”Send message using:”];
                          [view setCancelButtonWithTitle:@”Cancel” block:nil];
                          [view addButtonWithTitle:@”Twitter”, block:^{
                             [self sendWith:kTwitter];
                          }];
                          [view addButtonWithTitle:@”Facebook”, block:^{
                             [self sendWith:kFacebook];
                          }];
                          [view addButtonWithTitle:@”Email”, block:^{
                             MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init];
                                              view.mailComposeDelegate = self;
                                              [self.navigationController presentModalViewController:view animated:YES];
                            }];
                            view .tag = kSendAlertView;
                            [view show];
                       }

Tuesday, September 11, 12
@interface MyViewController : UIViewController <UIAlertViewDelegate>

                       #define kRemoveConfirmAlertView 1
                       #define kSendAlertView         2
                       #define kLogoutConfirmAlertView 3

                       - (IBAction)sendItem:(id)sender
                       {
                          BlockAlertView *view = [BlocAlertView alertWithTitle:@”Send to”
                                                 message:@”Send message using:”];
                          [view setCancelButtonWithTitle:@”Cancel” block:nil];
                          [view addButtonWithTitle:@”Twitter”, block:^{
                             [self sendWith:kTwitter];
                          }];
                          [view addButtonWithTitle:@”Facebook”, block:^{
                             [self sendWith:kFacebook];
                          }];
                          [view addButtonWithTitle:@”Email”, block:^{
                             MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init];
                                              view.mailComposeDelegate = self;
                                              [self.navigationController presentModalViewController:view animated:YES];
                            }];
                            view .tag = kSendAlertView;
                            [view show];
                       }

Tuesday, September 11, 12
- (IBAction)sendItem:(id)sender
                       {
                          BlockAlertView *view = [BlockAlertView alertWithTitle:@”Send to”
                                                message:@”Send message using:”];

                            [view setCancelButtonWithTitle:@”Cancel” block:nil];

                            [view addButtonWithTitle:@”Twitter”, block:^{
                               [self sendWith:kTwitter];
                            }];

                            [view addButtonWithTitle:@”Facebook”, block:^{
                               [self sendWith:kFacebook];
                            }];

                            [view addButtonWithTitle:@”Email”, block:^{
                              MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init];
                                               view.mailComposeDelegate = self;
                                               [self.navigationController presentModalViewController:view animated:YES];
                            }];

                            [view show];
                       }


Tuesday, September 11, 12
- (IBAction)sendItem:(id)sender
                       {
                          BlockAlertView *view = [BlockAlertView alertWithTitle:@”Send to”
                                                message:@”Send message using:”];

                            [view setCancelButtonWithTitle:@”Cancel” block:nil];

                            [view addButtonWithTitle:@”Twitter”, block:^{
                               [self sendWith:kTwitter];
                            }];

                            [view addButtonWithTitle:@”Facebook”, block:^{
                               [self sendWith:kFacebook];
                            }];

                            [view addButtonWithTitle:@”Email”, block:^{
                              MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init];
                                               view.mailComposeDelegate = self;
                                               [self.navigationController presentModalViewController:view animated:YES];
                            }];

                            [view show];
                       }


Tuesday, September 11, 12
Lesson number 1

                    1. Use blocks instead of delegates (almost) all
                       the time




Tuesday, September 11, 12
Lesson number 1

                    1. Use blocks instead of delegates (almost) all
                       the time
                            • Exception: When the block can retain
                              something that can be deallocated before
                              que block call gets made
                              (NSURLConnections for example)



Tuesday, September 11, 12
How to do it
                    1. Subclass the original class and have it conform with it’s
                       delegate.
                    2. Create typedefs for all blocks
                    3. Create @property for all blocks with (copy)
                    4. Implement all init methods and set self as delegate.
                    5. Implement all delegates, create ivars for all and call them
                       if not nil.




Tuesday, September 11, 12
ARC compatibility
                    •       Simple:
                            #if ! __has_feature(objc_arc)
                            #error This file must be compiled with ARC. Please add -fobjc-arc
                            to the compiler flags of this file.
                            #endif


                    •       Better:
                            Use Nick Lockwood’s ARC Helper .h file:
                            https://gist.github.com/1563325




Tuesday, September 11, 12
Improving AVAudioPlayer
                       #import <Foundation/Foundation.h>
                       #import <AVFoundation/AVFoundation.h>
                       #import "ARCHelper.h"

                       typedef void (^AudioPlayerDidFinishPlayingBlock)(BOOL);
                       typedef void (^AudioPlayerDecodeErrorDidOccurBlock)(NSError *);
                       typedef void (^AudioPlayerBeginInterruptionBlock)();
                       typedef void (^AudioPlayerEndInterruptionBlock)(NSUInteger);

                       @interface BlockAudioPlayer : AVAudioPlayer <AVAudioPlayerDelegate>

                       @property (nonatomic, copy) AudioPlayerDidFinishPlayingBlock audioPlayerDidFinishPlayingBlock;
                       @property (nonatomic, copy) AudioPlayerDecodeErrorDidOccurBlock
                       audioPlayerDecodeErrorDidOccurBlock;
                       @property (nonatomic, copy) AudioPlayerBeginInterruptionBlock audioPlayerBeginInterruptionBlock;
                       @property (nonatomic, copy) AudioPlayerEndInterruptionBlock audioPlayerEndInterruptionBlock;

                       @end




Tuesday, September 11, 12
Improving AVAudioPlayer
                       - (id)initWithContentsOfURL:(NSURL *)url error:(NSError **)outError
                       {
                           self = [super initWithContentsOfURL:url error:outError];
                           if (self)
                           {
                               self.delegate = self;
                           }

                            return self;
                       }

                       #pragma mark - AVAudioPlayerDelegate

                       - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
                       {
                          if (audioPlayerDidFinishPlayingBlock)
                              audioPlayerDidFinishPlayingBlock(flag);
                       }



                     https://github.com/gpambrozio/BlockAudioPlayer
                 Zachary Waldowski’s https://github.com/zwaldowski/BlocksKit

Tuesday, September 11, 12
Hate comes back with
                         a new face




Tuesday, September 11, 12
Hate comes back with
                         a new face




Tuesday, September 11, 12
Hate comes back with
                         a new face




Tuesday, September 11, 12
A vision on how to end
                        this hatred




Tuesday, September 11, 12
A vision on how to end
                        this hatred




Tuesday, September 11, 12
A vision on how to end
                        this hatred




Tuesday, September 11, 12
A vision on how to end
                        this hatred




Tuesday, September 11, 12
Striking hatred with code




Tuesday, September 11, 12
Striking hatred with code




Tuesday, September 11, 12
Striking hatred with code


                      UIWindow

                      UView

                              UILabel



                            UIButton




Tuesday, September 11, 12
Striking hatred with code


                      UIWindow

                      UView

                              UILabel



                            UIButton




Tuesday, September 11, 12
Striking hatred with code


                      UIWindow

                      UView

                              UILabel



                            UIButton




Tuesday, September 11, 12
Lesson number 2

                    2. UIWindow is an unkown obscure class
                       that’s very rarely used (and with very poor
                       documentation) but that might solve some
                       tricky UI problems. Use with care.




Tuesday, September 11, 12
UIWindow basics
                    • No hierarchy. UIWindow are ordered using
                      their windowLevel:
                     • UIWindowLevelNormal
                     • UIWIndowLevelAlert
                     • UIWindowLevelStatusBar
                    • If on the same level, ordered by creation
                      time, last on top.
                    • makeKeyAndVisible can push it to the top,
                            but still respecting windowLevel.


Tuesday, September 11, 12
Key Window
                    •       From the docs: “...window which is currently receiving
                            keyboard events and other non touch-related events.
                            Whereas touch events are delivered to the window in
                            which the touch occurred, events that do not have an
                            associated coordinate value are delivered to the key
                            window of your application. Only one window at a time
                            may be key."

                    •       When you create a UIWindow and call makeKeyWindow,
                            don’t just call resignKeyWindow. Save the previous
                            keyWindow and call makeKeyWindow on it when you’re
                            done.




Tuesday, September 11, 12
Destroying hate




Tuesday, September 11, 12
Lessons number 3 and 4

                    3. Open your mind to other libraries and
                       don’t assume you need to do it the Apple
                       way




Tuesday, September 11, 12
Lessons number 3 and 4

                    3. Open your mind to other libraries and
                       don’t assume you need to do it the Apple
                       way

                    4. Don’t be lazy. It’s fun to implement
                       something from scratch.



Tuesday, September 11, 12
Spreading the love
                    •       BlockAlertView and BlockActionSheets are
                            open source

                    •       github.com/gpambrozio/BlockAlertsAnd-
                            ActionSheets




Tuesday, September 11, 12
Spreading the love
                    •       BlockAlertView and BlockActionSheets are
                            open source

                    •       github.com/gpambrozio/BlockAlertsAnd-
                            ActionSheets

                    •       blog.codecropper.com/2012/01/replicating-
                            tweetbot-alerts-and-action-sheets/




Tuesday, September 11, 12
Spreading the love
                    •       BlockAlertView and BlockActionSheets are
                            open source

                    •       github.com/gpambrozio/BlockAlertsAnd-
                            ActionSheets

                    •       blog.codecropper.com/2012/01/replicating-
                            tweetbot-alerts-and-action-sheets/

                    •       Improvements to UIAlertView and
                            UIActionSheet

Tuesday, September 11, 12
Spreading the love

                    • Import 6 files, 3 .h and 3 .m




Tuesday, September 11, 12
Spreading the love

                    • Import 6 files, 3 .h and 3 .m
                    • Copy 1 .h file with UI attributes




Tuesday, September 11, 12
Spreading the love

                    • Import 6 files, 3 .h and 3 .m
                    • Copy 1 .h file with UI attributes
                    • Copy PNG assets or create your own


Tuesday, September 11, 12
Spreading the love

                    • Import 6 files, 3 .h and 3 .m
                    • Copy 1 .h file with UI attributes
                    • Copy PNG assets or create your own
                    • Change UI (optional)

Tuesday, September 11, 12
- (IBAction)sendItem:(id)sender
                       {
                          BlockAlertView *view = [BlockAlertView alertWithTitle:@”Send to”
                                                message:@”Send message using:”];

                            [view setCancelButtonWithTitle:@”Cancel” block:nil];

                            [view addButtonWithTitle:@”Twitter”, block:^{
                               [self sendWith:kTwitter];
                            }];

                            [view addButtonWithTitle:@”Facebook”, block:^{
                               [self sendWith:kFacebook];
                            }];

                            [view setDestructiveButtonWithTitle:@”Delete”, block:^{
                               [self removeItem];
                            }];

                            [view show];
                       }



Tuesday, September 11, 12
- (IBAction)sendItem:(id)sender
                       {
                          BlockAlertView *view = [BlockAlertView alertWithTitle:@”Send to”
                                                message:@”Send message using:”];

                            [view setCancelButtonWithTitle:@”Cancel” block:nil];

                            [view addButtonWithTitle:@”Twitter”, block:^{
                               [self sendWith:kTwitter];
                            }];

                            [view addButtonWithTitle:@”Facebook”, block:^{
                               [self sendWith:kFacebook];
                            }];

                            [view setDestructiveButtonWithTitle:@”Delete”, block:^{
                               [self removeItem];
                            }];

                            [view show];
                       }



Tuesday, September 11, 12
- (IBAction)sendItem:(id)sender
                       {
                          BlockAlertView *view = [BlockAlertView alertWithTitle:@”Send to”
                                                message:@”Send message using:”];

                            [view setCancelButtonWithTitle:@”Cancel” block:nil];

                            [view addButtonWithTitle:@”Twitter”, block:^{
                               [self sendWith:kTwitter];
                            }];

                            [view addButtonWithTitle:@”Facebook”, block:^{
                               [self sendWith:kFacebook];
                            }];

                            [view setDestructiveButtonWithTitle:@”Delete”, block:^{
                               [self removeItem];
                            }];

                            [view show];
                       }



Tuesday, September 11, 12
- (IBAction)sendItem:(id)sender
                       {
                          BlockAlertView *view = [BlockAlertView alertWithTitle:@”Send to”
                                                message:@”Send message using:”];

                            [view setCancelButtonWithTitle:@”Cancel” block:nil];

                            [view addButtonWithTitle:@”Twitter”, block:^{
                               [self sendWith:kTwitter];
                            }];

                            [view addButtonWithTitle:@”Facebook”, block:^{
                               [self sendWith:kFacebook];
                            }];

                            [view setDestructiveButtonWithTitle:@”Delete”, block:^{
                               [self removeItem];
                            }];

                            [view show];
                       }



Tuesday, September 11, 12
- (IBAction)sendItem:(id)sender
                       {
                          BlockAlertView *view = [BlockAlertView alertWithTitle:@”Send to”
                                                message:@”Send message using:”];

                            [view setCancelButtonWithTitle:@”Cancel” block:nil];

                            [view addButtonWithTitle:@”Twitter”, block:^{
                               [self sendWith:kTwitter];
                            }];

                            [view addButtonWithTitle:@”Facebook”, block:^{
                               [self sendWith:kFacebook];
                            }];

                            [view setDestructiveButtonWithTitle:@”Delete”, block:^{
                               [self removeItem];
                            }];

                            [view show];
                       }



Tuesday, September 11, 12
- (IBAction)sendItem:(id)sender
                       {
                          BlockAlertView *view = [BlockAlertView alertWithTitle:@”Send to”
                                                message:@”Send message using:”];

                            [view setCancelButtonWithTitle:@”Cancel” block:nil];

                            [view addButtonWithTitle:@”Twitter”, block:^{
                               [self sendWith:kTwitter];
                            }];

                            [view addButtonWithTitle:@”Facebook”, block:^{
                               [self sendWith:kFacebook];
                            }];

                            [view setDestructiveButtonWithTitle:@”Delete”, block:^{
                               [self removeItem];
                            }];

                            [view show];
                       }



Tuesday, September 11, 12
Spreading the love




Tuesday, September 11, 12
Spreading the love




Tuesday, September 11, 12
Advanced love
                    • Background and buttons and simple PNGs




Tuesday, September 11, 12
Advanced love
                    • It’s only an UIView....

                                       [BlockBackground
                                        sharedInstance]



                                         UIView




Tuesday, September 11, 12
Advanced love
                    • BlockTextPromptAlertView




Tuesday, September 11, 12
Animated love




Tuesday, September 11, 12
Animated love




Tuesday, September 11, 12
Animated love




Tuesday, September 11, 12
Animated love




Tuesday, September 11, 12
Animated love




Tuesday, September 11, 12
Animated love




Tuesday, September 11, 12
Animated love




Tuesday, September 11, 12
Lesson number 5

                    5. Opening your source is good: Improves
                       your karma, your reputation and your
                       source code.




Tuesday, September 11, 12
Gustavo Ambrozio

                    • @gpambrozio
                    • blog.codecropper.com
                    • github.com/gpambrozio
                    • linkedin.com/in/gustavoambrozio

Tuesday, September 11, 12
We’re hiring



                            2 apps in top 25 grossing apps




Tuesday, September 11, 12

Contenu connexe

En vedette

Why Smart Employees Underperform
Why Smart Employees UnderperformWhy Smart Employees Underperform
Why Smart Employees Underperformmother55
 
Fracas escolar? La solució inesperada del gènere i la coeducació
Fracas escolar? La solució inesperada del gènere i la coeducacióFracas escolar? La solució inesperada del gènere i la coeducació
Fracas escolar? La solució inesperada del gènere i la coeducacióEdu Torres
 
Wp3 refresh pgh
Wp3 refresh pghWp3 refresh pgh
Wp3 refresh pghMrDirby
 
As aves que frequentam a nossa escola
As aves que frequentam a nossa escolaAs aves que frequentam a nossa escola
As aves que frequentam a nossa escolajpog
 

En vedette (7)

Bo 31 05-2013-30 (2)
Bo 31 05-2013-30 (2)Bo 31 05-2013-30 (2)
Bo 31 05-2013-30 (2)
 
Why Smart Employees Underperform
Why Smart Employees UnderperformWhy Smart Employees Underperform
Why Smart Employees Underperform
 
Fracas escolar? La solució inesperada del gènere i la coeducació
Fracas escolar? La solució inesperada del gènere i la coeducacióFracas escolar? La solució inesperada del gènere i la coeducació
Fracas escolar? La solució inesperada del gènere i la coeducació
 
Wp3 refresh pgh
Wp3 refresh pghWp3 refresh pgh
Wp3 refresh pgh
 
Clda bmo01
Clda bmo01Clda bmo01
Clda bmo01
 
Rajul
RajulRajul
Rajul
 
As aves que frequentam a nossa escola
As aves que frequentam a nossa escolaAs aves que frequentam a nossa escola
As aves que frequentam a nossa escola
 

Similaire à Developing BlockAlertViews for iOS Apps

My Favourite 10 Things about Xcode/ObjectiveC
My Favourite 10 Things about Xcode/ObjectiveCMy Favourite 10 Things about Xcode/ObjectiveC
My Favourite 10 Things about Xcode/ObjectiveCJohnKennedy
 
Quick Start to iOS Development
Quick Start to iOS DevelopmentQuick Start to iOS Development
Quick Start to iOS DevelopmentJussi Pohjolainen
 
Advanced Memory Management on iOS and Android - Mark Probst and Rodrigo Kumpera
Advanced Memory Management on iOS and Android - Mark Probst and Rodrigo KumperaAdvanced Memory Management on iOS and Android - Mark Probst and Rodrigo Kumpera
Advanced Memory Management on iOS and Android - Mark Probst and Rodrigo KumperaXamarin
 
Converting Your Mobile App to the Mobile Cloud
Converting Your Mobile App to the Mobile CloudConverting Your Mobile App to the Mobile Cloud
Converting Your Mobile App to the Mobile CloudRoger Brinkley
 
New to native? Getting Started With iOS Development
New to native?   Getting Started With iOS DevelopmentNew to native?   Getting Started With iOS Development
New to native? Getting Started With iOS DevelopmentGeoffrey Goetz
 
Android Study Jams- Day 2(Hands on Experience)
Android Study Jams- Day 2(Hands on Experience)Android Study Jams- Day 2(Hands on Experience)
Android Study Jams- Day 2(Hands on Experience)GoogleDSC
 
iPhoneOS3.1でのカメラAPIについて
iPhoneOS3.1でのカメラAPIについてiPhoneOS3.1でのカメラAPIについて
iPhoneOS3.1でのカメラAPIについてKyosuke Takayama
 
Leaving Interface Builder Behind
Leaving Interface Builder BehindLeaving Interface Builder Behind
Leaving Interface Builder BehindJohn Wilker
 
The Life and Times of UIViewController
The Life and Times of UIViewControllerThe Life and Times of UIViewController
The Life and Times of UIViewControllerwhilethis
 
A tour through Swift attributes
A tour through Swift attributesA tour through Swift attributes
A tour through Swift attributesMarco Eidinger
 
iPhone SDK dev sharing - the very basics
iPhone SDK dev sharing - the very basicsiPhone SDK dev sharing - the very basics
iPhone SDK dev sharing - the very basicskenshin03
 
iOS Beginners Lesson 4
iOS Beginners Lesson 4iOS Beginners Lesson 4
iOS Beginners Lesson 4Calvin Cheng
 
iOS: Implementing a Custom View
iOS: Implementing a Custom ViewiOS: Implementing a Custom View
iOS: Implementing a Custom ViewJussi Pohjolainen
 
iOS Contact List Application Tutorial
iOS Contact List Application TutorialiOS Contact List Application Tutorial
iOS Contact List Application TutorialIshara Amarasekera
 

Similaire à Developing BlockAlertViews for iOS Apps (20)

My Favourite 10 Things about Xcode/ObjectiveC
My Favourite 10 Things about Xcode/ObjectiveCMy Favourite 10 Things about Xcode/ObjectiveC
My Favourite 10 Things about Xcode/ObjectiveC
 
iOS
iOSiOS
iOS
 
Quick Start to iOS Development
Quick Start to iOS DevelopmentQuick Start to iOS Development
Quick Start to iOS Development
 
I os 11
I os 11I os 11
I os 11
 
iphonedevcon 2010: Cooking with iAd
iphonedevcon 2010:  Cooking with iAd iphonedevcon 2010:  Cooking with iAd
iphonedevcon 2010: Cooking with iAd
 
Knockoutjs
KnockoutjsKnockoutjs
Knockoutjs
 
iOS testing
iOS testingiOS testing
iOS testing
 
Advanced Memory Management on iOS and Android - Mark Probst and Rodrigo Kumpera
Advanced Memory Management on iOS and Android - Mark Probst and Rodrigo KumperaAdvanced Memory Management on iOS and Android - Mark Probst and Rodrigo Kumpera
Advanced Memory Management on iOS and Android - Mark Probst and Rodrigo Kumpera
 
Converting Your Mobile App to the Mobile Cloud
Converting Your Mobile App to the Mobile CloudConverting Your Mobile App to the Mobile Cloud
Converting Your Mobile App to the Mobile Cloud
 
New to native? Getting Started With iOS Development
New to native?   Getting Started With iOS DevelopmentNew to native?   Getting Started With iOS Development
New to native? Getting Started With iOS Development
 
Android Study Jams- Day 2(Hands on Experience)
Android Study Jams- Day 2(Hands on Experience)Android Study Jams- Day 2(Hands on Experience)
Android Study Jams- Day 2(Hands on Experience)
 
SkinKit
SkinKitSkinKit
SkinKit
 
iPhoneOS3.1でのカメラAPIについて
iPhoneOS3.1でのカメラAPIについてiPhoneOS3.1でのカメラAPIについて
iPhoneOS3.1でのカメラAPIについて
 
Leaving Interface Builder Behind
Leaving Interface Builder BehindLeaving Interface Builder Behind
Leaving Interface Builder Behind
 
The Life and Times of UIViewController
The Life and Times of UIViewControllerThe Life and Times of UIViewController
The Life and Times of UIViewController
 
A tour through Swift attributes
A tour through Swift attributesA tour through Swift attributes
A tour through Swift attributes
 
iPhone SDK dev sharing - the very basics
iPhone SDK dev sharing - the very basicsiPhone SDK dev sharing - the very basics
iPhone SDK dev sharing - the very basics
 
iOS Beginners Lesson 4
iOS Beginners Lesson 4iOS Beginners Lesson 4
iOS Beginners Lesson 4
 
iOS: Implementing a Custom View
iOS: Implementing a Custom ViewiOS: Implementing a Custom View
iOS: Implementing a Custom View
 
iOS Contact List Application Tutorial
iOS Contact List Application TutorialiOS Contact List Application Tutorial
iOS Contact List Application Tutorial
 

Dernier

2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 

Dernier (20)

2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 

Developing BlockAlertViews for iOS Apps

  • 1. What I’ve learned when developing BlockAlertViews Gustavo Ambrozio 360iDev 2012 Tuesday, September 11, 12
  • 2. About me • Developing professionally since age of 15 Tuesday, September 11, 12
  • 3. About me • Developing professionally since age of 15 • For iOS since the official SDK came out Tuesday, September 11, 12
  • 4. About me • Developing professionally since age of 15 • For iOS since the official SDK came out • Did some apps and contracts as an independent developer in Brazil Tuesday, September 11, 12
  • 5. About me • Developing professionally since age of 15 • For iOS since the official SDK came out • Did some apps and contracts as an independent developer in Brazil • Writter for raywenderlich.com Tuesday, September 11, 12
  • 6. About me • Developing professionally since age of 15 • For iOS since the official SDK came out • Did some apps and contracts as an independent developer in Brazil • Writter for raywenderlich.com • Hired by PocketGems to code games in SF Tuesday, September 11, 12
  • 7. About me • Developing professionally since age of 15 • For iOS since the official SDK came out • Did some apps and contracts as an independent developer in Brazil • Writter for raywenderlich.com • Hired by PocketGems to code games in SF • Hate engligh prepositions Tuesday, September 11, 12
  • 11. My love and hate story with UIAlertView • (apparently) Easy to use • Delegates • Switches • Tags • Constants Tuesday, September 11, 12
  • 12. @interface MyViewController : UIViewController <UIAlertViewDelegate> #define kRemoveConfirmAlertView 1 #define kSendAlertView 2 #define kLogoutConfirmAlertView 3 - (IBAction)sendItem:(id)sender { UIAlertView *view = [[UIAlertView alloc] initWithTitle:@”Send to” message:@”Send message using:” delegate:self cancelButtonTitle:@”Cancel” otherButtonTitles:@”Twitter”, @”Facebook”, @”Email”, nil]; view.tag = kSendAlertView; [view show]; [view release]; } Tuesday, September 11, 12
  • 13. @interface MyViewController : UIViewController <UIAlertViewDelegate> #define kRemoveConfirmAlertView 1 #define kSendAlertView 2 #define kLogoutConfirmAlertView 3 - (IBAction)sendItem:(id)sender { UIAlertView *view = [[UIAlertView alloc] initWithTitle:@”Send to” message:@”Send message using:” delegate:self cancelButtonTitle:@”Cancel” otherButtonTitles:@”Twitter”, @”Facebook”, @”Email”, nil]; view.tag = kSendAlertView; [view show]; [view release]; } Tuesday, September 11, 12
  • 14. @interface MyViewController : UIViewController <UIAlertViewDelegate> #define kRemoveConfirmAlertView 1 #define kSendAlertView 2 #define kLogoutConfirmAlertView 3 - (IBAction)sendItem:(id)sender { UIAlertView *view = [[UIAlertView alloc] initWithTitle:@”Send to” message:@”Send message using:” delegate:self cancelButtonTitle:@”Cancel” otherButtonTitles:@”Twitter”, @”Facebook”, @”Email”, nil]; view.tag = kSendAlertView; [view show]; [view release]; } Tuesday, September 11, 12
  • 15. @interface MyViewController : UIViewController <UIAlertViewDelegate> #define kRemoveConfirmAlertView 1 #define kSendAlertView 2 #define kLogoutConfirmAlertView 3 - (IBAction)sendItem:(id)sender { UIAlertView *view = [[UIAlertView alloc] initWithTitle:@”Send to” message:@”Send message using:” delegate:self cancelButtonTitle:@”Cancel” otherButtonTitles:@”Twitter”, @”Facebook”, @”Email”, nil]; view.tag = kSendAlertView; [view show]; [view release]; } Tuesday, September 11, 12
  • 16. - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { switch (alertView.tag) { case kRemoveConfirmAlertView: if (buttonIndex == 1) [self removeItem]; break; case kSendAlertView: { switch (buttonIndex) { case 0: // Cancel break; case 1: // Twitter [self sendWith:kTwitter]; break; case 2: // Facebook [self sendWith:kFacebook]; break; case 3: // email MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init]; view.mailComposeDelegate = self; [self.navigationController presentModalViewController:view animated:YES]; break; } } break; } } Tuesday, September 11, 12
  • 17. - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { switch (alertView.tag) { case kRemoveConfirmAlertView: if (buttonIndex == 1) [self removeItem]; break; case kSendAlertView: { switch (buttonIndex) { case 0: // Cancel break; case 1: // Twitter [self sendWith:kTwitter]; break; case 2: // Facebook [self sendWith:kFacebook]; break; case 3: // email MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init]; view.mailComposeDelegate = self; [self.navigationController presentModalViewController:view animated:YES]; break; } } break; } } Tuesday, September 11, 12
  • 18. - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { switch (alertView.tag) { case kRemoveConfirmAlertView: if (buttonIndex == 1) [self removeItem]; break; case kSendAlertView: { switch (buttonIndex) { case 0: // Cancel break; case 1: // Twitter [self sendWith:kTwitter]; break; case 2: // Facebook [self sendWith:kFacebook]; break; case 3: // email MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init]; view.mailComposeDelegate = self; [self.navigationController presentModalViewController:view animated:YES]; break; } } break; } } Tuesday, September 11, 12
  • 19. - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { switch (alertView.tag) { case kRemoveConfirmAlertView: if (buttonIndex == 1) [self removeItem]; break; case kSendAlertView: { switch (buttonIndex) { case 0: // Cancel break; case 1: // Twitter [self sendWith:kTwitter]; break; case 2: // Facebook [self sendWith:kFacebook]; break; case 3: // email MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init]; view.mailComposeDelegate = self; [self.navigationController presentModalViewController:view animated:YES]; break; } } break; } } Tuesday, September 11, 12
  • 20. - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { switch (alertView.tag) { case kRemoveConfirmAlertView: if (buttonIndex == 1) [self removeItem]; break; case kSendAlertView: { switch (buttonIndex) { case 0: // Cancel break; case 1: // Twitter [self sendWith:kTwitter]; break; case 2: // Facebook [self sendWith:kFacebook]; break; case 3: // email MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init]; view.mailComposeDelegate = self; [self.navigationController presentModalViewController:view animated:YES]; break; } } break; } } Tuesday, September 11, 12
  • 21. - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { switch (alertView.tag) { case kRemoveConfirmAlertView: if (buttonIndex == 1) [self removeItem]; break; case kSendAlertView: { switch (buttonIndex) { case 0: // Cancel break; case 1: // Twitter [self sendWith:kTwitter]; break; case 2: // Facebook [self sendWith:kFacebook]; break; case 3: // email MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init]; view.mailComposeDelegate = self; [self.navigationController presentModalViewController:view animated:YES]; break; } } break; } } Tuesday, September 11, 12
  • 22. How blocks ended my hatred • PSFoundation (https://github.com/steipete/ PSFoundation/tree/master/Utils) • Peter Steinberger Tuesday, September 11, 12
  • 23. How blocks ended my hatred • PSFoundation (https://github.com/steipete/ PSFoundation/tree/master/Utils) • Peter Steinberger • PSAlertView e PSActionSheet Tuesday, September 11, 12
  • 24. How blocks ended my hatred • PSFoundation (https://github.com/steipete/ PSFoundation/tree/master/Utils) • Peter Steinberger • PSAlertView e PSActionSheet • Renamed to BlockAlertView and BlockActionSheet Tuesday, September 11, 12
  • 25. @interface MyViewController : UIViewController <UIAlertViewDelegate> #define kRemoveConfirmAlertView 1 #define kSendAlertView 2 #define kLogoutConfirmAlertView 3 - (IBAction)sendItem:(id)sender { BlockAlertView *view = [BlocAlertView alertWithTitle:@”Send to” message:@”Send message using:”]; [view setCancelButtonWithTitle:@”Cancel” block:nil]; [view addButtonWithTitle:@”Twitter”, block:^{ [self sendWith:kTwitter]; }]; [view addButtonWithTitle:@”Facebook”, block:^{ [self sendWith:kFacebook]; }]; [view addButtonWithTitle:@”Email”, block:^{ MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init]; view.mailComposeDelegate = self; [self.navigationController presentModalViewController:view animated:YES]; }]; view .tag = kSendAlertView; [view show]; } Tuesday, September 11, 12
  • 26. @interface MyViewController : UIViewController <UIAlertViewDelegate> #define kRemoveConfirmAlertView 1 #define kSendAlertView 2 #define kLogoutConfirmAlertView 3 - (IBAction)sendItem:(id)sender { BlockAlertView *view = [BlocAlertView alertWithTitle:@”Send to” message:@”Send message using:”]; [view setCancelButtonWithTitle:@”Cancel” block:nil]; [view addButtonWithTitle:@”Twitter”, block:^{ [self sendWith:kTwitter]; }]; [view addButtonWithTitle:@”Facebook”, block:^{ [self sendWith:kFacebook]; }]; [view addButtonWithTitle:@”Email”, block:^{ MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init]; view.mailComposeDelegate = self; [self.navigationController presentModalViewController:view animated:YES]; }]; view .tag = kSendAlertView; [view show]; } Tuesday, September 11, 12
  • 27. @interface MyViewController : UIViewController <UIAlertViewDelegate> #define kRemoveConfirmAlertView 1 #define kSendAlertView 2 #define kLogoutConfirmAlertView 3 - (IBAction)sendItem:(id)sender { BlockAlertView *view = [BlocAlertView alertWithTitle:@”Send to” message:@”Send message using:”]; [view setCancelButtonWithTitle:@”Cancel” block:nil]; [view addButtonWithTitle:@”Twitter”, block:^{ [self sendWith:kTwitter]; }]; [view addButtonWithTitle:@”Facebook”, block:^{ [self sendWith:kFacebook]; }]; [view addButtonWithTitle:@”Email”, block:^{ MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init]; view.mailComposeDelegate = self; [self.navigationController presentModalViewController:view animated:YES]; }]; view .tag = kSendAlertView; [view show]; } Tuesday, September 11, 12
  • 28. @interface MyViewController : UIViewController <UIAlertViewDelegate> #define kRemoveConfirmAlertView 1 #define kSendAlertView 2 #define kLogoutConfirmAlertView 3 - (IBAction)sendItem:(id)sender { BlockAlertView *view = [BlocAlertView alertWithTitle:@”Send to” message:@”Send message using:”]; [view setCancelButtonWithTitle:@”Cancel” block:nil]; [view addButtonWithTitle:@”Twitter”, block:^{ [self sendWith:kTwitter]; }]; [view addButtonWithTitle:@”Facebook”, block:^{ [self sendWith:kFacebook]; }]; [view addButtonWithTitle:@”Email”, block:^{ MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init]; view.mailComposeDelegate = self; [self.navigationController presentModalViewController:view animated:YES]; }]; view .tag = kSendAlertView; [view show]; } Tuesday, September 11, 12
  • 29. - (IBAction)sendItem:(id)sender { BlockAlertView *view = [BlockAlertView alertWithTitle:@”Send to” message:@”Send message using:”]; [view setCancelButtonWithTitle:@”Cancel” block:nil]; [view addButtonWithTitle:@”Twitter”, block:^{ [self sendWith:kTwitter]; }]; [view addButtonWithTitle:@”Facebook”, block:^{ [self sendWith:kFacebook]; }]; [view addButtonWithTitle:@”Email”, block:^{ MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init]; view.mailComposeDelegate = self; [self.navigationController presentModalViewController:view animated:YES]; }]; [view show]; } Tuesday, September 11, 12
  • 30. - (IBAction)sendItem:(id)sender { BlockAlertView *view = [BlockAlertView alertWithTitle:@”Send to” message:@”Send message using:”]; [view setCancelButtonWithTitle:@”Cancel” block:nil]; [view addButtonWithTitle:@”Twitter”, block:^{ [self sendWith:kTwitter]; }]; [view addButtonWithTitle:@”Facebook”, block:^{ [self sendWith:kFacebook]; }]; [view addButtonWithTitle:@”Email”, block:^{ MFMailComposeViewController *view = [[MFMailComposeViewController alloc] init]; view.mailComposeDelegate = self; [self.navigationController presentModalViewController:view animated:YES]; }]; [view show]; } Tuesday, September 11, 12
  • 31. Lesson number 1 1. Use blocks instead of delegates (almost) all the time Tuesday, September 11, 12
  • 32. Lesson number 1 1. Use blocks instead of delegates (almost) all the time • Exception: When the block can retain something that can be deallocated before que block call gets made (NSURLConnections for example) Tuesday, September 11, 12
  • 33. How to do it 1. Subclass the original class and have it conform with it’s delegate. 2. Create typedefs for all blocks 3. Create @property for all blocks with (copy) 4. Implement all init methods and set self as delegate. 5. Implement all delegates, create ivars for all and call them if not nil. Tuesday, September 11, 12
  • 34. ARC compatibility • Simple: #if ! __has_feature(objc_arc) #error This file must be compiled with ARC. Please add -fobjc-arc to the compiler flags of this file. #endif • Better: Use Nick Lockwood’s ARC Helper .h file: https://gist.github.com/1563325 Tuesday, September 11, 12
  • 35. Improving AVAudioPlayer #import <Foundation/Foundation.h> #import <AVFoundation/AVFoundation.h> #import "ARCHelper.h" typedef void (^AudioPlayerDidFinishPlayingBlock)(BOOL); typedef void (^AudioPlayerDecodeErrorDidOccurBlock)(NSError *); typedef void (^AudioPlayerBeginInterruptionBlock)(); typedef void (^AudioPlayerEndInterruptionBlock)(NSUInteger); @interface BlockAudioPlayer : AVAudioPlayer <AVAudioPlayerDelegate> @property (nonatomic, copy) AudioPlayerDidFinishPlayingBlock audioPlayerDidFinishPlayingBlock; @property (nonatomic, copy) AudioPlayerDecodeErrorDidOccurBlock audioPlayerDecodeErrorDidOccurBlock; @property (nonatomic, copy) AudioPlayerBeginInterruptionBlock audioPlayerBeginInterruptionBlock; @property (nonatomic, copy) AudioPlayerEndInterruptionBlock audioPlayerEndInterruptionBlock; @end Tuesday, September 11, 12
  • 36. Improving AVAudioPlayer - (id)initWithContentsOfURL:(NSURL *)url error:(NSError **)outError { self = [super initWithContentsOfURL:url error:outError]; if (self) { self.delegate = self; } return self; } #pragma mark - AVAudioPlayerDelegate - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { if (audioPlayerDidFinishPlayingBlock) audioPlayerDidFinishPlayingBlock(flag); } https://github.com/gpambrozio/BlockAudioPlayer Zachary Waldowski’s https://github.com/zwaldowski/BlocksKit Tuesday, September 11, 12
  • 37. Hate comes back with a new face Tuesday, September 11, 12
  • 38. Hate comes back with a new face Tuesday, September 11, 12
  • 39. Hate comes back with a new face Tuesday, September 11, 12
  • 40. A vision on how to end this hatred Tuesday, September 11, 12
  • 41. A vision on how to end this hatred Tuesday, September 11, 12
  • 42. A vision on how to end this hatred Tuesday, September 11, 12
  • 43. A vision on how to end this hatred Tuesday, September 11, 12
  • 44. Striking hatred with code Tuesday, September 11, 12
  • 45. Striking hatred with code Tuesday, September 11, 12
  • 46. Striking hatred with code UIWindow UView UILabel UIButton Tuesday, September 11, 12
  • 47. Striking hatred with code UIWindow UView UILabel UIButton Tuesday, September 11, 12
  • 48. Striking hatred with code UIWindow UView UILabel UIButton Tuesday, September 11, 12
  • 49. Lesson number 2 2. UIWindow is an unkown obscure class that’s very rarely used (and with very poor documentation) but that might solve some tricky UI problems. Use with care. Tuesday, September 11, 12
  • 50. UIWindow basics • No hierarchy. UIWindow are ordered using their windowLevel: • UIWindowLevelNormal • UIWIndowLevelAlert • UIWindowLevelStatusBar • If on the same level, ordered by creation time, last on top. • makeKeyAndVisible can push it to the top, but still respecting windowLevel. Tuesday, September 11, 12
  • 51. Key Window • From the docs: “...window which is currently receiving keyboard events and other non touch-related events. Whereas touch events are delivered to the window in which the touch occurred, events that do not have an associated coordinate value are delivered to the key window of your application. Only one window at a time may be key." • When you create a UIWindow and call makeKeyWindow, don’t just call resignKeyWindow. Save the previous keyWindow and call makeKeyWindow on it when you’re done. Tuesday, September 11, 12
  • 53. Lessons number 3 and 4 3. Open your mind to other libraries and don’t assume you need to do it the Apple way Tuesday, September 11, 12
  • 54. Lessons number 3 and 4 3. Open your mind to other libraries and don’t assume you need to do it the Apple way 4. Don’t be lazy. It’s fun to implement something from scratch. Tuesday, September 11, 12
  • 55. Spreading the love • BlockAlertView and BlockActionSheets are open source • github.com/gpambrozio/BlockAlertsAnd- ActionSheets Tuesday, September 11, 12
  • 56. Spreading the love • BlockAlertView and BlockActionSheets are open source • github.com/gpambrozio/BlockAlertsAnd- ActionSheets • blog.codecropper.com/2012/01/replicating- tweetbot-alerts-and-action-sheets/ Tuesday, September 11, 12
  • 57. Spreading the love • BlockAlertView and BlockActionSheets are open source • github.com/gpambrozio/BlockAlertsAnd- ActionSheets • blog.codecropper.com/2012/01/replicating- tweetbot-alerts-and-action-sheets/ • Improvements to UIAlertView and UIActionSheet Tuesday, September 11, 12
  • 58. Spreading the love • Import 6 files, 3 .h and 3 .m Tuesday, September 11, 12
  • 59. Spreading the love • Import 6 files, 3 .h and 3 .m • Copy 1 .h file with UI attributes Tuesday, September 11, 12
  • 60. Spreading the love • Import 6 files, 3 .h and 3 .m • Copy 1 .h file with UI attributes • Copy PNG assets or create your own Tuesday, September 11, 12
  • 61. Spreading the love • Import 6 files, 3 .h and 3 .m • Copy 1 .h file with UI attributes • Copy PNG assets or create your own • Change UI (optional) Tuesday, September 11, 12
  • 62. - (IBAction)sendItem:(id)sender { BlockAlertView *view = [BlockAlertView alertWithTitle:@”Send to” message:@”Send message using:”]; [view setCancelButtonWithTitle:@”Cancel” block:nil]; [view addButtonWithTitle:@”Twitter”, block:^{ [self sendWith:kTwitter]; }]; [view addButtonWithTitle:@”Facebook”, block:^{ [self sendWith:kFacebook]; }]; [view setDestructiveButtonWithTitle:@”Delete”, block:^{ [self removeItem]; }]; [view show]; } Tuesday, September 11, 12
  • 63. - (IBAction)sendItem:(id)sender { BlockAlertView *view = [BlockAlertView alertWithTitle:@”Send to” message:@”Send message using:”]; [view setCancelButtonWithTitle:@”Cancel” block:nil]; [view addButtonWithTitle:@”Twitter”, block:^{ [self sendWith:kTwitter]; }]; [view addButtonWithTitle:@”Facebook”, block:^{ [self sendWith:kFacebook]; }]; [view setDestructiveButtonWithTitle:@”Delete”, block:^{ [self removeItem]; }]; [view show]; } Tuesday, September 11, 12
  • 64. - (IBAction)sendItem:(id)sender { BlockAlertView *view = [BlockAlertView alertWithTitle:@”Send to” message:@”Send message using:”]; [view setCancelButtonWithTitle:@”Cancel” block:nil]; [view addButtonWithTitle:@”Twitter”, block:^{ [self sendWith:kTwitter]; }]; [view addButtonWithTitle:@”Facebook”, block:^{ [self sendWith:kFacebook]; }]; [view setDestructiveButtonWithTitle:@”Delete”, block:^{ [self removeItem]; }]; [view show]; } Tuesday, September 11, 12
  • 65. - (IBAction)sendItem:(id)sender { BlockAlertView *view = [BlockAlertView alertWithTitle:@”Send to” message:@”Send message using:”]; [view setCancelButtonWithTitle:@”Cancel” block:nil]; [view addButtonWithTitle:@”Twitter”, block:^{ [self sendWith:kTwitter]; }]; [view addButtonWithTitle:@”Facebook”, block:^{ [self sendWith:kFacebook]; }]; [view setDestructiveButtonWithTitle:@”Delete”, block:^{ [self removeItem]; }]; [view show]; } Tuesday, September 11, 12
  • 66. - (IBAction)sendItem:(id)sender { BlockAlertView *view = [BlockAlertView alertWithTitle:@”Send to” message:@”Send message using:”]; [view setCancelButtonWithTitle:@”Cancel” block:nil]; [view addButtonWithTitle:@”Twitter”, block:^{ [self sendWith:kTwitter]; }]; [view addButtonWithTitle:@”Facebook”, block:^{ [self sendWith:kFacebook]; }]; [view setDestructiveButtonWithTitle:@”Delete”, block:^{ [self removeItem]; }]; [view show]; } Tuesday, September 11, 12
  • 67. - (IBAction)sendItem:(id)sender { BlockAlertView *view = [BlockAlertView alertWithTitle:@”Send to” message:@”Send message using:”]; [view setCancelButtonWithTitle:@”Cancel” block:nil]; [view addButtonWithTitle:@”Twitter”, block:^{ [self sendWith:kTwitter]; }]; [view addButtonWithTitle:@”Facebook”, block:^{ [self sendWith:kFacebook]; }]; [view setDestructiveButtonWithTitle:@”Delete”, block:^{ [self removeItem]; }]; [view show]; } Tuesday, September 11, 12
  • 68. Spreading the love Tuesday, September 11, 12
  • 69. Spreading the love Tuesday, September 11, 12
  • 70. Advanced love • Background and buttons and simple PNGs Tuesday, September 11, 12
  • 71. Advanced love • It’s only an UIView.... [BlockBackground sharedInstance] UIView Tuesday, September 11, 12
  • 72. Advanced love • BlockTextPromptAlertView Tuesday, September 11, 12
  • 80. Lesson number 5 5. Opening your source is good: Improves your karma, your reputation and your source code. Tuesday, September 11, 12
  • 81. Gustavo Ambrozio • @gpambrozio • blog.codecropper.com • github.com/gpambrozio • linkedin.com/in/gustavoambrozio Tuesday, September 11, 12
  • 82. We’re hiring 2 apps in top 25 grossing apps Tuesday, September 11, 12