Category Archive: Code

Rasterizing a UIView

I was doing some work with parsing and visualising SVG files but the views ended up having lots of paths and a lot of memory was consumed. So the idea was to convert the UIView to an image … :)

 
// Doing work to generate the SVG in the schematics view;
// At the end there was no reason to keep all these (SVGView)subviews 
// ******* Rasterize ************
// Create an image from the view
 
    UIGraphicsBeginImageContext(schematicsView.frame.size);
    [schematicsView.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
 
// Remove the SVG views to release the memory.
    for (SVGView *view in SVGReferences) 
        [view removeFromSuperview];
 
// Add the image that was created before as a subview
    [self.view addSubview:[[[UIImageView alloc] 
                            initWithImage:viewImage] autorelease]];

I swear pure awesomeness!!! :)

NSCoder + NSKeyedArchiver

This post is a simple example of NSCoder and NSKeyedArchiver to save and restore the data of an instance.

First of all we need to create our object, in this case an object “Person” with three properties (name, surname, age). The interface looks like normally.

#import <Foundation/Foundation.h>
@interface Person : NSObject { }
@property (retain) NSString *firstName;
@property (retain) NSString *lastName;
@property int age;
@end

The implementation needs some additional code. We need to implement the NSCoding protocol, which means two additional methods. (initWithCoder: and encodeWithCoder:)

#import "Person.h"
@implementation Person
@synthesize age,firstName,lastName;
-(id)initWithCoder:(NSCoder*)decoder{
    if ((self = [super init])) {
        firstName = [decoder decodeObjectForKey:@"firstName"];
        lastName  = [decoder decodeObjectForKey:@"lastName"];
        age           = [decoder decodeIntForKey:@"age"];
    }
    return self;
}
-(void)encodeWithCoder:(NSCoder*)encoder{
    [encoder encodeObject:firstName forKey:@"firstName"];
    [encoder encodeObject:lastName forKey:@"lastName"];
    [encoder encodeInt:age forKey:@"age"];
}
@end

Once we implement the protocol, saving will look like this:

// Save method
// We initialise our object and set the values
Person* p1 = [[[Person alloc] init] autorelease];
p1.firstName = [firstNameTextField stringValue];
p1.lastName  = [lastNameTextField stringValue];
p1.age       = [ageTextField intValue];
 
// We initialise our NSMutableData
NSMutableData *sData = [[NSMutableData alloc] init];
/*And our NSKeyedArchiver initialised to encode stream and version 
information into a given mutable data object.*/
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] 
                      initForWritingWithMutableData:sData];
// Then we encode our object for a key of our choice
[archiver encodeObject:p1 forKey:@"person"];
[archiver finishEncoding];
 
// Finally we can write out the data      
[sData writeToURL:fileURL atomically:YES];

Restoring is the other way around:

// Restore method
NSMutableData *rData = [[NSMutableData alloc]
                         initWithContentsOfURL:locationOfTheFile];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]
                         initForReadingWithData:rData];
 
// Initialise the object and use the unarchiver to set the values
Person* p1 = [[[Person alloc] init] autorelease];
p1 =  [unarchiver decodeObjectForKey:@"person"];
 
// set the value on the textfields
[firstNameTextField setStringValue:p1.firstName];
[lastNameTextField setStringValue:p1.lastName];
[ageTextField setStringValue:
                 [NSString stringWithFormat:@"%i",p1.age]];

Here is the source code of the above example with NSSavePanel and NSOpenPanel.

Stacks and Queues

I usually find these two simple data structures (Stack and Queues) more than useful… So using a NSMutableArray we can code their behaviour quite easily.

So here you go:

The Queue

@interface NSMutableArray (CPQueue)
- (void)add:(id)object;
- (id)remove;
- (id)first;
- (id)last;
@end
 
@implementation NSMutableArray (CPQueue)
- (void)add:(id)object{
    if(object) [self addObject:object];
}
 
- (id)remove{
    id theResult = nil;
    if([self count]){
        theResult = [[[self objectAtIndex:0] retain] autorelease];
        [self removeObjectAtIndex:0];
    }
    return theResult;
}
 
- (id)first{
    return [self objectAtIndex:0];
}
 
- (id)last{
    return [self lastObject];
}
@end

The Stack

@interface NSMutableArray (CPStack)
- (void)push:(id)object;
- (id)pop;
- (id)top;
@end
 
@implementation NSMutableArray (CPStack)
- (void)push:(id)object{
    if(object) [self addObject:object];
}
 
- (id)pop
{
    id theResult = nil;
    if([self count])
    {
        theResult = [[[self lastObject] retain] autorelease];
        [self removeLastObject];
    }
    return theResult;
}
 
- (id)top
{
    return [self lastObject];
}
@end

Simple Rotation

This was my first rotation animation few year before with iDMG (my first Cocoa application) it is very simple but is my favourite. Of course this rotation is hardly used since there is no way to define the anchor point like core animation.



Here is the code:

[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setDuration:1.0f];
[[arrow animator] setFrameRotation:90]; 
[NSAnimationContext endGrouping];

Checking OS Version

Well again, part of DockSpaces requires different code for 10.5 Leopard and different for 10.6 Snow Leopard. The following code can distinguish the operating system and do your work accordingly.

SInt32 version = 0;
Gestalt( gestaltSystemVersion, &version );
BOOL snowleopard = ( version >= 0x1060 ); 
BOOL leopard = ( version >= 0x1050 ); 
 
if ( snowleopard ){   
    // some code
}
else if ( leopard ){   
    // some other code
}

Launching Preferences

Hi, long time no post :)
I been quite bust with university and work therefore not that much effort on the blog.
DockSpaces needed a direct call to open the Dock Preferences within System Preferences.




So here is something quite simple but in case you need it…

-(IBAction)launchPreferences:(id)sender
{
 NSArray *paths = NSSearchPathForDirectoriesInDomains
 (NSLibraryDirectory, NSSystemDomainMask, NO);
 [[NSWorkspace sharedWorkspace] openFile:[[paths objectAtIndex:0]
   stringByAppendingPathComponent:@"PreferencePanes/Dock.prefPane"]];
}

Bandwidth Limiter

Hi everyone…

This post it won’t be very helpful for most of you, but it is extremely useful for me. :)
Currently I live in accommodation flat in London and for some annoying reason every room has a weekly cap of 14Gb… Therefore, I usually reach the limit quite fast so I had to do something!!!

Solution: A Bandwidth limiter that limits my connection to 64kbit/s.

Grab the application from here and the source code here.

Click here to read more »

Textfield validation


The following example is the simplest way to validate a textfield. In this case we have a textfield and the only characters allowed are:

[0123456789QWERTYUIOPLKJHGFDSAZXCVBNMqwertyuioplkjhgfdsazxcvbnm ];

I think in any application with user input you will need some sort of validation :)

You can grab the code TextFormatter

Infix to Postfix in Cocoa

Hi, recently I have been working on this infix to postfix notation converter in C++ for my data structures module at the university. I also discovered that Objective-C does not have templates like C++ to create an abstract data type.

Anyway, the infix to postfix requires the use of a Stack and as you can see here there is a way to implement this behaviour using a NSMutableArray.

Grab the source code - InfixToPostfix – The code is based on this java implementation. Click here to read more »

Preferences window paradigm

In this post I will introduce you my preferences window approach :) For sure is not the only one you will come across, but is definitely one of the easiest ways. In this case the toolbar is created with Interface Builder so is compatible only with 10.5 or later. (less code)

So let’s start…

STEP #1 Preferences window controller

Click here to read more »