Tuesday, January 26, 2010

Disabling keyboard on UITextField selection

There are often cases where you want the look of UITextField but don't want to use the keyboard. There are a few hacky ways such as hidden buttons overlaying text fields, but I think this is the most intelligent way to disable the show of the UIKeyboard, and replacing it with something of your choice:


- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { 
// Make a new view, or do what you want here
UIDatePicker *pv = [[UIDatePicker allocinitWithFrame:CGRectMake(0,185,0,0)];
[self.view addSubview:pv];

return NO;
}

You'll need to be implementing UITextFieldDelegate, and you can catch this event prior to the framework showing the UIKeyboard. In the above example I am showing a UIDatePicker instead. Returning NO is what is making the keyboard not show, since we aren't actually letting the editing begin.

Making the keyboard disappear

So... I said this blog was going to be about basics, right? Well, here's a really basic concept that may elude some folks. If you have a UITextField on your view, and are implemented UITextFieldDelegate in your delegate class, perhaps you have noticed that after you enter some text using the keyboard for your field, the keyboard won't disappear when you hit return? Well, here's all you have to do:


- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return YES;
}

Since you are implementing the UITextFieldDelegate class, this method will be called on Return, your text field will give up focus, and the UIKeyboard will disappear. If you want to be more particular and a little safer in your method you can do the following:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
  if(textField == [self yourTextField]) {
[textField resignFirstResponder];
  }
return YES;
}

Monday, January 25, 2010

REST calls using Objective-C

Over the weekend I was working on a project where I needed to create some REST calls to an XML service. I already created a generic SOAP Request class in the past, so I figured this would be a little simpler. Before going and re-inventing the wheel I took a quick look around the web and found this excellent Base REST Client class out on the web, so I wanted to share the link with everyone.

I still pains me that I can't use XPATH or XSL in the iPhone SDK. Do you hear me Apple?

Wednesday, January 20, 2010

"Abstract Classes" in Objective-C

One of my favorite interview questions for a programming position is "What is the difference between a class, an abstract class, and an interface?". You'd be surprised how many people can't answer that. Anyways, that's my intro to today's lesson, where we attempt to create an abstract class in Objective-C.

Hopefully by now you know that an interface is a type whose methods are devoid of implementation, and it cannot serve as an instantiated class on it's own; it's not actually a class. An abstract class can have methods devoid of implementation, but has at least one method that contains implementation. It also contains member variables.

Enough of the introduction, and let's get down to business. First off, you cannot create an abstract class in Objective-C; there is no abstract modifier. I recently had the need for an abstract class and an interface in a project I was working on, and I emulated an abstract class to the best of my ability. Here's what I came up with:



//  MyObject.h

#import

@protocol IMyObject
-(void) myMethod;
@end

@interface MyObject : NSObject {
NSUInteger myID;
}

@property (nonatomic) NSUInteger myID;

-(void) myMethod2;


@end



//  MyObject
#import "MyObject.h"

@implementation MyObject

@synthesize myID;

- (id)init
{
[self doesNotRecognizeSelector:_cmd];
[self release];
return nil;
}

-(void) myMethod {
[self doesNotRecognizeSelector:_cmd];
}

-(void) myMethod2 {
  //do stuff
}

@end


So, the above class header file contains a nested @protocol which declares a required method signature. You can declare optional methods inside the @protocol with a @optional declaration. Essentially, the protocol is defining my interface. Next I declare my actual class and implement my IMyObject interface, which "forces" me to implement myMethod. I quote the "forces" in that last because the compiler really just gives me a warning, not a full error.

I've also declared a member variable myID and a property for it in my "abstract" class implementation, along with myMethod2, which can contain actual implementation to inherit to the subclasses of this "abstract" class. It is key to note the [self doesNotRecognizeSelector:_cmd]; lines, where I am basically using that to declare the method as abstract. It will throw an error if you try to call the method on the base call. If you put that within your init method, the class will not be able to be instantiated on its own.

Monday, January 18, 2010

UITableViewController subclassing in XCode has incorrect stub

If you've ever tried to create a UITableViewController subclass using XCode with SDK 3.x (3.1.2 at the time of this writing), it is important to note that the commented out code in the didSelectRowAtIndexPath method is incorrect.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    //Navigation logic may go here. Create and push another view controller.
AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:@"AnotherView" bundle:nil];
[self.navigationController pushViewController:anotherViewController];
[anotherViewController release];
}

If you try to modify the above code to use one of your own custom view controllers, you will see a compilation warning stating:

  'UINavigationController' may not respond to '-pushViewController:'

If you actually try to run your application and select an item which tries to push an additional view controller, an exception will be thrown that states:

  [NSObject doesNotRecognizeSelector:]

The exception is definitely very misleading. The reason for both of the above problems is a second required parameter for this call, as follows:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    //Navigation logic may go here. Create and push another view controller.
AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:@"AnotherView" bundle:nil];
[self.navigationController pushViewController:anotherViewController animated:YES];
[anotherViewController release];
}

iPhone Application Development - First Steps

Your first step in the wonderful world of iPhone SDK Development is to download the SDK, err... I mean, register for the iPhone Development Program... oh wait... you actually need a Mac... that's right :) Ok, let's try to make this more clear:
  1. Obtain a modern day Intel based Mac running Mac OS X Leopard. My suggestion is a Macbook Pro due to it's portability. Always check out the Refurb section of the Apple store!
  2. Register for the iPhone Developer Program
  3. Download the latest version of the iPhone SDK, including XCode
  4. Install the SDK
  5. Follow the iPhone Development Quick Start guide
I won't waste the time to completely go through a basic Hello World application, so instead I'll link you to an excellent beginner's resource - the iPhone Development Quick Start from Apple themselves. Depending upon your experience level with C-based programming languages, another recommendation of mine is to read through Apple's primer on Learning Objective-C, which I will not lie about... it can be a doozy at times.

Welcome to iPhone SDK Basics

During my own learning of various iPhone Development techniques over the past several months, I grew tired of the constant search for tips and tutorials related to the basics of iPhone application development. I'm talking about general layouts and navigation flow - things like setting up an application that has a tab bar and some tableviews, etc. Given my background in software engineering, some things that looked to be rather simple were much more complex than I expected.

I'll also be posting links to valuable resources that I found throughout the web.