iOS 6 UIRefreshControl – Pull To Refresh Like Mail App

viewDidLoad:

self.refreshControl = [[UIRefreshControl alloc] init];    
[self.refreshControl addTarget:self action:@selector(refreshView:) forControlEvents:UIControlEventValueChanged];

Refresh:

- (void)refreshView:(UIRefreshControl *)sender {
    //Refresh...
    NSLog(@"Refresh");
    
    [sender endRefreshing];
}

Source: http://stackoverflow.com/questions/12607015/uirefreshcontrol-ios-6-xcode

Extract (uncrush) Images from an iOS App

Often I’ll see an app incorporate a new UI implementation that really impresses me. Still being a learner, I always wonder how these elements are coded or put together — is it an image trick? Maybe a CGGradientLayer? How are they able to achieve so much speed? It’s times like these that it helps to get a small peek under the hood. Like Mac apps, iOS apps are bundled together basically as a zip file — you can actually change the IPA extension to ZIP and unarchive the app very easily. The limitation here is Xcode compresses (or ‘crushes’) the png’s used in an app to keep the file size down. Luckily, since iOS 3.2, the command line tool that compressed these images included the added functionality of decompressing them. Peter Boctor (of iDevRecipes) wrote a Ruby script called App Crush that would uncrush the png files (with instructions here) but it hasn’t been updated in about a year. Since then, Apple has changed how Xcode is deployed (through the App Store these days) and the location in which they put it. It’s very easy to update the Ruby script to find the new Xcode and several have. I wanted to make it just a tad easier and created an Applescript Droplet that allows you to drag the IPA onto it and uncrushes the png files. You can download it here. I’ve also made this version’s source available here. This is my first attempt at an AppleScript Droplet (which seems like a dying tech) so if you see something that could be done better, let me know!

Usage instructions:

  1. If you don’t know the location of the IPA (app) you’d like to uncrush, open iTunes and click the apps tab, right click on the app you’d like and click “Reveal in Finder”
  2. Drag IPA onto the App Uncrusher
  3. It’ll take up to a few minutes to finish and you’ll have a folder called “APPNAME images” on your desktop that should be full of pngs.

Be ethical with this. Don’t steal another app’s images and call them your own.

It’s a Native Day

Facebook released their native iOS app today, finally putting to rest their wrapped UIWebView HTML5 frankenstein of an app. The performance improvement I’ve noticed thus far is amazing: more responsive, more predictable and noticeably faster — it just feels better.

My experience with iOS development started with PhoneGap and after noticing it just wasn’t going to do what I needed it to do, I started down the road of learning Objective-C and haven’t looked back since. The performance difference and the lack of Nitro in UIWebViews makes a huge difference. You’ll never be cutting edge by cutting corners.

In an article by Eric Allam entitled “Go Native or Go Home” he discusses the benefits of developing natively. He quotes Steve Jobs from his famed open letter to Adobe regarding flash:

We know from painful experience that letting a third party layer of software come between the platform and the developer ultimately results in sub-standard apps and hinders the enhancement and progress of the platform. If developers grow dependent on third party development libraries and tools, they can only take advantage of platform enhancements if and when the third party chooses to adopt the new features. We cannot be at the mercy of a third party deciding if and when they will make our enhancements available to our developers.

This becomes even worse if the third party is supplying a cross platform development tool. The third party may not adopt enhancements from one platform unless they are available on all of their supported platforms. Hence developers only have access to the lowest common denominator set of features. Again, we cannot accept an outcome where developers are blocked from using our innovations and enhancements because they are not available on our competitor’s platforms.

With all the talk of Apple TVs, iPad minis and the simple fact that Apple is continuing to increase their value, there’s never been a better time to learn Objective-C.

Using custom fonts on iOS (iPhone iPad)

This is a quick walk-through on using a font other than those supplied by Apple on an iOS device.

For reference purposes, you can find out what fonts are available to you “out of the box” by checking out this comprehensive list:
http://iosfonts.com/

I’m going to be using Bebas for my example, a great font created by Dharma Type. You can pick it up here: http://www.dafont.com/bebas.font or use a font of your own choice. It’s important to note you should check a font’s license before you use it in an app you intend to distribute in the app store.

If your font’s not installed on your Mac, go ahead and install it. Before we get too deep into coding and while you’re in or around Font Book let’s go ahead and get the PostScript name of your font. You can do this by selecting your font from the list inside of Font Book and pressing Command + I to toggle the font information. The right side of the window will look like this:

The PostScript name is listed on the top, with Bebas, the PostScript name is simple… it’s Bebas but most are more complicated. Take the PTSans family for example: PTSans-Regular to PTSans-CaptionBold. Keep this PostScript name handy as we’ll reference it later.

Moving on let’s get the ttf file into an Xcode project.

I started with a Single View Application template, go ahead and get that going as normal. Inside my Supporting Files folder I’m going to create a group named “Fonts”. I’m going to drag BEBAS___.TTF into that directory and make sure “Copy items into destination group’s folder (if needed)” is checked. Click finish.

Next, open your app’s plist. Right click and add a row, we’re going to add the key “Fonts provided by application” which is an array of the ttf font files. Toggle that down and for Item 0 add BEBAS___.TTF.

Now you need to head over to your project’s build phases tab. Click to the “Copy Bundle Resources” and click the + icon to add a new item and choose BEBAS___.TTF.

Now, when your window looks like this, you’re ready to use the font in the application:

I put some simple code to create a UILabel in my viewDidLoad method like this:

    UILabel *bebasFlavoredLabel = [[UILabel alloc] initWithFrame: CGRectMake(0, 0, 320, 44)];
    bebasFlavoredLabel.text = @"Bebas on iPhone";
    [bebasFlavoredLabel setFont: [UIFont fontWithName:@"Bebas" size:15]];

    [self.view addSubview: bebasFlavoredLabel];

On line 3 you see where we use [UIFont fontWithName:@"Bebas" size:15]. The name you use there is the PostScript name you found at the beginning. Go ahead and run:

Viola! Your font is ready to be used as you wish!

Scanning a Bar Code with ZBarSDK

We’re going to focus on scanning UPCs, however I believe the ZBarSDK can be used to scan QRCodes and that may be the topic of another tutorial at a later date (feel free to leave a comment or tweet at me if you would be interested). You can download the sample project here.

To get started I’m going to create a new project and use the Single View template. We’ll need to add a few frameworks to our project:

AVFoundation.framework
CoreMedia.framework
CoreVideo.framework
QuartzCore.framework
libiconv.dylib

You’ll need to download the ZBarSDK from here: http://zbar.sourceforge.net/iphone/ (you’ll need to scroll about halfway down to the section titled “iPhone Developers”. Once you’ve downloaded the DMG file it’s pretty straightforward about how to get the library into your project:

Go ahead and drag the ZBarSDK folder into your XCode project.

In our ViewController’s header we need to import the ZBarSDK header file:
#import "ZBarSDK.h"

Let’s also make our ViewController a ZBarReaderDelegate:
@interface ViewController : UIViewController

While we’re in the header let’s go ahead and declare an IBOutlet for a UIButton named “scanButton”:

IBOutlet UIButton *scanButton;

@property (nonatomic, retain) IBOutlet UIButton *scanButton;

Also be sure to @synthesize:

@synthesize scanButton;

Next we’ll create an IBAction for the scanButton called scanButtonPress:

-(IBAction) scanButtonPress:sender;

Your ViewController’s header should now look like this:


#import <UIKit/UIKit.h>
#import "ZBarSDK.h"

@interface ViewController : UIViewController <ZBarReaderDelegate> {
    IBOutlet UIButton *scanButton;
    
}

@property (nonatomic, retain) IBOutlet UIButton *scanButton;

-(IBAction) scanButtonPress:sender;

@end

Go ahead and create a button in Interface Builder and link it to the outlet and action we’ve created:

Next let’s work on the scanButtonPress action:

-(IBAction)scannerPress:(id)sender{
    
    ZBarReaderViewController *reader = [ZBarReaderViewController new];
    reader.readerDelegate = self;
    
    [reader.scanner setSymbology: ZBAR_UPCA config: ZBAR_CFG_ENABLE to: 0];
    reader.readerView.zoom = 1.0;
    
    [self presentModalViewController: reader
                            animated: YES];
    
}

We’ll go through line by line:

On line 3, we create a new ZBarReaderViewController and on line 4, set our ViewController as the delegate. On line 6-7, we set up the reader and tell it we’re going to be scanning a UPC (ZBAR_UPCA, you can read about the supported symbologies here) and we want the zoom level to be 1.0. Finally, on line 9, we show the reader. If you’ve ever used the UIImagePickerController. This will begin to seem familiar.

Now we need to setup our delegate method — this is pretty vanilla code from the SDK documentation:

- (void) imagePickerController: (UIImagePickerController*) reader
 didFinishPickingMediaWithInfo: (NSDictionary*) info
{
    id<NSFastEnumeration> results = [info objectForKey: ZBarReaderControllerResults];
    
    ZBarSymbol *symbol = nil;
    
    for(symbol in results){
           
        NSString *upcString = symbol.data;
        
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Scanned UPC" message:[NSString stringWithFormat:@"The UPC read was: %@", upcString] delegate:self cancelButtonTitle:nil otherButtonTitles:@"Ok", nil];
        
        [alert show];
        
        [reader dismissModalViewControllerAnimated: YES];
        
    }
    
    
}

Basically the Picker can return multiple results, so we’ll enumerate through those (lines 4-8 — also the for loop). On line 10 we actually pull the UPC result from the data returned from the Picker (ZBarReaderViewController) and then on lines 12 and 14 we display that UPC with an alert and dismiss the ZBarReaderViewController modal on line 16.

Again, this is very vanilla information available to you in the official SDK documentation, which is available here, where you’ll also find additional information about the ZBarSDK.

It’s important to note that because the reader uses the camera you will have to run this on an actual device (not the simulator) to test it.

Post-Release Development Bundle Identifiers and Display Names

So you’ve released version 1.0 and it’s in the App Store but you’ve noticed a few bugs and there are still those features you were holding out until 1.0.1. You tweak some code and test on your device but now you’ve lost the current release version because they both have the same bundle identifier. Sometimes …most of the time, as a developer it’s important for you to have both the current release version AND the current beta version on your device. Project’s aren’t configured like this out of the box but it is certainly possible to make this happen without manually changing the bundle identifier every time by way of User Defined Build Settings and variables.

If you take a look at your Application’s plist, you’ll see your bundle name, and bundle identifier along with other information about your app. You’ve probably seen a few fields that include variables that look like this: ${PRODUCT_NAME} or ${EXECUTABLE_NAME}. We’re going to use that system to change the bundle identifier and the bundle display name dependent on the build-type (Debug, Release, Ad Hoc, etc).

To get started, open up your Application Target and click the Build Settings tab:

Once you have this open, click the “Add Build Setting” button in the lower right corner:

Then click “Add User-Defined Setting”. You’ll see XCode adds a section named “User-Defined” and a new setting for you to type in. Type in BUNDLE_DISPLAY_NAME_SUFFIX and hit enter. We’re going to use this as a string to append to our bundle display name (the name of the app that shows on the springboard). Now you should see this:

You can enter in whatever value you like for debug, a few common or recommended ones are “Beta”, “B”, ß but you can use whatever you want. Don’t enter a value in for release as we don’t want to append anything when we build for release as that build should be headed for the app store.

Next, let’s add another User Defined Setting and called this one BUNDLE_IDENTIFIER_SUFFIX. For this you can, again, enter any value you like for Debug. This is appended to the bundle identifier and since an iOS requires unique bundle identifiers this beta version of the app needs one different than the release version. I usually use ‘.dev’ for this field but you could use something like ‘.beta’ or whatever you’d like. So now your settings should look similar to this:

Now that we have the variables set let’s go to the application’s plist and use them. In the bundle display name field simply append ${BUNDLE_DISPLAY_NAME_SUFFIX} to whatever is already there. Move on to the Bundle identifier field and add ${BUNDLE_IDENTIFIER_SUFFIX} and append that to the existing data there. When complete, you’ll see something like this:

Now you’re set. When you build for Debug releases your app will be named with your appended string as well as your bundle identifier. You’ll be able to keep the current release from the app store installed as well as your development build build XCode or TestFlight!