COCOA


28
Jul 11

Pixel Perfection – is it worth going the extra step?

Hey,

I thought id write a quick post about…well, the things you may not notice, some of you may, some might not, I’m talking about “the little things” which make an application’s UI that extra bit more awesome over competition.

Caffeinated took on the 3 column design along time ago, since then, magically after I released few early screens, we have seen more applications / developers have adopted this. Im pretty sure I wasn’t the first, but I think a trend got set, so it was for the best. But lets look at the smaller things which I spend many hours trying to make :

First up, split views…

I hate dealing with split views, they give you this horrible line which doesn’t really go with anything with your application. Sure you can change the colour and its width, but for me, that wasn’t enough, behold this small thing that I’m sure not many people would even notice…until I take it away…

Looks pretty normal…but you will actually notice, the top 40px of the split views vertical line is actually a different colour then the rest, this is so it works well next the the filter bar. who knew!

Another thing that really gets on my nerves are having the table view grid lines for a selected item always in view. Correct me if I’m wrong, but if you select an item, surely its grid lines should not be in view?

Its ever so small, but its also the same with if a table cell is selected / in-between two “group items” then I remove the grid lines around it and if its selected, remove the appropriate selected lines depending on its surroundings.

Like-wise same principle with sticky row headers – I’m not sure how Apple have done this 10.7 but its rarely straight forward……until you add in transparency, transparency caused me grief, I think it looks cool but its adding the extra bit of complexity into the overall question “how do I get this to work?”

The way the group cells work within Caffeinated is by grabbing the prepared cell, and drawing it over the top of the content within the tableviews drawing methods, this is fine, but it also means that the cell thats sticky is still inside the table and would be visible under the transparent group cell which is the exact clone of it.

Compare the two :

The top one has its non sticky version of the cell directly behind it, as you notice, you have to make it non transparent for this to actually look good…or it looks confusing! The bottom one is fine as the cell thats within the scrolling table is off the top of the view which means we can make this transparent.

There are a bunch of little things here and there which I have spent a lot of time finessing. Some I’m sure you would never ever notice were there. Im hoping my concentration to detail and pixel perfection will make Caffeinated a great user friends application for you wonderful people to use!

Feel free to post comments :).


30
Nov 09

Quick glance at NSOperationQueue

I was recently having a quick play with threading in COCOA ( because I needed to run some code on another thread ) and stumbled across NSOperationQueue within the docs. Basically, NSOperationQueue handles NSOperation’s, you give it an NSOperation, it will queue it, and run it when it gets to that part in the queue, but the cool thing is … it runs the NSOperation on another thread!

Its really simple to use, to run your own code / class, you ust subclass NSOperation and have a method called main which doesn’t return anything, so … – (void)main {}. main will get invoked when the item gets called, once all your code has done what it was set out to do, you simple have to perform a selector on the main thread and do what ever you like.

All that said and done, its pretty god damn awesome!, if you haven’t had a look at it yet, its worth a go :D.


13
Sep 09

A simple COCOA Asynchronous image loader class to use in your iPhone app.

Updated version here : http://www.geekygoodness.com/2011/06/17/uiimage-from-url-simplified/

This isnt a tutorial, this is just some source code that you might find useful. This class will load images in the background so it wont lock your UI up!

Heres the header file :

@interface GGImageLoader : NSObject {
 
	NSURLConnection * connection;
 
	NSURL * url;
 
	NSMutableData * mutData;
 
	UIImage * image;
 
	id delegate;
 
}
 
@property ( nonatomic, retain ) UIImage * image;
 
- (id)initWithURL:(NSURL *)aURL;
- (void)setDelegate:(id)anObject;
- (void)load;
 
@end
 
@protocol GGImageLoaderProtocol
 
@required
- (void)imageLoader:(GGImageLoader *)loader
	   didLoadImage:(UIImage *)anImage;
 
@optional
- (void)imageLoader:(GGImageLoader *)loader
	didReceiveError:(NSError *)anError;
 
@end

and heres the main file :

#import "GGImageLoader.h"
 
@implementation GGImageLoader
 
@synthesize image;
 
- (void)dealloc
{
	[url release];
	[connection release];
	[mutData release];
	[image release];
        [super dealloc];
}
 
- (id)initWithURL:(NSURL *)aURL
{
	url = [aURL retain];
	return self;
}
 
- (void)setDelegate:(id)anObject
{
	delegate = anObject;
}
 
- (void)load
{
	// SHOW NETWORK INDICATOR
 
	[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
 
	// SET UP THE REQUEST
 
	NSURLRequest * request = [[[NSURLRequest alloc] initWithURL:url] autorelease];
 
	// SET UP THE CONNECTION
 
	connection = [[NSURLConnection alloc] initWithRequest:request
												 delegate:self];
 
	// NEW MUT DATA
 
	mutData = [[[NSMutableData alloc] init] retain];
 
}
 
- (void)connection:(NSURLConnection *)connection
  didFailWithError:(NSError *)error
{
	if( [delegate respondsToSelector:@selector(imageLoader:didReceieveError:)] )
	{
		[delegate imageLoader:self
			  didReceiveError:error];
	}
}
 
- (void)connection:(NSURLConnection *)connection
	didReceiveData:(NSData *)data
{
 
	// APPEND THE DATA
 
	[mutData appendData:data];
}
 
- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection
{
 
	// ONCE LOADED HIDE NETWORK INDICATOR
 
	[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
 
	// RELEASE THE CONNECTION
 
	[connection release];
 
	// CREATE NEW UIIMAGE FROM THE DATA
 
	image = [[[UIImage alloc] initWithData:mutData] retain];
 
	if( [delegate respondsToSelector:@selector(imageLoader:didLoadImage:)] )
	{
		[delegate imageLoader:self
				 didLoadImage:image];
	}
 
}
 
@end

Its pretty self explanatory, meerly do the following to get it to work..

GGImageLoader * imageLoader = [[[GGImageLoader alloc] initWithURL:[NSURL URLWithString:@"myimageurlhere"]] retain];
[imageLoader setDelegate:self];
[imageLoader load];

The class also has delegate methods and a protocol to follow, so we know when the image has loaded, you can use the GGImageLoaderProtocol in your header file if you like.

- (void)imageLoader:(GGImageLoader *)imageLoader didReceieveError:(NSError *)anError
{
}
 
- (void)imageLoader:(GGImageLoader *)imageLoader didLoadImage:(UIImage *)anImage
{
	// BE SURE TO RELEASE THE IMAGE LOADER
	[imageLoader release];
}

and thats about it, hope its helps some people out!

If ive made a mistake anywhere in this please say, it was a rush post!