The document discusses the author's experience developing iOS apps and their love-hate relationship with UIAlertView. It introduces BlockAlertView, which uses blocks instead of delegates to handle alert view button presses. This eliminates the need for tags, constants, and switch statements. Blocks make the code cleaner and easier to read.
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
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
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
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
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