Hiatus
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.
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.
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.
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.
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.
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/
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.
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.
I learned about pointers briefly in a Java class in college and never worried about them in C#/.Net. Of course, it’s all coming back to haunt me in Objective-C.
When you declare an NS variable, it’s often indicative of an object in the Foundation Framework, so you declare with an asterix as a pointer, as such:
NSArray *myArray = [[NSArray alloc] initWithObjects:@”item1″, @”item2″, @”item3″, nil];
This also indicates that this object will need to be release at some point after you’re done needing a reference to it.
But what’s the deal with the missing “*” in an NSInteger declaration?
Well, it turns out that NSInteger objects aren’t objects at all, but integer or long datatypes which are handled by compiler and held on the stack. The compiler chooses the best size (32 or 64 bit) to allocate based on the platform for which we are compiling (always 32 bit for the iPhone… for now!).
Declaring NSIntegers using an asterix will throw the following error: Initialization makes pointer from integer without a cast
To fix this, just remove the * (pointer) from your variable declaration and let your ints be ints and longs be by-longs.
I recently finished my first book on iPhone Development, iPhone Programming The Big Nerd Ranch Guide (you can read my Amazon review here).
I’m currently going through Jeff LaMarche’s Beginning iPhone 3 Development Exploring the iPhone SDK and am already noticing some differences in the way Apple is adopting new ways of doing things (keep up, programmers… keep up).
For example, declaring outlets in previous versions of the sdk was simply done like this:
IBOutlet UIButton *saveButton;
Recently, Apple’s taken to moving its sample code to placing IBOutlet in the property declaration:
@property (nonatomic, retain) IBOutlet UIButton *saveButton;
You can choose to declare your outlets either way, but keep in mind that, if you declare a property that has a different name than its underlying instance variable (remember the @synthesize directive?), you will need to put the IBOutlet keyword with the property declaration to make things work correctly.
In light of Android’s huge 886% year-on-year growth and remarkable shipments of the OS to giants HTC, Samsung, Motorola, LG, and Sony Ericsson followed by Apple’s second-biggest showing with would-have-been-sweet-numbers-had-it-not-been-overshadowed-by-google 61.4 percent growth over the same period of time, Symbian’s 41.5 percent growth, and RIM at 41 percent, it doesn’t take a mathematician to know that there’s money to be made in mobile development.
Even with Microsoft’s poor display at a minus 10.2 percent, the company is poised to make a comeback with its Windows 7 Mobile platform promising to at least keep up with the other pugilists. Heck, they’re even willing to pay us to develop their next generation of mobile applications.
While creating mobile apps on your own can be fun, more and more companies are looking for skilled (and published) developers to join their efforts in getting a piece of the pie. There are also more programs popping up everywhere to get young students interested and producing.
So despite my other post on the comparison between iPhone and Windows 7 Mobile development, I’m not claiming any allegiance just yet. While I already possess mild skillz in .Net/Silverlight and working with the iOS4 SDK has been a challenging pleasure, I’m getting ready to get my feet wet with Android SDK and see what Droid really does for a developer.