Replicating TweetBot’s Alerts and Action Sheets

Email This Post Email This Post

How it all started: A love and hate story.

Since the first time I had to use an UIActionSheet or UIAlertView in an app I disliked the way it was implemented. It was a pain if you had two kinds of alerts in the same class for example as everything is done by invoking a delegate method. I also disliked the fact that the code that should be executed in the event of a button was almost always in a separate place in your source code. The code needs a lot of constants, switches and you need to tag your UIAlertView…. I hated it!

But on the other hand they are very useful for asking information in a modal way so I kept using them when it was appropriate.

And then I found PSFoundation a library of very nice iOS utilities by Peter Steinberger. It has a LOT of useful utility classes but two stood out for me as a relief for my hatred: PSActionSheet and PSAlertView.

To see an explanation on how they work, take a look at the blog post that originated PSActionSheet and inspired PSAlertView: “Using Blocks” by Landon Fuller who apparently hates UIActionSheets as much as I do.

Since I found these classes I’ve incorporated them into every one of my projects. And when I took over as lead developer for Arrived’s iPhone app I took a few hours right at the beginning of the project to convert every UIActionSheet and every UIAlertView into a BlockActionSheet and BlockAlertView (I renamed the classes to make the name more memorable and descriptive).

A new kind of hate

Arrived has a very distinctive look. I love the design of the app, with lots of textures, the red carpet over the pictures on the stream, the custom buttons, the title, even the tab bar is customized to look unique. So, in the middle of all this very nice color scheme whenever I had to use an Alert View or an Action Sheet I was punched in the face by a freaking blue Alert! How I hated those Alert Views ruining the look of the app.

And then I got TweetBot. What a nice app, what a unique interface and…. what the hell? They customized their Alert Views! Super cool. Right then I thought: I gotta have this….

Hate is a very effective motivator

We then decided to terminate every instance of default Alert View and Action Sheet. Since I already had every call to those wrapped with my own Block* classes, it was just a matter of changing these classes and everything should work as before, but with a much better look.

And so we did it and we decided to open source it. And let me tell you they look great!

  

But before I send you over to our repository to download this baby, let me tell you how they work and what are the current limitations.

Using the library

If you’re familiar with the above mentioned PLActionSheet and PLAlertView you will have no problems adjusting to these classes as I didn’t change their methods at all. I added some methods to make the class even better but everything that used the old classes worked with no modifications.

You’ll need to import 6 files into your project: 4 for both classes (BlockActionSheet.(h|m) and BlockAlertView.(h|m)) and 2 for another view that serves as the background for the alerts and action sheets, obscuring the window to make it look very modal and make the user focus more on the dialog (BlockBackground.(h|m)). You’ll never have to use this third class directly though as everything is handled by the two main classes. You’ll also need the image assets that we se to draw the view, such as the buttons and background.

To create an alert view you use:

BlockAlertView *alert = [BlockAlertView alertWithTitle:@"Alert Title" message:@"This is a very long message, designed just to show you how smart this class is"];

Then for every button you want you call:

[alert addButtonWithTitle:@"Do something cool" block:^{
    // Do something cool when this button is pressed
}];

You can also add a “Cancel” button and a “Destructive” button (this is one of the improvements that UIAlertView can’t even do):

[alert setCancelButtonWithTitle:@"Please, don't do this" block:^{
    // Do something or nothing.... This block can even be nil!
}];
 
[alert setDestructiveButtonWithTitle:@"Kill, Kill" block:^{
    // Do something nasty when this button is pressed
}];

When all your buttons are in place, just show:

[alert show];

That’s it! Showing an Action Sheet works almost exactly the same. I won’t bore you here with more code but the repository has a demo project with everything you’ll need.

You can even have more than one cancel and destructive button, despite the fact that the methods are prefixed set and not add, but this is because I wanted to keep the same names I used in the original libraries where you could only have one cancel button. Feel free to rename those if you don’t have any legacy code as I had.

Another cool thing we did was add an animation when showing and hiding the new views as Tweetbot does. This is another area where you can go nuts and add all kinds of animation.

The look of the alerts and action sheets is made of a few assets for the background and the buttons so if you want to change the color scheme all you need is a little time to change ours. Check out the included assets and just change them if they don’t work for you.

The only limitation these classes have so far is with device rotation. As Arrived only works in portrait this is not a problem I needed to solve. And it’s not that trivial because you’d have to reposition the buttons and text because the window now has a different size and the alert might be too tall to hold a long message in landscape. And you might need to add a scroll for some action sheets too. But feel free to fork and fix this!

Gimme that!

You can get the everything you need from out GitHub repository. There’s a demo project with lots of buttons to trigger alerts and action sheets until you get sick of them.

Another thing that’s included in the project but that you might need to roll your own are the graphical assets for the buttons and backgrounds. You can use ours but they might not fit the look of your app.

Now go get the project and have fun with it. Feel free to fork and add pull requests so we can incorporate your changes for everyone.

How to stop clenching teeth while sleeping how to stop clenching teeth while sleeping. Gay emo cam gay emo cam. Free sheet music piano beginner free sheet music piano beginner. Best deodorant for heavy sweating best deodorant for heavy sweating. Green tea extract cream rosacea green tea extract cream rosacea. Belgium dating website belgium dating website. Rheumatoid arthritis esa rheumatoid arthritis esa. Gay cam gay gay cam gay. Tinnitus up tinnitus up. Sexy shemale webcams sexy shemale webcams. Treating guttate psoriasis treating guttate psoriasis. Pcos decreased breast size pcos decreased breast size. Gynecomastia reducing drugs gynecomastia reducing drugs. Fiber supplement weight loss fiber supplement weight loss. Pcos relievers pcos relievers. Best republican presidential candidate for 2012 best republican presidential candidate for 2012. Herpes positive stories herpes positive stories. Bv otc bv otc. Best treatment for rosacea bumps best treatment for rosacea bumps. Prevent falling hair naturally prevent falling hair naturally. Psoriasis self help psoriasis self help. Rosacea product rosacea product. Free dating site international free dating site international. Free web cam shemale free web cam shemale. Female hair loss stress treatment female hair loss stress treatment. Psoriasis arthritis herbal treatment psoriasis arthritis herbal treatment


Keep tuned for more technical and non technical posts. You can subscribe by email, RSS or following me on twitter.


Email This Post Email This Post
  • Pingback: The CodeCropper » Replicating TweetBot’s Alerts and Action Sheets | Mobile Applications | Scoop.it

  • http://ekosdeux.com/ PetroEkos

    Great job, I specifically like the sheet title on the right. Thanks for sharing it.

  • Pingback: The CodeCropper » Replicating TweetBot’s Alerts and Action Sheets « myiphonenotes

  • Pingback: Open Source: Great Block Based UIAlertSheet And UIActionSheet Replacement Library |

  • Pingback: Open Source: Great Block Based UIAlertSheet And UIActionSheet Replacement Library | WebScriptPlus.com

  • Pingback: Open Source: Great Block Based UIAlertSheet And UIActionSheet Replacement Library | iPhone, iOS 5, iPad SDK Development Tutorial and Programming Tips

  • Pingback: Using Blocks: A Library for iOS Alerts and Action Sheets | So You Want to Build an App...

  • Érico

    Great! can i insert a UIPickerDate in ActionSheet?

    • Anonymous

      Yes you can, even though it might look weird. Both these classes are just UIViews presented in a way to make them look like an action sheet and alert so you can add anything to them. Take a look inside the class and you’ll figure it out.

      • Érico

        Thanks, i will try this! just explaining… i wanna call the Action Sheet with Picker Date from a UITextField input

        • Anonymous

          In this case I’d suggest creating a new class based on mu BlockActionSheet (BlockDatePicker?) and change the guts of it to suit your needs. There’s a lot of stuff in there you won’t need in your case anyway. And if you can do this as a fork you can then issue me a pull request to add it to my repo? That’d be very cool!

  • Rodrigo

    Great Job Gustavo.
    Im using this class in my project, but im having some problems with the MBProgressHUD callbacks after i call alertWithTitle and 

    sheetWithTitle. Because of the design of my app i call the HUD init with [[UIApplication sharedApplication] keyWindow]] witch works fine, but when i call sheetWithTitle or alertWithTitle the method - (void)addToMainWindow:(UIView *)view in BlockBackground calls [self makeKeyAndVisible] and kills the reference for my HUD callbacks.I comment this call and the alert and sheet keeps working, can you explain to me why you call makeKeyAndVisible, is really necessary?Thx

    • Anonymous

      It’s necessary because of the times where you might be showing the keyboard and you want to be above it. I had a similar problem with another project and found a fix that might help you. I can’t push the changes right now because they’re in another branch with a lot of changes. Send an email to gustavo@codecrop.com and I’ll send you a patch.

  • sage

    Could we add an image via a imageView to your BlockAlertView

    • http://blog.codecropper.com/ Gustavo Ambrozio

      You sure can! Take a look inside the source code for BlockAlertView and you’ll see that it is nothing fancy, just a simple UIView displayed in a different way. Being just a UIView means you can add whatever you want to it, change the size, whatever.  Check out the new BlockTextPromptAlertView added by Barrett Jacobsen that adds a UITextView to the Alert View

  • Dima Shmidt

    It’s awesome, thank you!

    The only thing — I have a problem with alertView in ViewController with ScrollView. Alertview shows, but all touches goes through it and receives by scrollView. Is it any fix for it?

    • http://blog.codecropper.com/ Gustavo Ambrozio

      What’s the last time you checked out the repo? I did some modifications about a week ago that might address this issue. Let me know if it does. If it does not, would you mind sharing a sample project that demonstrates the problem and reporting as an issue on GitHub?

      • Dima Shmidt

        I replaced UIAlertView with BlockAlert which was inside this block:
            [geocoder reverseGeocodeLocation:_sight.location completionHandler:^(NSArray *placemarks, NSError *error) 
        {…}If I place BlockAlert in other places it works fine

        • http://blog.codecropper.com/ Gustavo Ambrozio

          It doesn’t work with the latest version also?

          • Dima Shmidt

            Yes, I used today’s download.
            I’ll try to find a solution by reading more about blocks.

  • Harry Jennerway

    I love your solution, but there’s a pretty big flaw which I can’t figure out. It doesn’t seem to support orientation. If I’m in landscape mode, the actionsheet/alert is always rotated in the direction of the home button. Any idea how to fix this?

    • http://twitter.com/gpambrozio Gustavo

      Yes, as I mention in the article this is a know limitation. There are ways to fix this but unfortunately I don’t have any free time to do it now. You’ll probably have to get rotation events using NSNotificationCenter and then redraw the dialog or action sheet in this new orientation. 

  • Fabrizio Prosperi

    Great job as usual Gustavo. Could you share some hints on how to generate images of the same kind of yours as I need to use buttons of different colors? Thanks. 

    • http://blog.codecropper.com/ Gustavo Ambrozio

      Thanks. Unfortunately I can’t help you much. The designer that was working with us did that. He was going to write about it on Ray’s blog but I don’t know if it’ll happen or when..

      • Fabrizio Prosperi

        I’ll find another way then, thank you Gustavo.

  • Fabrizio Prosperi

    Another quick question, I see the BlockAlertView does not implement the addSubview method – which was useful to add an UIActivityIndicatorView – Do you see any other way to do that with BlockAlertView? Thanks.

    • http://blog.codecropper.com/ Gustavo Ambrozio

      The view is exposed in the “view” property. ou can use that to add subviews.

      • Fabrizio Prosperi

        You’re absolutely right, I should have known. I managed to use it. Thanks.

  • Alessandro

    Hi, I just found this post and I’d like to try your code, but it is not available on GitHub. Maybe removed :(

    • http://blog.codecropper.com/ Gustavo Ambrozio

      Sorry, I’ve moved the repo: https://github.com/gpambrozio/BlockAlertsAnd-ActionSheets. I’ll update the post too.

  • Ill

    Is this library making use of any private APIs or does it have any way of getting apps rejected from app store ? 

    • Ill

      I have 2 more questions;

      1.) There is a folder called ‘ToAddToYourProject’ in the example provided, in that folder there are few files which are supposed to be added to our project, Do we require to paste the Licence agreement in those files ? (Because those files doesn’t have a license statement)

      2.) is the method ‘show’ belong to a private API,because UIAlertView also has a method called ‘show’. (I am new to iPhone dev, please help me)

      • http://blog.codecropper.com/ Gustavo Ambrozio

        1) No, you don’t have to copy the license to your project.
        2) No, this method is documented and as such is public. Even if these classes were subclasses of UIAlertView (they are not) I could implement the show method without violating the developer agreement.

    • http://blog.codecropper.com/ Gustavo Ambrozio

      No, it does not use any private APIs. I had 2 apps that use this and got approved and have been contacted by other devs that had app approved too.

  • Ill

    Unless the user types something the Button should be disabled. (I just want to make this field mandatory, How can i do this ?) any idea how to disable the button ?      

      UITextField *textField;

            BlockTextPromptAlertView *alert = [BlockTextPromptAlertView promptWithTitle:@"Name" message:@"Enter your name " textField:&textField];

            [alert addButtonWithTitle:@"okay" block:^{

                NSLog(@"Text: %@", textField.text);

                if ([textField.text isEqualToString:@""]) {
                     // dont’t close the view until the user types something

                    return;

                }

                self.text=textField.text;

            }];

            [alert show];

    • http://blog.codecropper.com/ Gustavo Ambrozio

      It is possible, for sure. The buttons are just instances of UIButton so you can call btn.enabled=NO. Just look inside the code and you’ll see everything should be easy to manipulate.

  • jackarotor

    I have a problem. I implemented the BlockTextPromptAlertView, and it works perfectly. But when i pop open the alertview and go the background and then come to foreground in another 1 hour or so, the keyboard appears above the Alertview (1/2 of the alertview is covered by the keyboard). So i am unable to click on any button on the alertview. The BlockTextPromptAlertView has an animation so this might be the reason, The BlockTextPromptAlertView might have got stuck when it was animating. How can i fix this issue ?

    • http://blog.codecropper.com/ Gustavo Ambrozio

      No idea really. This component was implemented later by another developer that issued a pull request and I just incorporated his code into my source. But this should not be this hard to fix. Take a look inside the source code, fork it and if you fix it issue me a pull request. Thanks

  • Natan Rolnik

    Oi, Gustavo!
    Estou usando seu BlockAlerts And ActionSheets em um dos meus projetos. Antes de mais nada, parabéns! Muito bem escritos.

    No entanto, um pequeno probleminha, acontece comigo. Quando uso o
    PromptAlertView no device, acontece que o AlertView não sobe e fica
    escondido atrás do teclado, erro que não acontece no simulador. Postei a
    pergunta no StackOverFlow, se puder, dê uma olhada: http://stackoverflow.com/questions/10672040/uiview-animatewithduration-completion-block-delayed-on-device

    • http://blog.codecropper.com/ Gustavo Ambrozio

      Já aceitei seu pull request. Obrigado pela correção.

  • http://www.nkyea.com/ Nana Sarpong

    If I just want the alertView to fade in from the middle like the standard alert and not drop from the top, what do I have to change in BlockAlertView.m to achieve this. Thanks.

    • http://blog.codecropper.com/ Gustavo Ambrozio

      Animations are done at the end of the show and

      dismissWithClickedButtonIndex of the BlockAlertView class. Just change the animation to whatever you want! Your imagination is the limit!

  • Xaphann

    Love it. Just wondering if you are going to do an ARC version as well?

  • Mike

    Is this going to be updated to iOS 6? I’m getting 17 warnings here.

  • Laurent Daudelin

    Nice job Gustavo, except it won’t support landscape orientations at all. I’m not talking about the rotation happening after the BlockActionSheet has shown up, even if the device is rotated *before* the BlockActionSheet shows, it will draw sideways because it seems to draw in the BlockBackground which is a subclass of UIWindow. From what I read, UIWindows always use portrait orientation. It’s when you add a rootViewController that this one can start managing the rotation. Since the code makes use of that BlockBackground in a few places, I was unable to add a rootViewController to handle the rotation. Bummer. Really liked it but, these days, not supporting orientation is a no show.

    • http://blog.codecropper.com/ Gustavo Ambrozio

      Laurent,

      I’ve had no time lately to maintain the project but there are a number of forks that have added orientation support. Check out the network of forks on GitHub, there are some well maintained forks out there. I’m thinking about giving some of these guys write privileges in order to have a better master project.

      • Laurent Daudelin

        Thanks, Gustavo. I’ll check it out!

  • http://www.facebook.com/rtayal11 Rishabh Tayal

    Does some one know if we could impose validations on textfield in BlockTextPromptAlertView? I love this control, but I need to restrict user to enter something in the textfield when block prompt view is shown.

  • Dermot O Sullivan

    Hi, Thank you for this. Just thought I’d let you know i’ve added this to my upcoming 2.0 update of my GroovePond app. Its exactly what I was looking for. Great work!
    (I’m just looking up your blog to give you a mention in the acknowledgements)

  • Oriol

    Hi,

    I am trying to use your library but when I add the .h/.m files (included on ToAddToYourProjects folder) on my project I am getting multiple errors like just building the project…..

    /Volumes/xCodeMacBookAir/SAPToolKitV2/SAP Toolkit/BlockTableAlertView.m:40:13: ‘autorelease’ is unavailable: not available in automatic reference counting mode

    /Volumes/xCodeMacBookAir/SAPToolKitV2/SAP Toolkit/BlockTableAlertView.m:40:13: ARC forbids explicit message send of ‘autorelease’

    Could you help me on this? I guess that I have to amend any setting…. I saw in the forum that this library works with ARC.

    What I need to change???

    Thanks in advance,

    Best regards,

    Oriol

  • Karen Anne

    Hi, could I use image buttons on this? Thanks. :)

    • http://blog.codecropper.com/ Gustavo Ambrozio

      Not as is but it should not be hard to change to code to achieve this.

  • Alfarider

    Great job , but i want to change the button frame and background it’s possible or not ?
    Thanks.

    • http://blog.codecropper.com/ Gustavo Ambrozio

      Yes it is. You’ll find the current assets in the source. Just change them.