What I’ve learned when developing BlockAlertViews

Preview:

DESCRIPTION

 

Citation preview

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: // Cancelbreak;

case 1: // Twitter[self sendWith:kTwitter];break;

case 2: // Facebook[self sendWith:kFacebook];break;

case 3: // emailMFMailComposeViewController *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: // Cancelbreak;

case 1: // Twitter[self sendWith:kTwitter];break;

case 2: // Facebook[self sendWith:kFacebook];break;

case 3: // emailMFMailComposeViewController *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: // Cancelbreak;

case 1: // Twitter[self sendWith:kTwitter];break;

case 2: // Facebook[self sendWith:kFacebook];break;

case 3: // emailMFMailComposeViewController *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: // Cancelbreak;

case 1: // Twitter[self sendWith:kTwitter];break;

case 2: // Facebook[self sendWith:kFacebook];break;

case 3: // emailMFMailComposeViewController *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: // Cancelbreak;

case 1: // Twitter[self sendWith:kTwitter];break;

case 2: // Facebook[self sendWith:kFacebook];break;

case 3: // emailMFMailComposeViewController *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: // Cancelbreak;

case 1: // Twitter[self sendWith:kTwitter];break;

case 2: // Facebook[self sendWith:kFacebook];break;

case 3: // emailMFMailComposeViewController *view = [[MFMailComposeViewController alloc] init];view.mailComposeDelegate = self;[self.navigationController presentModalViewController:view animated:YES];break;

}}break;

}}

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....

[BlockBackgroundsharedInstance]

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

Recommended