UILabel with Stroke!

Time to invoke some… dark magic. For some reason, UILabel doesn’t support stroke. So, if you’re… by chance… working on a videogame, or a simple iOS app, and you actually need to render an UILabel with a stroke, in a given color, you have come to the right place.

Let’s begin with the header file:

@interface LAStrokeLabel : UILabel
{
    NSUInteger _strokeWidth;
    UIColor* _strokeColor;
}

@property (nonatomic, assign) NSUInteger strokeWidth;
@property (nonatomic, retain) UIColor* strokeColor;

@end

So far so good… right?. Nothing weird. Just a simple UILabel subclass, with two extra properties.

Now, let’s get to business. We’re gonna need to link ‘CoreGraphics’ framework. Otherwise this won’t work. The .m file should look like this:

static NSUInteger kDefaultStrokeWidth = 1;

@implementation LAStrokeLabel

@synthesize strokeWidth = _strokeWidth;
@synthesize strokeColor = _strokeColor;

-(void)dealloc
{
    [_strokeColor release];
    _strokeColor = nil;

    [super dealloc];
}

-(id)init
{
   if((self = [super init]))
   {
      _strokeWidth = kDefaultStrokeWidth;
      _strokeColor = [[UIColor blackColor] retain];
   }

   return self;
}

-(id)initWithFrame:(CGRect)frame
{
   if((self = [super initWithFrame:frame]))
   {
      _strokeWidth = kDefaultStrokeWidth;
      _strokeColor = [[UIColor blackColor] retain];
   }

   return self;
}

-(void)awakeFromNib
{
   _strokeWidth = kDefaultStrokeWidth;
   _strokeColor = [[UIColor blackColor] retain];

   [super awakeFromNib];
}

-(void)drawTextInRect:(CGRect)rect
{
   CGSize shadowOffset = self.shadowOffset;
   UIColor* textColor = self.textColor;
   BOOL highlighted = self.highlighted;

   CGContextRef c = UIGraphicsGetCurrentContext();

   // Draw the stroke
   if( _strokeWidth > 0 )
   {
      CGContextSetLineWidth(c, _strokeWidth);
      CGContextSetTextDrawingMode(c, kCGTextStroke);

      self.textColor = _strokeColor;
      self.shadowColor = _strokeColor;
      self.shadowOffset = CGSizeMake(0, 0);
      self.highlighted = NO;

      [super drawTextInRect:rect];
   }

   // Revert to the original UILabel Params
   self.highlighted = highlighted;
   self.textColor = textColor;

   // If we need to draw with stroke, we're gonna have to rely on the shadow
   if(_strokeWidth > 0)
   {
      self.shadowOffset = CGSizeMake(0, 1); // Yes. It's inverted.
   }

   // Now we can draw the actual text
   CGContextSetTextDrawingMode(c, kCGTextFill);
   [super drawTextInRect:rect];

   // Revert to the original Shadow Offset
   self.shadowOffset = shadowOffset;
}

@end

If you figured out… you just got an extra point. Yes. For some reason, CoreGraphics’s stroke wasn’t drawing anything ‘below the bottom line’. That’s the reason why i’ve implemented a workaround: the ‘bottom’ of the stroke is actually a shadow.

A bit hacky, but i promess, it will work great.

Display a modal UIViewController when a UITabBarItem is pressed

Suppose the following scenario. You need to display a modal UIViewController whenever the user presses a specific button in a UITabBar.

The trick is pretty simple. First, add an empty UIViewController, wich will serve as placeholder for the ‘modal tab’:

UIViewController* someViewController    = [[UIViewController alloc] init];
[someViewController setTitle:NSLocalizedString(@"Modal Tab", nil)];
[someViewController.tabBarItem setImage:[UIImage imageNamed:@"modal.png"]];

Then, setup the UITabBarController’s delegate:

[_tabBarController setDelegate:self];

At last… you need to implement the UITabBarControllerDelegate protocol. Specifically, something that looks like this:

- (BOOL)tabBarController:(UITabBarController*)tabBarController shouldSelectViewController:(UIViewController*)viewController

{
    BOOL isModalTab = ([[viewController title] isEqualToString:NSLocalizedString(@"Modal Tab", nil)]);

    if(isModalTab)
    {
        UIViewController* modalViewController = [[[ModalViewController alloc] init] autorelease];
        [self presentModalViewController:modalViewController animated:YES];
    }

    return !isModalTab;
}

That would do the trick..!

Guitar Pro for OSX

We, as guitar players, need to constantly practise. Every single day of our lifes. After a certain point… you don’t really need to practise. Your fingers get used to the strings… everything works smoothly.

Personally, i love Guitar Pro. If you’re lazy enough to learn songs by yourself, there are just  plenty of tab resources everywhere…

Maybe the best feature that GP has is the ‘speed trainer’. You can set up the initial Beats Per Minute, the number of loops, and the speed increase in each round. So all you need to do is to hook your guitar up to an amp, and hit the strings.

Besides that, the second major feature i love about this app is the ‘scale transposer’. You can easily transpose a song to any key you wish.

Go get it here!. Although it’s not free, there is a free trial in there, so you get to check it out before spending cash in it…!

The iPad is the new Macintosh

I’ve just seen a really interesting video, i’d like to share with you all. It’s what i’ve been thinking of since i began working on iOS. This technology is aimed at the masses. What do normal people need to do with a computer?…. probably, check emails, surf the web, and videochat.

Do you need a complex machine with a keyboard, mouse, and an antivirus?. Of course not!. If you need to do simple tasks such as those… you can just get an iPad. Virus free, keyboard free… always on. Isn’t that great?.

Note: This video, obviously, was recorded before iOS got multitasking capabilities. Nowadays… iOS indeed is more flexible than the original Mac.

iOS and JavaScript Bridge

What if you need to write a completely dynamic app, and you need to have the ability of updating the App’s contents remotely, without the need of pushing a new build to the AppStore?.

What if you need to write javascript code, which needs to interact with your iOS code?.
Yeah. I had that problem. Long short story, i’m testing a nice framework called clutch.

Clutch has a nice JavaScript and iOS SDK, which smoothens the interaction between those two technologies. When you ship the app, you bundle a version of the webApp in it.

If the app has no internet access, it will rely on that bundled web. And as soon as you launch it, it gets sync’ed with the backend. (You can actually push ‘new version’ to the Clutch backend).

So far… i’m loving it. Go, try it… and let me know what you think!.

If you just need to build a dumb iOS and JS bridge, i suggest you also check out this github project, and this one.