Jayr Parro

What Motivate Us

The source of human motivation and our best work comes from the drive towards autonomy, mastery and purpose.

iDevice Models

I’ve been using the helper method in the code below to determine the sytem name of the iPhone/iPod/iPad device models. I’ll try to update this list as Apple will release new devices in the future.

1
2
3

\#include <sys/types.h>
\#include <sys/sysctl.h>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

// -------------------------------------------------------------------------
// Private Method - Platform
// -------------------------------------------------------------------------
- (NSString *) platform
{
    size_t size;
    sysctlbyname("hw.machine", NULL, &size, NULL, 0);
    char *machine = malloc(size);
    sysctlbyname("hw.machine", machine, &size, NULL, 0);
    NSString *platform = [NSString stringWithUTF8String:machine];
    free(machine);
    return platform;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

// -------------------------------------------------------------------------
// Platform String - get the device model
// -------------------------------------------------------------------------
- (NSString *) platformString
{
    NSString *platform = [self platform];

    if ([platform isEqualToString:@"iPhone1,1"])    return @"iPhone 1G";
    if ([platform isEqualToString:@"iPhone1,2"])    return @"iPhone 3G";
    if ([platform isEqualToString:@"iPhone2,1"])    return @"iPhone 3GS";
    if ([platform isEqualToString:@"iPhone3,1"])    return @"iPhone 4";
    if ([platform isEqualToString:@"iPhone3,3"])    return @"Verizon iPhone 4";
    if ([platform isEqualToString:@"iPhone4,1"])    return @"iPhone 4S";
    if ([platform isEqualToString:@"iPhone5,1"])    return @"iPhone 5 (GSM)";
    if ([platform isEqualToString:@"iPhone5,2"])    return @"iPhone 5 (GSM+CDMA)";
    if ([platform isEqualToString:@"iPod1,1"])      return @"iPod Touch 1G";
    if ([platform isEqualToString:@"iPod2,1"])      return @"iPod Touch 2G";
    if ([platform isEqualToString:@"iPod3,1"])      return @"iPod Touch 3G";
    if ([platform isEqualToString:@"iPod4,1"])      return @"iPod Touch 4G";
    if ([platform isEqualToString:@"iPod5,1"])      return @"iPod Touch 5G";
    if ([platform isEqualToString:@"iPad1,1"])      return @"iPad";
    if ([platform isEqualToString:@"iPad2,1"])      return @"iPad 2 (WiFi)";
    if ([platform isEqualToString:@"iPad2,2"])      return @"iPad 2 (GSM)";
    if ([platform isEqualToString:@"iPad2,3"])      return @"iPad 2 (CDMA)";
    if ([platform isEqualToString:@"iPad2,4"])      return @"iPad 2 (WiFi)";
    if ([platform isEqualToString:@"iPad2,5"])      return @"iPad Mini (WiFi)";
    if ([platform isEqualToString:@"iPad2,6"])      return @"iPad Mini (GSM)";
    if ([platform isEqualToString:@"iPad2,7"])      return @"iPad Mini (GSM+CDMA)";
    if ([platform isEqualToString:@"iPad3,1"])      return @"iPad 3 (WiFi)";
    if ([platform isEqualToString:@"iPad3,2"])      return @"iPad 3 (GSM+CDMA)";
    if ([platform isEqualToString:@"iPad3,3"])      return @"iPad 3 (GSM)";
    if ([platform isEqualToString:@"iPad3,4"])      return @"iPad 4 (WiFi)";
    if ([platform isEqualToString:@"iPad3,5"])      return @"iPad 4 (GSM)";
    if ([platform isEqualToString:@"iPad3,6"])      return @"iPad 4 (GSM+CDMA)";
    if ([platform isEqualToString:@"i386"])         return @"Simulator";
    if ([platform isEqualToString:@"x86_64"])       return @"Simulator";

    return platform;
}

References

http://en.wikipedia.org/wiki/List_of_iOS_devices
http://support.apple.com/kb/HT3939

Xcode Project Layout

In keeping my Xcode project organize, I’m following this structure:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/<ProjectName>
    /Shared
        /Application      # App delegate and related files
        /Controllers      # Base view controllers
        /Models           # Models, Core Data schema etc
        /Views            # Shared views
        /Library          # Anything that falls outside of the MVC pattern
        /Support          # Categories and helpers
    /iPhone
        ...               # Same structure as 'Shared' but with interface specific classes
    /iPad
        ...
    /Supporting files    # Info.plist, Prefix headers, main.m
    /Resources           # Images, videos, .strings files, 
/Vendors                 # 3rd party dependencies not managed by CocoaPods
  

If you’ve got some easier & better structure to organize the Xcode project files, let me know in the comments below. Thanks!


References:

http://stuartkhall.com/posts/ios-development-tips-i-would-want-if-i-was-starting-out-today

Leap Motion

Leap Motion, a game-changer in a 3D gesture-based controller space. It’s a tiny device but very sensitive in which it can able to control PC/Mac/Linux applications by using your natural hand or fingers.

I’ve got the Leap Motion Developers Kit and its SDK by participating on their Developer Program, FREE of charge.

Thanks to the Leap Motion Team for sending it!

Also, included in the box is a Letter from the Founders enticing 3rd-party developers to build apps for Leap Motion. Yeah, it’s very encouraging!

Let’s see what I can do as I’ll try to experiment on it.
For now, check the images below.

Installing Homebrew, RVM, & Ruby 1.9.3

I’ve been doing Ruby on Rails recently and setting its configuration on Mac OSX Mountain Lion with Xcode 4.6 installed is bit of a pain.

If you want to update to the latest stable version of Ruby, which is v1.9.3 as of now, you’d better install first - Homebrew and Ruby Version Manager (RVM).

This tutorial from Moncef Belyamani, I’ve found it very useful.

A note to self.

iOS Programming Workshop

Spending my whole-day weekend volunteering as a Coach/Trainer for the iOS Programming Workshop organized by Elisha Tan of Learnemy and local iOSDev group, iOSDevScout, that’s being held in Plug-In@Blk71. The main speaker is Subhransu Behera.

I’m surprise with the number of people of different ages & races, that show up in the workshop eager to learn iOS Development. Tech scene in Singapore is so vibrant! :-)

Here’s the scene of the iOS Programming workshop:

pic
pic

Bands - Core Animation Sample

A simple animation project using Core Animation. It can be use in your App’s Splash Screen transition animation.

The Code

To use Core Animation APIs in your project, you need to add the QuartzCore framework. So, in your Xcode project, go to Target-> Build Phases-> Link Binary With Libraries-> Add QuartzCore.framework

Then, in ViewController.h:

1
\#import <QuartzCore/QuartzCore.h>

In ViewController.m file:

1
2
3
@interface ViewController () {
    CALayer *bgLayer;
}

- (void)viewDidLoad method:

1
2
3
4
5
6
7
8
9
bgLayer = [[CALayer alloc] init];
[bgLayer setBounds:CGRectMake(0.0, 0.0, self.view.bounds.size.width, self.view.bounds.size.height)]; // set size
[bgLayer setPosition:CGPointMake(self.view.frame.size.width/2, self.view.frame.size.height/2)]; // set position
[bgLayer setBackgroundColor:[UIColor blueColor].CGColor];

[bgLayer setContents:(id)[UIImage imageNamed:@"image1.jpg"].CGImage];
// [bgLayer setContentsGravity:kCAGravityResizeAspect];
[[self.view layer] addSublayer:bgLayer];
[self performSelector:@selector(setupBandsAndAnimation) withObject:nil afterDelay:1.0];

In the above code, we’ve setup a CALayer, bgLayer, that will hold our contents which is an UIImage. Then, we set its properties and add this layer to the view. After 1 second, we call the method selector setupBandsAndAnimation to do the splitting of the bands and its animation.

1
2
3
4
5
6
7
8
9
10
11
12
- (CABasicAnimation *)slideUpAnimation
{
   //setup animation  
   CABasicAnimation *slideUpAnim = [CABasicAnimation animationWithKeyPath:@"position.y"];
   [slideUpAnim setToValue:[NSNumber numberWithFloat:-bgLayer.frame.size.height]];
   [slideUpAnim setDuration:1.0];

   CAMediaTimingFunction *tf = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
   [slideUpAnim setTimingFunction:tf];

   return slideUpAnim;
}
1
2
3
4
5
6
7
8
9
10
11
12
- (CABasicAnimation *)slideDownAnimation
{
   //setup animation
   CABasicAnimation *slideDownAnim = [CABasicAnimation animationWithKeyPath:@"position.y"];
   [slideDownAnim setToValue:[NSNumber numberWithFloat:bgLayer.frame.size.height*2]];
   [slideDownAnim setDuration:1.0];

   CAMediaTimingFunction *tf = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
   [slideDownAnim setTimingFunction:tf];

   return slideDownAnim;
}

In the above code, we’ve setup CABasicAnimation for sliding up & down. We just need to modify the position.y which is the destination value of the bgLayer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
- (void)setupBandsAndAnimation
{
  NSUInteger nNumBands = 20;
  NSMutableArray *bands = [[NSMutableArray alloc] initWithCapacity:nNumBands];
  CABasicAnimation *slideUpAnim = [self slideUpAnimation];
  CABasicAnimation *slideDownAnim = [self slideDownAnimation];

  [bgLayer removeFromSuperlayer];
  [CATransaction begin];
  [CATransaction setCompletionBlock:^(void) {
   [bands enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
              [obj setDelegate:nil];
              [obj removeFromSuperlayer];
          }];
    }];

  CGSize layerSize = bgLayer.bounds.size;
  CGFloat bandWidth = layerSize.width / (CGFloat)nNumBands;

  for (int n = 0; n < nNumBands; n++) {
   CALayer *band = [[CALayer alloc] init];
   band.masksToBounds = YES;

   CGFloat xOffset = 1.f / (CGFloat)nNumBands;
   band.bounds = CGRectMake(0.f, 0.f, bandWidth, layerSize.height);
   band.contents = bgLayer.contents;
   band.contentsGravity = kCAGravityCenter;
   band.contentsRect = CGRectMake(xOffset * n , 0.f, xOffset, 1.f);

   CGPoint bandOrigin = bgLayer.frame.origin;
   bandOrigin.x = bandOrigin.x + (bandWidth * n);
   [band setValue:[NSValue valueWithCGPoint:bandOrigin] forKeyPath:@"frame.origin"];

   [self.view.layer addSublayer:band];

   [band addAnimation:(n % 2) ? slideUpAnim : slideDownAnim forKey:nil];
   [bands addObject:band];
  }

  [CATransaction commit];
}

In the above code, we specify how many bands that it need to split up (nNumBands). Then, we’ve called the 2 CABasicAnimation we setup earlier. We iterate on the number of small bands that’s been split up, created another CaLayer object and setting up its properties and apply the animation. After the animation is finished, we remove the layer, [obj removeFromSuperLayer].

Sample Output


You can get the code here.

Happy Coding! :)


PS: Further reading:
Core Animation Programming Guide

Hello Octopress!

Happy New Year!

A New Year, a new blog. I’ve decided to move my personal blog from Posterous to Octopress. I like the simplicity of Octopress and it’s really easy to setup and deploy. Aside from that, using Markdown make it very handy writing a blog.

Over time, I’ll try to maintain this site and evolve with things that I have already done, things that I have to share and accumulate more experiences in the future.

Happy Coding! :)


[UPDATE] 02/17/2013

Posterous is turning off on April 30, 2013. No wonder.
For those who haven’t moved from Posterous yet, it’s time to back-up your data.
See their blog here.