iOS 5 Twitter SDK Available

October 13, 2011 12 comments

I could not find anyway online for testing if the user had the Twitter API available (IE: they’re running iOS 5). The best solution I came up with was to instantiate the TWTweetComposeViewController and check if it is nil. If so then I don’t include any references to Twitter in my app.

-(BOOL) twitterSDKIsAvailable{
    TWTweetComposeViewController *tweetViewController = [[TWTweetComposeViewController alloc] init];
    BOOL twitterSDKAvailable = tweetViewController != nil;
    if(tweetViewController != nil){
         [tweetViewController release];
    }

    return twitterSDKAvailable;
}

Adding state to NSURLConnection

July 8, 2011 2 comments

When you want to make a data request in Objective-C you typically use NSURLConnection and can either do it synchronously or asynchronously. Obviously the later is the preferred choice so you don’t lock out the thread. Unfortunately, you will run into the problem where you want to make concurrent requests and you’ll find it doesn’t work. This usually happens because you set your class as the delegate and if you kick off another request it’ll step on top of the previous one returning the wrong data. One way around this is to keep a NSMutableDictionary of NSMutableData objects using the NSURLConnection as the key. Unfortunately you can’t do this with NSURLConnection as it doesn’t have a unique identifier that you can use.

Unfortunately you can’t use categories for this since they only allow you to add in methods, and subclassing just to add a field is not the most elegant solution. Luckily for us Objective-C has something nifty called Associative References. Creating an associative reference will let you add data storage (AKA a new iVar) to an existing class without the need to sub-class it.

So enough jabbering, here’s an example:

DataProxy.h

#import <Foundation/Foundation.h>

@interface DataProxy : NSObject {
    NSMutableDictionary *dataStreams;
}

-(void) getData: (NSMutableArray*) arguments withDict: (NSMutableDictionary*) options;

-(NSString*) createUUID;

-(void) removeDataStream: (NSString*) uuid;
    
@property(nonatomic, retain) NSMutableDictionary *dataStreams;

@end

DataProxy.h

#import "DataProxy.h"
#import <objc/runtime.h>

@implementation DataProxy
@synthesize dataStreams;

static char dataInstanceKey;

-(void) getData: (NSMutableArray*) arguments withDict: (NSMutableDictionary*) options{
    if(dataStreams == nil){
        dataStreams = [[NSMutableDictionary alloc] init];
    }
    
    NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[options objectForKey:@"url"]]
                                         cachePolicy:NSURLRequestUseProtocolCachePolicy 
                                     timeoutInterval:8.0];
    
    // The caller should set the UA
    [req setValue:[options objectForKey:@"ua"] forHTTPHeaderField:@"User-Agent"];
    
    // Create a UUID to associate with the request
    NSString *uuid = [self createUUID];
    
    // Create & store data keyed off of the UUID
    NSMutableDictionary *ds = [[NSMutableData alloc] initWithCapacity:2048];
    [dataStreams setObject:ds forKey:uuid];
    [ds release];
    
    // Create a URL connection
    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
    
    // Add an associative reference to the connection to keep the key for the data
    objc_setAssociatedObject(conn, &dataInstanceKey, uuid, OBJC_ASSOCIATION_RETAIN);
    
    // Kick off the connection
    [conn scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    [conn start];
    [conn release];
}


#pragma mark -
#pragma mark Private

-(NSString*) createUUID{
    CFUUIDRef theUUID = CFUUIDCreate(NULL);
    CFStringRef str = CFUUIDCreateString(NULL, theUUID);
    CFRelease(theUUID);
    
    return [(NSString*) str autorelease];
}

-(void) removeDataStream: (NSString*) uuid{
    NSMutableData *data = (NSMutableData*) [dataStreams objectForKey:uuid];
    if(data != nil){
        data = nil;
        [dataStreams removeObjectForKey:uuid];
    }
}


-(void) connection: (NSURLConnection *) theConnection didReceiveData: (NSData *) incrementalData{
    // Pull the key out of the connection (we add when the connection is instantiated)
    NSString *uuid = (NSString*) objc_getAssociatedObject(theConnection, &dataInstanceKey);
    
    // Add the data to the correct stream
    [[dataStreams objectForKey:uuid] appendData:incrementalData];
}

-(void) connectionDidFinishLoading: (NSURLConnection*) theConnection{
    // Pull the key out of the connection (we add when the connection is instantiated)
    NSString *uuid = (NSString*) objc_getAssociatedObject(theConnection, &dataInstanceKey);
    
    // Get the correct data
    NSMutableData *data = (NSMutableData*) [dataStreams objectForKey:uuid];
    
    // Convert the result into a string
    NSString *response = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];

    // Do something with the response!    

    [response release];
    
    // Remove the data
    [self removeDataStream:uuid];
}

-(void) connection: (NSURLConnection*) connection didFailWithError: (NSError*) error{
    // Pull the key out of the connection (we add when the connection is instantiated)
    NSString *uuid = (NSString*) objc_getAssociatedObject(connection, &dataInstanceKey);
    
    // Do something with the error
    NSString *error = [error localizedDescription];

    // Remove the data
    [self removeDataStream:uuid];
}

#pragma mark -
#pragma mark Memory Management

- (void)dealloc {
    for(id data in dataStreams){
        if(data != nil){
            data = nil;
        }
    }    
    [dataStreams release], dataStreams = nil;
  
    [super dealloc];
}

@end

Fixing network printer issue on OSX 10.6.8

June 30, 2011 15 comments

The latest rollout of OSX 10.6.8 has an issue where it can no longer print to most network printers (over IP). To fix it you simply replace four files that cups uses and restart the service. Download the zip file below with the replacement files (from 10.6.6) and a shell script that will take care of everything for you.

http://zomgdinosaurs.com/printer_fix.zip

Thanks to http://blog.digitechhosting.com/?p=421 for the help.

Below is the script that does the heavy lifting for you:

#!/bin/bash  

echo "Fixing printers!"

echo "Checking your version of OSX"
ver=$(system_profiler SPSoftwareDataType | grep 'Mac OS X 10.6.8')
if [ -z "$ver" ]
then
  echo "You aren't running 10.6.8!"
  exit
fi

echo "You're running: $ver"
echo "Backing up files.."
mkdir ~/PrinterBackup
sudo cp /usr/libexec/cups/backend/dnssd ~/PrinterBackup/dnssd.bak
sudo cp /usr/libexec/cups/backend/lpd ~/PrinterBackup/lpd.bak
sudo cp /usr/libexec/cups/backend/ipp ~/PrinterBackup/ipp.bak
sudo cp /usr/libexec/cups/backend/socket ~/PrinterBackup/socket.bak

echo "Replacing 10.6.8 files with 10.6.6 files"
sudo cp dnssd /usr/libexec/cups/backend/dnssd
sudo cp lpd /usr/libexec/cups/backend/lpd
sudo cp ipp /usr/libexec/cups/backend/ipp
sudo cp socket /usr/libexec/cups/backend/socket

echo "Restarting cups"
sudo killall cupsd
sudo cupsd

echo "You should be good to go"

iOS Retina Sprites

May 11, 2011 5 comments

One of the great things about the iPhone 4 is the Retina Display. Native iOS apps make handling the switching between the non-retina and retina version of the image really easy. Simply supply the two files and suffix one with “@2x” and it handles the rest (ex: 1.png, 2@2x.png). Taking advantage of the retina display in a web app is not so easy, especially if you want to use sprites.

This example will assume that you have three images that you wish to turn into a sprite that will support both retina and non-retina displays.

Create Images

Retina images are basically twice the size of the non-retina version which is then rendered into the non-retina dimensions to double the DPI. This means that if you want a retina and non-retina version of an image you should start out with the retina version (lets say, 50px x 50px) and then generate your scaled down version at 50% (25px x 25px).

In our example we will have three images: a, b and c. These images are to be shown at 56px x 22px on the screen. This means that our retina version will need to be 112px x 44px and our non-retina version should be 56px x 22px. Once you have the retina and non-retina version of all three images (you should have six images total) you’ll want to create a zip file for the retina images and a zip file for the non-retina images.

Generate Sprites

There are a lot of useful services and tools that will generate your sprites for you. For this example we are going to be using the CSS Sprite Generator service at http://spritegen.website-performance.org/.

The settings between retina and non-retina are going to be slightly different so pay close attention to the different settings.

Generating Non-Retina Sprite:

  1. Select your zip file, be sure to pick the non-retina zip.
  2. Under “Sprite Output Options” > “Build Direction” choose “Horizontal”.
  3. Under “Sprite Output Options” > “Horizontal Offset” enter “25px”.
  4. Click “Create Sprite Image & CSS”

Save the outputted file as “test-sprite.png” and copy the generated CSS to a temporary file, we’ll come back to it momentarily.

Generating Retina Sprite:

  1. Select your zip file, be sure to pick the retina zip.
  2. Under “Sprite Output Options” > “Build Direction” choose “Horizontal”.
  3. Under “Sprite Output Options” > “Horizontal Offset” enter “50px”.
  4. Click “Create Sprite Image & CSS”

Save the outputted file as “test-sprite@2x.png”, you can ignore the CSS generated.

You probably notice that the only main difference between generating the retina and non-retina sprites was the horizontal offset. Basically we are going to have web kit scale our retina version by 50% so we want the offsets between the images in the sprite to remain the same. This means that the horizontal offset between the images will need to be doubled in the retina sprite, just like the images themselves.

Generate CSS/HTML

Unfortunately we aren’t so much generating CSS as we are piecing together some previously generated CSS.

Sample HTML

Here’s the HTML that we’re going to be styling:

<div class=”test-sprite” id=”a”></div>
<div class=”test-sprite” id=”b”></div>
<div class=”test-sprite” id=”c”></div>

Base CSS

Let’s define the test class which will be where we handle setting our default sprite properties (non-retina):

.test-sprite{
	background-image: url(images/test-sprite.png);
	width:56px;
	height:22px;
}

Take note of the width and height, it’s the size of the non-retina images. When we insert our retina version the browser will handle scaling them down to fit the correct dimensions. Now we need to specify our retina sprite, we do this via a CSS override of the previous class’ background image. The override is handling using CSS3 Media Selectors:

@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
       only screen and (min--moz-device-pixel-ratio: 1.5),
       only screen and (min-resolution: 240dpi) {
		.test-sprite{
			background-image: url(images/test-sprite@2x.png);
			-moz-background-size: 218px 22px;
			-o-background-size: 218px 22px;
			-webkit-background-size: 218px 22px;
			background-size: 218px 22px;
		}
}

Here you can see we overrode the background image with our retina version as well as specified a background size. If you pay close attention you’ll notice that the dimensions do not match those of the image, but rather those of the non-retina image – this is where we utilize the browser to handle our retina scaling.

Sprites

Now its time to create our sprite classes, this is the easy part. You’ll need to reference the generated sprite CSS from the non-retina, it’s very important that you use the offsets provided by it rather then the retina version. All you care about is the background-position variable, the rest you’ll fill in yourself:

#a{ background-position: 0 50%; }
#b{ background-position: -81px 50% }
#c{ background-position: -162px 50% }

That was the easy part, just a simple background position offset with a 50% horizontal/vertical offset.

Uppercase Words in a JS String

April 7, 2011 2 comments

I ran into a problem today where our geo coder returns city names in all uppercase. Obviously this doesn’t look very good when you print it out to the screen so I wanted to make it pretty. A good example is Young America, MN. We get “YOUNG AMERICA”.. Here’s a quick way to clean it up using jQuery:

$.map("YOUNG AMERICA".split(" "), 
    function(s){ 
        return s.charAt(0).toUpperCase() + s.toLowerCase().slice(1); 
    }
).join(" ");

Explode the string into an array by splitting on the space, map that array into a function that returns the first character uppercased and the remaining characters in lower case. Then join the outputted array by a space.

This converts “young america” to “Young America”.

jQuery Mobile Slider Events

March 29, 2011 2 comments

Out of the box there is no way to ask a jQuery slider to notify you when the value changes. This was problematic for me on a mobile app as I needed to know as soon as the user toggled the component. Some googling didn’t turn up anything helpful and I was hesitant to add a custom trigger. Now don’t get me wrong, there were lots of examples dealing with the programatic interaction with sliders, but none where you weren’t the creator of the slider (in this case jQuery Mobile automagically does it).

After a little head scratching I realized that I could monitor the change event on the underlying select element that the slider was bound to. The only catch was to filter out change events that weren’t really changing the value.. The reason for this was because if you held your finder on the slider and drug it around the on state (example: half drag through the off side) the change event on the select element is continuously fired. Simply storing the previous state of the button did the trick.

Sample button HTML:

<div data-role="page" id="sample">
    <div data-role="header">
        <h1>Sample Page</h1>
    </div>
    <div data-role="content">    
        <ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b">
            <li>Toggle Me <select name="slider" id="toggle-me" data-role="slider">
                <option value="off">Off</option>
                <option value="on">On</option>
            </select> 
            </li>
        </ul>
    </div>
</div>

JavaScript

var oldVal = $("#toggle-me").bind("change", function(){ 
    if(oldVal != $(this).val()){
        oldVal = $(this).val();
        console.log("val change to " + oldVal);
    }
 }).val()

Unable to access an error message corresponding to your field name

November 22, 2010 Leave a comment

If you use CodeIgniter and you have custom field validators you may have encountered this error before “Unable to access an error message corresponding to your field name”. I scratched my head for awhile on this one as I was calling $this->validation->set_message(…) in my validators. But oops, looks like I changed the function name and didn’t reflect it in the first parameter that set_message requires, which is the function name.

I don’t get why CI wants you to specify the function name when they can easily figure it out. Anyway, here is my new solution that will avoid this from happening ever again:

	function _duplicate_URL_check($URL){
		$this->load->model('Page_model');
	    $page = $this->Page_model->get_page_by_url($URL);      
	    
	    if(count($page) != 0){
	        $this->validation->set_message(__FUNCTION__, 'The URL you entered is already used.');
	        return FALSE;
	    }                
	    else{
	        return TRUE;
	    }
	}

All you have to do is replace “_duplicate_URL_check” with __FUNCTION__, which is PHP’s magic keyword for the current function’s name, and you’ll be good to go! :)

Follow

Get every new post delivered to your Inbox.