Jan 4 2012

2012 Resolutions

Rod Liberal

New Year's ResolutionThis might be the first year I actually write some practical resolutions. None of that “lose weight, get in shape” babble that echos fighting the “war on terror” and not accomplishing anything. I know I’ll get to the gym as often as I have been for the past several years; I’ll get on a kick for a while, then watch it dwindle, then pick it up again, and the merry goes round.
But this year I do have some pretty concrete things I’d really like to put up front and center of my efforts (aside from my must-do’s). I’ll try to list a few here, but I’m sure new things will come up:

  • Teach my children my mother tongue – I am really going to get a teaching system and a schedule down this year in order to teach my kids Portuguese. I’m also going to start talking to my 1yo in Portuguese only… eh… soon.
  • Write, write, write – I had a crazy idea for a book and I began writing some of it down last year. I like what I have so far and I plan on keeping it going this year. I mean, Ghandi did it and that dude barely had any food. Maybe there’ll be a finished book by December?!Ghandi writing
  • Update ScreenTime to iOS 5 – I’ve started adding some requested features to the app (like the ability to add time without using the timer), which is almost done. I’m also working on adding iCloud support for device syncing and doing a revamp on the UI. I really dislike the UI now. I don’t mind the look, it’s more of the feel and the navigation. We’ll see what can be done.
  • Get my blue belt in Brazilian Jiu Jitsu – wow! I can’t believe it’s almost been a year since I started doing Jits. Despite my recent break, I’d love to continue training and getting my first belt upgrade this year. Really, the only reason is so I can kick my brother-in-law’s can when I see him in the Spring.
  • Plant a tree – Jose Marti said (I’m pretty sure it was him) that is part of what every man should do before he dies; have a child, plant a tree, write a book. Given the recent events in my front yard involving a wind storm and my 25 foot pine tree almost landing on my house, I think it might just be the right time to fit that one in.
  • Dedicate a little more time to my old canine friend, Takoda. He’s getting on in life (he’ll be 11 in March!!!) and has definitely been kicked to the curb since all the kids started showing up. I can use the daily walks, too, let’s be honest.
  • Rock more – last year I undoubtedly ruled but I didn’t quite rock. My 5yo says I rock all the time, but who really believes what a 5yo says, anyway?

Ok, I think that’s it for now. If I start adding too much to this list, none of it will get done.

 


Oct 21 2011

Hiatus

Rod Liberal

I’ve been working on upgrading my apps to iOS5 and doing some Ruby programming as of lately, but I’ll be updating the site again soon.


Jan 19 2011

Screen Time has been released

Rod Liberal

Well, the app (ScreenTime) is in the app store and it’s doing fairly well. I had set some pretty low expectations, so I’ve been surprised to see downloads every day of the free app and a few sales already. I’ve been spending most of my time lately networking and learning the marketing game, trying a few things, and unfortunately, spending some more money.

I see the spending as paying for my own education. I hope I can make money on the app, but if I don’t, then many lessons learned. I’m doing a lot of the let work myself, though, building relationships with bloggers for my target audience, using developer groups and forums as platforms for learning what works or doesn’t for other people, and all the while trying to come up with new ideas for new apps.

Twitter has been my main source of referrals so far. The original press release did create a lot of hits to my web site, but that didn’t seem to influence the downloads much. It seems most downloads come from my followers on twitter, as far as I can tell.

I’ve also received some great feedback already from people using the app and have just released an update with some of their ideas. It’s been really fun, on top of everything.

I just ordered Learning iOS Game Programming by Michael Daley and have a project lined up with a graphic designer friend. It seems like a great idea for a kids’ game and a great way to get my feet wet into this side of iOS development.

Well, now that I have some more time, I’ll update the site a little more often with news from the app world, so stay tuned.


Oct 24 2010

The work so far

Rod Liberal

I’m in the final stages of development of my first iOS app and the work so far has been very challenging but fun.
It’s really a whole different deal working on something for yourself in comparison to working on a project for a company or a client.

The good so far:

It’s been a lot of fun learning a whole new language (I’ve been doing VB/C#) on a different platform. Aside from the graphics, I’m doing all the work myself, including the UI design.  My app is fairly simple since I’m not using many of the api’s in iOS, but I feel pretty comfortable with objective-c now and feel I can at least ask intelligent questions on a forum.

Working on your own stuff definitely gives you a lot of flexibility, which can be good if you’re disciplined enough to stick to a schedule and not let things slide.  I have to admit that initially I was tempted to let my other priorities get in the way, but I pushed through and got a lot of work done in a relatively short amount of time (approximately 3 months since I started).  Having the product almost done now has been very rewarding.

Having entered a whole new community of developers, I feel like a new developer again and my desire to learn received a new boost.  For the past few years I’ve felt like I “had” to keep  up with all the changes Microsoft has made to its development suite, but now I feel like I “want” to keep learning and improving my skills as a developer.

The bad so far:

First and foremost, the hours have been killer.  I can only get to work on my stuff after 9pm or 10pm on most nights, since I try to sacrifice as little time as possible away from the family.  That means going to bed between 2am and 4am some nights and waking up at 7am.  Staying healthy has taken a toll as well, lately, so I’m sure I’ll have to cut back soon (uh, right after I’m done with my first app, right?)

Working with Apple products has been specially challenging since it’s a relatively smaller community of people and resources.  I’m used to tons of materials and books and I feel it lacking somewhat for iOS (but not entirely).  I have been able to make good use of sites such as StackOverflow and iPhoneDevSDK, IRC, and many books (4 good ones so far), so there’s definitely enough to keep me going.

————

I really hope to have all development completed before the end of the month and have things ready for testing on the first week of November.  It’s a little overwhelming to think how much work I still have to accomplish; finish coding, create my test group, work on the app’s website, twitter, and Facebook page, create screen cast and screen shots, and market, market, market the heck out of this thing.

I have no dreams of making it big, obviously, with this app, but I want to feel that I’ve done everything right and build a good base for future work, be it for myself or for others.


Oct 14 2010

UIPickerView with custom view

Rod Liberal

I’ve been finding that the UIPickerView is just not the friendliest of controls with which to work.
I needed a picker with two pieces of text on it from some core data objects and figured that would be something fairly simple to do. Not so.

The UIPickerView has two methods to load data into it:

  • pickerView:titleForRow:forComponent
  • pickerView:viewForRow:forComponent:reusingView

The first one is pretty simple; you return a string and that string will be used to display data for that row.

The second one allows you to return any views that inherent from UIView, so basically any control or custom views.

I decided I was going to need two UILabels inside a UIView in order to accomplish what I wanted.
There are several problems which arise from going this route, however.

First and the least of the problems, you will have to change the background color of each label to NSColorClear to display through your grid row.
Once your labels are added and you touch them to select one, a highlighted frame will show around them making for a very unpleasant UI experience.
Lastly, the labels will overtake the pickers touch response, so you’ll have to fix that, which is a nice segway for some code.

  1. Let’s start by creating subclasses of UILabel and UIView.
    From the File menu, select New File…/Objective-C Class (Under Cocoa Touch Class; select subclass of UIView) and check “Also create …h”
    Name your new UIView subclass something like CustomPickerView.
  2. Repeat the process and create another view called CustomPickerLabel
    Once this class is created, change its parent class from UIView to UILabel
    In the implementation code for both of your new classes, add the following exact same code:

  3. - (void)didMoveToSuperview
    {
    if ([[self superview] respondsToSelector:@selector(setShowSelection:)])
    {
    [[self superview] performSelector:@selector(setShowSelection:) withObject:NO];
    }
    }

  4. Create your controller where your UIPickerView will reside, assign UIPickerView delegates and datasources, and create the delegate and datasource methods required.
    (Remember though, instead of using pickerView:titleForRow, use pickerView:viewForRow instead)
  5. In your controller implementation, in the pickerView:viewForRow method, let’s create our custom view and labels:

    // create custom view to take the width of your pickerView
    CustomPickerView *customView = [[CustomPickerView alloc] initWithFrame:CGRectMake(0.0, 0.0, 290, 32)];

    // first label will be displayed on the left of view, taking 3/4 of the row
    CustomPickerLabel *pickerLabelLeft = [[CustomPickerLabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 190, 32)];

    [pickerLabelLeft setTextAlignment:UITextAlignmentLeft];
    [pickerLabelLeft setFont:[UIFont boldSystemFontOfSize:15]];
    pickerLabelLeft.backgroundColor = [UIColor clearColor]; // don't forget to do this to clear the label's color
    [pickerLabelLeft setText:@"Refrigerator"];

    // second label will be displayed on the right taking remaining width
    CustomPickerLabel *pickerLabelRight =[[CustomPickerLabel alloc]
    initWithFrame:CGRectMake(pickerLabelLeft.frame.size.width, 0.0, 100, 32)];

    [pickerLabelRight setTextAlignment:UITextAlignmentRight];
    [pickerLabelRight setFont:[UIFont boldSystemFontOfSize:15]];
    pickerLabelRight.backgroundColor = [UIColor clearColor];
    [pickerLabelRight setText:@"$4.99"];

    // THIS IS IMPORTANT
    // you MUST set the view's userInteractionEnabled property to NO to let the picker regain touch events
    customView.userInteractionEnabled = NO;

    //finally, add both labels to custom view and return view
    [customView addSubview:pickerLabelLeft];
    [customView addSubview:pickerLabelRight];

    return customView;

Don’t forget to set your numberOfComponentsInPickerView and numberOfRowsInComponent methods and you’re all set.
This will give you a customized and interactive UIPickerView.


Oct 10 2010

Defaulting Core Data data

Rod Liberal

If your app relies on default data that needs to be shipped with the app release, there are several ways of accomplishing such task.
If your data is contained in plists, then populating those lists at first launch is a viable and common solution.

But what about getting the same result when using core data?

My app relies on a lot of initial default data which not only needs to be available to the user at first launch, but is also mutable data which the user can update.

First off, I wanted to use my app itself to populate the default data. The reason for this is to use all the data validation and formatting that is already available within the app to load the data. Also, I’ve spent hours upon hours in the simulator updating and using this data, so no need to reinvent the wheel with a different tool to load it.
Core Data saves all of your app data into a sqlite database file which, in turn, is a flat file easily transportable. Here’s how to do it:

First, run your app in the simulator and enter all the data you need into your app through your UI.
Again, core data will create a sqlite flat file that you can get to, so from Xcode, under your Source group, choose Add/Existing Files… and navigate to your app’s documents directory and select the sqlite file that contains your default data. Make sure the “Copy items into destination group’s folder” check mark is checked and click Add.

(The document directory for your app (for iOS 4.1) will be in <user>/Library/Application Support/iPhone Simulator/4.1/Applications//Documents where <user> will your user folder (Rod in my case) and <applicationFolder> is a GUID which may look like 3C17B9C8-76CE-4089-B77E-221968BB3CA5)

Now, there’s a little bit of code you need to add to make this all work, so let’s get into your app’s Application Delegate implementation file and look for the persistenceStoreCoordinator method.

This method is where your database file gets created in the app’s documents if it doesn’t already exist, upon application launch. Right before your persistence store gets initialized…

persistentStoreCoordinator_ = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

You want to add the following bit of code:


//First, check to see if sqlite db exists in documents already
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; // get documents directory

NSString* toFile = [documentsPath stringByAppendingPathComponent:@"My_Sweet_App.sqlite"];

BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:toFile];

//if not, copy from bundle to docs (if file in bundle exists)
if (!fileExists) {
NSString *fromFile = [[NSBundle mainBundle] pathForResource:@"My_Sweet_App" ofType:@"sqlite"]; // gets path for file in bundle i.e. the default sql file you added to your Source group

fileExists = [[NSFileManager defaultManager] fileExistsAtPath:fromFile];

if (fileExists) {
[[NSFileManager defaultManager] copyItemAtPath:fromFile toPath:toFile error:nil]; // copy from bundle to documents
}
}

What you’re basically doing here is checking to see if this is the first time the user is using your app. If it is, you copy your default db (the one you added to your Source group) to the documents folder so it’s available to be compiled into the momd.

This raises questions regarding updates to your db in later releases, but it’s nothing that versioning and migrations can’t handle.


Sep 2 2010

Using UITabBar and Navigation Controllers together

Rod Liberal

After doing some digging around, adding and removing controllers from my Nib files, creating and deleting Outlets, and creating subViews from subViews from subViews, I finally settled for an easy, Nib-less approach to getting my UITabBar to work nicely with Navigation controllers, and here’s how I did it:

First off, all the work was done in the App Delegate implementation file, so no need for outlets (at least not for viewing my views).
I started by declaring a TabBar controller. This will be your base controller for all your Navigation controllers


UITabBarController *myBarController = [[UITabBarController alloc] init];

Then, I created all the view controllers for each UITabBar item. In this example, I’ll create three TabBar items:


HomeViewController *homeController = [[HomeViewController alloc] init];
homeController.title = @"Home"; // you can also here set the controller's tabBarItem.Image to an icon of your choice
homeController.tabBarItem.Image = [UIImage imageNamed:@"homeIcon.png"];

SecondViewController *secondController = [[SecondViewController alloc] init];
secondController.title = @"Second";
secondController.tabBarItem.Image = [UIImage imageNamed:@"secondIcon.png"];

ThirdViewController *thirdController = [[ThirdViewController alloc] init];
thirdController.title = @"Third";
thidController.tabBarItem.Image = [UIImage imageNamed:@"thirdIcon.png"];

Next, you can create a Navigation controller for each of the views that will display a Navigation bar. In this case, let’s set the Home and Second controllers to show a Navigation bar:


UINavigationController *homeNavController = [[[UINavigationController alloc] initWithRootViewController:homeController] autorelease]; // home navigation
UINavigationController *secondNavController = [[[UINavigationController alloc] initWithRootViewController:secondController] autorelease];

Now you can tie it all together by adding your Navigation controllers to your UITabBarController’s viewControllers and add your TabBar view to the window:


barController.viewControllers = [NSArray arrayWithObjects:homeNavController, secondNavController, thirdController, nil];
//notice above the last TabBar item is a view controller and not a Navigation controller
[window addSubView:barController.view];
[window makeKeyAndVisible];

// don't forget to clean up your mess
[homeController release];
[secondController release];
[thirdController release];
[homeNavController release];
[secondNavController release];
// however, DO NOT release your TabBar Controller since window is it's owner and it'll cause your app to crash

That’s it! By keeping things out of Nib files, you’ve kept your code clean and visible and all parts working well together.


Aug 28 2010

Simple NSTimer Countdown/Countup

Rod Liberal

I wanted to post this very simple code sample of how to get NSTimer to show the user a countdown or countup timer. I’ve been looking through the apple dev docs and there’s nothing really too straight forward and it’s taken a lot of digging around to put this little bit of code together.


- (IBAction)use:(id)sender {
// start timer
myTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerFired:) userInfo:nil repeats:YES];

// set userInfo to nil as we don't need user interaction
}

- (void)timerFired:(NSTimer *)timer{
// update label

int usedToday = [self.usedTodayLabel.titleLabel.text intValue]; //grab the starting value from your label
int newUsed = usedToday++; //or -- to decrement the timer
self.usedTodayLabel.titleLabel.text = [NSString stringWithFormat:@"%d", newUsed]; //set new incremented value to label
}

When you need to stop your timer, you just need to call [myTicker Invalidate].

And that’s it… simple!


Aug 18 2010

Microsoft’s WebMatrix too little too late?

Rod Liberal

Microsoft introduced a new development environment yesterday aimed towards new or lazy web developers called WebMatrix (beta).

The serious .Net developer may overlook this dummed-down version of Studio, but I wouldn’t be so quick to judge. Microsoft is wrapping this new package with some nice tools that will help even the more serious developers write some nifty code in a short amount of time.

Some of the features include a new version SQL Compact 4.0 which allows for multiple connections and a localized database file (you copy the assembly into your bin folder or the GAC and voila’) along with tools to edit the files and tables.

Also included is the “new” Razor view engine for its MVC style architecture paradigm (missing in VS as of right now). I’m not too familiar with Razor yet, but it seems like a pretty straight-forward script-only view engine which is all making more and more sense to me since I’ve been programming iPhone apps (makes you wonder who’s keeping up with whom).

Anyway, I stay away from ASP.Net for a couple of months and it seems like it’s all going the way of the Dodo. I need to get on MVC and keep an eye on WebMatrix’s tools making their way to Visual Studio.


Aug 18 2010

Windows Phone 7 Training Begins

Rod Liberal

Yesterday, Brandon Watson announced the launch of the first batch of MVP-led training sessions for Windows Phone 7 development.

The course work includes 12 sessions, each about :50 minutes long, by MVP’s Rob Miles and Andy Wigley and cover a pretty expansive array of topics, from basic Silverlight development to XNA Games and marketing your apps.

All course work is based on the Beta release of Windows Phone Developer Tools.

I guess it’s time to get serious about Microsoft again.