iPhone App Started...
Started the iPhone app and have the registration and login screens stubbed out. Today I'm feeling special, just like this guy:
- Sketched out the screens I wanted to build.
- Created a new iPhone project in Xcode.
- Basic navigation controller app with Core Data.
- Added a new Core Data Entity.
- Created the "first time" screen, seen upon install.
- Created the registration and sign in screens.
- Added some basic validation on the email fields.
- Added a class to check on a users login status.
So first thing I did was pull out a pencil and some paper. I wanted to visualize the screens:
Pretty basic, but this allowed me to know exactly what I needed to attack. Basically, upon application install, I want a welcome screen displayed to the user explaining, briefly, what they have in their hands. Also, I'm forcing registration. This is a free app and if you want to use it you have to register. I know the Apple guidlines say this is a no-no, but I've studied many other free app's that do just this and are in the top 25 for their category, so I'm going to risk it.
One of the interesting challenges will be to understand if a user is logged into the remote server or not. All of the data that they enter into the application will not only be stored within Core Data, but also remotly. So I built an Authenticated class that checks and returns a BOOL whether or not they are logged in. Right now it's just stubbed out returning a hard-coded YES or NO, but in the future this will be the class that does that query to find out.
@implementation Authenticated
- (id)init {
@synthesize loggedin;
// temp override
self.loggedin = NO;
// check the database to see if we are logged in
return self;
}- (BOOL)locally {
return self.loggedin;
}- (BOOL)remotly {
return self.loggedin;
}@end
Pretty basic, but it get's me where I need to be :)
So if the Authenticated class returns false, we get a welcome screen with a login and register button in the toolbar. If they are already logged in, we will dump them to the main screen displaying all of their data.
Next up was the toolbar. I created in code rather than through the Interface Builder as I wanted a bit more control over it:
#pragma mark -
- (void)configureToolbarItems {
#pragma mark Tool Bar
UIBarButtonItem *loginButtonItem = [[UIBarButtonItem alloc]
initWithTitle:@"Sign in"
style:UIBarButtonItemStyleBordered
target:self action:@selector(loginClicked:)];
UIBarButtonItem *registerButtonItem = [[UIBarButtonItem alloc]
initWithTitle:@"Register"
style:UIBarButtonItemStyleBordered
target:self action:@selector(registerClicked:)];
UIBarButtonItem *flexSpaceButtonItem = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:nil action:nil];
self.toolbarItems = [NSArray arrayWithObjects:
flexSpaceButtonItem,
loginButtonItem,
registerButtonItem,
flexSpaceButtonItem,
nil];
[self.navigationController setToolbarHidden:NO];
}
Which is triggered by:
// do we have a valid authentication?
Authenticated *authed = [[Authenticated alloc] init];
if (![authed locally]){
[self configureToolbarItems];
}
[authed release];
From the RootControllers viewWillAppear method. Done and done...
Next up were the registration and log in screens. I'll have some refactoring to do on these screens as right now they are very similar and there is some code duplication. I like to charge through this stuff as fast as possible, get something up and working, then take a step back and see what I can do to improve not only the user experience but also the code base. I had a few things that I wanted to accomplish with these screens:
- Email text field had focus.
- Keyboard was poped up for the user.
- The labels for the where inside the text fields and disappeared on input.
- I wanted the password text field to not show the password on the screen.
- I wanted to validate that the email address entered was a real email (or as close as I could get).
Here's how the Sign in screen came out:
You can't see it in this picture but the Email Address screen has a blinking cursor in it. So, for the email validation. Searched around a bit and ended up using an NSPredicate solution. Seems to work with iOS 3.0 so that should be fine. Found the awesome solution at the Cocoa with Love site, what a great blog! Here are the relevent bit's:
UITextField *emailEntry = (UITextField *)[emailCell viewWithTag:777];
UITextField *passwordEntry = (UITextField *)[passwordCell viewWithTag:778]; emailEntry.text = [emailEntry.text lowercaseString]; NSString *emailRegEx =
@"(?:[a-z0-9!#$%\\&'*+/=?\\^_`{|}~-]+(?:\\.[a-z0-9!#$%\\&'*+/=?\\^_`{|}"
@"~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\"
@"x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-"
@"z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5"
@"]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-"
@"9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21"
@"-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"; NSPredicate *regExPredicate =
[NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegEx];
BOOL myStringMatchesRegEx = [regExPredicate evaluateWithObject:emailEntry.text]; NSLog(@"myStringMatchesRegEx: %i", myStringMatchesRegEx);
NSLog(@"emailEntry: %@",emailEntry.text);
NSLog(@"passwordEntry: %@",passwordEntry.text);
So if the email validates, I get a BOOL returning YES. I also force a lower case on the email. The email won't validate unless it's all lower case. The Registration screen looks and act's much the same, so no use going over it.
And that's basically it. Tomorrow I'll be dumping those text fields to Core Data and then communicating with the server to authenticate. Should be fun! I quickly threw together a screen cast of what I have going so far, it's not that clear, but it gives a good idea of for the feel of it so far:
And I'll now leave you will some crazy goodness dug up from my archives. Stumbled across this one and said WTF!? Gotta love those crazy Japanese game shows :)
STALTO!!!
Cheers!
