Blog Archives

Pick Your Own Adventure iPhone Edition

A few days ago I came across this cool Pick Your Own Adventure game on Twitter from user Peretti. I decided to make a quick renewable application that used UIAlertViews and UIActionSheets to tell the story. We are going to implement the UIAlertView and UIActionSheet protocol methods in order to get the functionality we are looking for. This will be a short project but will show the important methods associated with these views.

Step 1

Start a new view based project called CYOA. If you want to add a background image you can add a UIImageView to your CYOAViewController.xib. You can get the one I used here. But that is not necessary.

Step 2

In your project we are going to create a new object to hold the pieces that compose and given “frame” of a pick your own adventure. A frame of a pick your own adventure game is composed of 6 things as far as I am concerned.

  1. Prompt/Title
  2. Choice 1 Text
  3. Choice 2 Text
  4. Choice 1 Tile
  5. Choice 2 Tile
  6. isEnd

Through the use of these 6 objects we will be able to create a network of what I have called “AdventurePieces”. Create a new file. Make a subclass of NSObject and call it AdventurePiece.

Open AdventurePiece.h and input the following.

#import 
 
@interface AdventurePiece : NSObject {
	NSString *message;
	NSString *choice1;
	NSString *choice2;
 
	AdventurePiece *choice1Piece;
	AdventurePiece *choice2Piece;
 
	BOOL isEnd;
}
 
@property (nonatomic, retain) NSString *message;
@property (nonatomic, retain) NSString *choice1;
@property (nonatomic, retain) NSString *choice2;
 
@property (nonatomic, retain) AdventurePiece *choice1Piece;
@property (nonatomic, retain) AdventurePiece *choice2Piece;
 
@property (assign) BOOL isEnd;
 
-initWithMessage:(NSString*)_message
	 firstChoice:(NSString*)_choice1
	secondChoice:(NSString*)_choice2
	  firstPiece:(AdventurePiece*)_choice1Piece
	 secondPiece:(AdventurePiece*)_choice2Piece
		   isEnd:(BOOL)_isEnd;
 
@end

Step 3

We are now going to implement the initialization method that we defined in our header. Open up AdventurePiece.m and input the following.

#import "AdventurePiece.h"
 
@implementation AdventurePiece
 
@synthesize message;
@synthesize choice1;
@synthesize choice2;
 
@synthesize choice1Piece;
@synthesize choice2Piece;
 
@synthesize isEnd;
 
-initWithMessage:(NSString*)_message
	 firstChoice:(NSString*)_choice1
	secondChoice:(NSString*)_choice2
	  firstPiece:(AdventurePiece*)_choice1Piece
	 secondPiece:(AdventurePiece*)_choice2Piece
		   isEnd:(BOOL)_isEnd
{
	if(self = [super init])
	{
		message = _message;
		choice1 = _choice1;
		choice2 = _choice2;
		choice1Piece = _choice1Piece;
		choice2Piece = _choice2Piece;
		isEnd = _isEnd;
	}
 
	return self;
}
@end

All we need to do in this initialization method is fill in our object parameters appropriately.

Step 4

Now that we have made the object that will facilitate our story we need to go about making the logic to automate bringing up the adventure pieces in the right order. First we are going to define one object in our view controller header. Go to CYOAViewController.h and input the following.

#import
#import "AdventurePiece.h"
 
@interface MakeMyOwnAdventureViewController : UIViewController <UIActionSheetDelegate, UIAlertViewDelegate>  {
 
	AdventurePiece *currentPiece;
}
 
@end

Step 5

With that done we need to do the following final steps.

  1. When the app launches a method should be called that creates a bunch of connected adventure pieces and sets the currentPiece instance variable to the one we desire to start on.
  2. Tell the app to show the currentPiece adventure tile.
  3. Respond to users pushing buttons on the adventure tile by resetting the current piece instance variable.
  4. Pull up a different view when the end of the chain is reached.

For our purposes we will be have UIAlertViews show the parts of the story before the end. And the final piece of our story will be shown in a UIActionSheet. Lets look at each of the code pieces required to finish off our last four steps.

1. When the app launches a method should be called that creates a bunch of connected adventure pieces and sets the currentPiece instance variable to the one we desire to start on.

-(void)makeTheStory {
 
	AdventurePiece *successPiece = [[AdventurePiece alloc] initWithMessage:@"Sparks fly from the red wire but no explosion! Kim Jong Il’s evil plot is foiled!" firstChoice:@"YAY" secondChoice:nil firstPiece:nil secondPiece:nil isEnd:YES];
	AdventurePiece *failPiece = [[AdventurePiece alloc] initWithMessage:@"Cutting the blue wire begins a chain reaction - omg that is bad. Like really bad..Kaboom! What went wrong!?!" firstChoice:@"Too Bad" secondChoice:nil firstPiece:nil secondPiece:nil isEnd:YES];
	AdventurePiece *failPiece1 = [[AdventurePiece alloc] initWithMessage:@"Bad Choice. You Die" firstChoice:@"Too Bad" secondChoice:nil firstPiece:nil secondPiece:nil isEnd:YES];
	AdventurePiece *middlePieceA = [[AdventurePiece alloc] initWithMessage:@"You parachute to North Korea, sneak past guards to a live nuclear bomb. Do you" firstChoice:@"Cut Red" secondChoice:@"Cut Blue" firstPiece:successPiece secondPiece:failPiece isEnd:NO];
	AdventurePiece *middlePieceB = [[AdventurePiece alloc] initWithMessage:@"As you are leaving you notice trained assassins behind you" firstChoice:@"Run" secondChoice:@"Fight" firstPiece:failPiece1 secondPiece:failPiece1	isEnd:NO];
	currentPiece = [[AdventurePiece alloc] initWithMessage:@"You are assigned to a dangerous mission." firstChoice:@"Accept" secondChoice:@"Vacation" firstPiece:middlePieceA secondPiece:middlePieceB isEnd:NO];
}

In this method we make 5 total adventure pieces. This specific pick your own adventure is quite short. It as 3 prompts, 2 choices each with a total of 4 end points. You can see what I mean in this diagram here. The white square are the prompts, the green squares are the choices and the red squares are the final results. We fill in the current piece instance variable as the top most piece and we are done here.

2. Tell the app to show the currentPiece adventure tile.

- (void)viewDidLoad {
 
    [super viewDidLoad];
	[self makeTheStory];
	[self showStoryForCurrentPiece];
}
-(void)showStoryForCurrentPiece {
 
	if([currentPiece isEnd]) {
		UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:[currentPiece message] delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:[currentPiece choice1],@"Retry",nil];
		[actionSheet showInView:self.view];
	}
 
	else {
 
		UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Your Message" message:[currentPiece message] delegate:self cancelButtonTitle:nil otherButtonTitles:[currentPiece choice1],[currentPiece choice2],nil];
		[alert show];
	}
}

This method should be called every time a new current piece is set. If checks to see if the adventure piece is an ending piece, if it is then an action sheet it created. If it is not an alert view is created. The button titles, and prompts are filled in appropriately.

Respond to users pushing buttons on the adventure tile by resetting the current piece instance variable.

- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex {
 
	if(buttonIndex == 0)
	{
		currentPiece = [currentPiece choice1Piece];
		[self showStoryForCurrentPiece];
	}
 
	else
	{
		currentPiece = [currentPiece choice2Piece];
		[self showStoryForCurrentPiece];
	}
}

When an alert view button is pressed this method will be called. An adventure piece that brings up an alert view should always have connected adventure pieces for both of the possible answers it as. This resets the currentPiece adventure piece and show the current piece again.

Pull up a different view when the end of the chain is reached

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
 
	if(buttonIndex == 1)
	{
		[self makeTheStory];
		[self showStoryForCurrentPiece];
	}
}

If this method is called that means that a action piece that was at the end of a chain was brought up. If the users hits the second button (button id == 1) that means they want to reset the story. This can be performed by building our story again showing the current piece again.

You can change the makeTheStory method to be whatever type of story you want. You can download the project here.

iPhone Coding – Turbo Charging Your Apps With NSOperation

Introduction

So, let’s face it, MANY applications in the app store are “Clunky”.  They have jittery interfaces, poor scrolling performance, and the UI tends to lock up at times.  The reason? DOING ANYTHING OTHER THAN INTERFACE MANIPULATION IN THE MAIN APPLICATION THREAD!

What do I mean by this? Well, I am essentially talking about multithreading your application.  If you don’t know what is meant by multithreading, I suggest you read up on it and return to this post OR don’t worry about it because you don’t need much threading knowledge for this tutorial.  Let’s dig in and I’ll give you an example of the problem.

The Problem

When you create an application, the iPhone spawns a new process containing the main thread of your application.  All of interface components are run inside of this thread (table views, tab bars, alerts, etc…).  At some point in your application, you will want to populate these views with data.  This data can be retrieved from the disk, the web, a database, etc… The problem is: How do you efficiently load this data into your interface while still allowing the user to have control of the application.

Many applications in the store simply ‘freeze’ while their application data is being loaded.  This could be anywhere from a tenth of a second to much longer. Even the smallest amount of time is noticeable to the user.

Now, don’t get me wrong, I am not talking about applications that display  a loading message on the screen while the data populates.  In most cases, this is acceptable, but can not be done effectively unless the data is loaded in another thread besides the main one.

Here is a look at the application we will be creating today:

Let’s take a look at the incorrect way to load data into a UITableView from data loaded from the web.   The example below reads a plist file from icodeblog.com containing 10,000 entries and populates a UITableView with those entries.  This happens when the user presses the “Load” button.

Wrong (download this code here to see for yourself)

@implementation RootViewController
@synthesize array;
 
- (void)viewDidLoad {
    [super viewDidLoad];
 
    /* Adding the button */
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Load"
        style:UIBarButtonItemStyleDone
        target:self
        action:@selector(loadData)];
 
    /* Initialize our array */
    NSMutableArray *_array = [[NSMutableArray alloc] initWithCapacity:10000];
    self.array = _array;
    [_array release];
}
 
// Fires when the user presses the load button
- (void) loadData {
 
    /* Grab web data */
    NSURL *dataURL = [NSURL URLWithString:@"http://icodeblog.com/samples/nsoperation/data.plist"];
 
    NSArray *tmp_array = [NSArray arrayWithContentsOfURL:dataURL];
 
    /* Populate our array with the web data */
    for(NSString *str in tmp_array) {
        [self.array addObject:str];
    }
 
    /* reload the table */
    [self.tableView reloadData];
}
 
#pragma mark Table view methods
 
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}
 
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.array count];
}
 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 
    static NSString *CellIdentifier = @"Cell";
 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                reuseIdentifier:CellIdentifier] autorelease];
    }
 
    /* Display the text of the array */
    [cell.textLabel setText:[self.array objectAtIndex:indexPath.row]];
 
    return cell;
}
 
- (void)dealloc {
    [super dealloc];
    [array release];
}
 
@end

“Looks good to me”, you may say.  But that is incorrect.  If you run the code above, pressing the “Load” button will result in the interface ‘freezing’ while the data is being retrieved from the web.  During that time, the user is unable to scroll or do anything since the main thread is off downloading data.

About NSOperationQueue And NSOperation

Before I show you the solution, I though I would bring you up to speed on NSOperation.

According to Apple…

The NSOperation and NSOperationQueue classes alleviate much of the pain of multi-threading, allowing you to simply define your tasks, set any dependencies that exist, and fire them off. Each task, or operation, is represented by an instance of an NSOperation class; the NSOperationQueue class takes care of starting the operations, ensuring that they are run in the appropriate order, and accounting for any priorities that have been set.

The way it works is, you create a new NSOperationQueue and add NSOperations to it.  The NSOperationQueue creates a new thread for each operation and runs them in the order they are added (or a specified order (advanced)).  It takes care of all of the autorelease pools and other garbage that gets confusing when doing multithreading and greatly simplifies the process.

Here is the process for using the NSOperationQueue.

  1. Instantiate a new NSOperationQueue object
  2. Create an instance of your NSOperation
  3. Add your operation to the queue
  4. Release your operation

There are a few ways to work with NSOperations.  Today, I will show you the simplest one: NSInvocationOperation.  NSInvocationOperation is a subclass of NSOperation which allows you to specify a target and selector that will run as an operation.

Here is an example of how to execute an NSInvocationOperation:

NSOperationQueue *queue = [NSOperationQueue new];
 
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
    selector:@selector(methodToCall)
    object:objectToPassToMethod];
 
[queue addOperation:operation];
[operation release];

This will call the method “methodToCall” passing in the object “objectToPassToMethod” in a separate thread.  Let’s see how this can be added to our code above to make it run smoother.

The Solution

Here we still have a method being fired when the user presses the “Load” button, but instead of fetching the data, this method fires off an NSOperation to fetch the data.  Check out the updated code.

Correct (Download the source code here)

@implementation RootViewController
@synthesize array;
 
- (void)viewDidLoad {
    [super viewDidLoad];
 
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Load"
       style:UIBarButtonItemStyleDone
       target:self
       action:@selector(loadData)];
 
    NSMutableArray *_array = [[NSMutableArray alloc] initWithCapacity:10000];
    self.array = _array;
    [_array release];
}
 
- (void) loadData {
 
    /* Operation Queue init (autorelease) */
    NSOperationQueue *queue = [NSOperationQueue new];
 
    /* Create our NSInvocationOperation to call loadDataWithOperation, passing in nil */
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
        selector:@selector(loadDataWithOperation)
        object:nil];
 
    /* Add the operation to the queue */
    [queue addOperation:operation];
    [operation release];
}
 
- (void) loadDataWithOperation {
    NSURL *dataURL = [NSURL URLWithString:@"http://icodeblog.com/samples/nsoperation/data.plist"];
 
    NSArray *tmp_array = [NSArray arrayWithContentsOfURL:dataURL];
 
    for(NSString *str in tmp_array) {
        [self.array addObject:str];
    }
 
    [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];
}
 
#pragma mark Table view methods
 
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}
 
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.array count];
}
 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 
    static NSString *CellIdentifier = @"Cell";
 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
 
    [cell.textLabel setText:[self.array objectAtIndex:indexPath.row]];
 
    return cell;
}
 
- (void)dealloc {
    [super dealloc];
    [array release];
}

As you can see, we haven’t added much code here, but we have GREATLY improved the overall user experience.  So, what did I do exactly?

  1. Moved all of the processing (downloading) code from the loadData method to another method that could be run asynchronously
  2. Created a new instance of NSOperationQueue by calling [NSOperationQueue new]
  3. Created an NSInvocationOperation to call our method loadDataWithOperation
  4. Added the operation to the queue
  5. Released the operation
  6. When the Data has been downloaded, we reload the table data in the main thread since it’s a UI manipulation

One thing to note here is we never actually tell the operation to run.  This is handled automatically in the queue.   The queue will figure out the optimal time run the operation and do it for you.

Now that you have your downloading and processing in a separate thread, you are now free to add things such as a loading view.

I will be expanding on this tutorial in the coming week and showing you how to cache data and display old data to the user while the new is loading.  This is a popular technique used in many Twitter and News applications.

That concludes today’s tutorial.

Post questions in the comments or Ping me on Twitter.

Happy iCoding!

iPhone Coding Recipe – Shortening URLs

I had some a to shorten URLs for an in-application Twitter client I’m working on and thought I would share my simple solution with you guys.

It’s actually pretty straight forward and can be done in 1 line of code.  I have broken it up into several for clarity.

NSString *url    = @"http://brandontreb.com";
NSString *apiEndpoint = [NSString stringWithFormat:@"http://api.tr.im/v1/trim_simple?url=%@",url];
NSString *shortURL = [NSString stringWithContentsOfURL:[NSURL URLWithString:apiEndpoint]
		 encoding:NSASCIIStringEncoding
		 error:nil];
NSLog(@"Long: %@ - Short: %@",url,shortURL);
 
// Outputs Long: brandontreb.com - Short: tr.im/MRDd

Pretty easy huh?

The magic here is in a method that Apple gave us as part of NSString. This method is called stringWithContentsOfURL. It will easily allow you to grab the text of any remote source.

I have used Tr.im as an example here because their service is very easy to use and has little overhead.  I would have used bit.ly but they return a JSON string which would then have to be parsed.  Tr.im’s trim_simple service simply outputs the string of the shortened URL.

Sure Twitter may shorten links for you automatically, but what if you want to use a custom service? Or,…wait for it… use it for something other than Twitter (please post in the comments if you do. I would love to hear some other uses :) )

Questions? Comments? Complaints?

Happy iCoding

UITextField – A Complete API Overview

The UITextField is probably one of the most commonly used UI controls on the iPhone. It is the primary method of user input via the keyboard and provides a great deal of additional functionality.

With the success of our las API tutorial on NSArray, I thought I would do another walkthrough, this time on UITextField. I will be explaining all of the properties for it as well as bringing up some functionality that you may not have known about.

Text Attributes

The attributes have to do with the actual text inside of the UITextField.

text The text displayed in the UITextField
placeholder The text that gets displayed prior to the user entering in anything. This text is usually a lighter color than the primary text to denote that it will be replaced.
font The font of the text to be displayed. You can set it like this
textColor The color of the text that is displayed
textAlignment How the text is aligned in the UITextField. The possible values for this are UITextAlignmentLeft, UITextAlignmentRight, UITextAlignmentCenter

Here are some examples of using these properties.

// Setting the text
[myTextField setText:@"This is some text!"];
 
// Setting the placeholder
[myTextField setPlaceholder:@"Type text here"];
 
// Setting the font.
[myTextField setFont:[UIFont fontWithName:@"Times New Roman" size:14]];
 
// Setting the text color
[myTextField setTextColor:[UIColor blueColor]];
 
// Setting the text alignment
[myTextField setTextAlignment:UITextAlignmentCenter];

Here is what the UITextField would look like after we update these properties.


Adjusting the size of the text in the UITextField

The text displayed in our UITextField can be dynamically sized based on the width of the UITextField. The benefit of this is all of the text being typed will be visible on the screen. It will shrink the text down until it reaches the default font size of 17. So, for this to make sense, you must set the font size of the UITextField to something larger than 17.

adjustsFontSizeToFitWidth Boolean value denoting whether to fit the font size to the width of the UITextField.

Here is an example of using these properties.

[myTextField setFont:[UIFont fontWithName:@"Times New Roman" size:30]];
[myTextField setAdjustsFontSizeToFitWidth:YES];

Here are some screenshots of the text shrinking when typing in the UITextField.


Managing the editor’s behavior

These two properties are pretty straight forward.

editing Read-only boolean value letting you know if the user is currently editing the UITextField
clearsOnBeginEditing Clears the text in the field every time the user begins to edit it.

Not very exciting and probably doesn’t even deserve an example…

Setting the view’s background appearance

This group of properties defines how the UITextField will look. If you have ever seen a fancy input box, this is how they are doing it.

borderStyle Defines the type of border for the UITextField. Possible choices are UITextBorderStyleNone, UITextBorderStyleLine, UITextBorderStyleBezel, and UITextBorderStyleRoundedRect. The default is UITextBorderStyleNone.
background A UIImage representing the background image of the UITextField when it’s enabled. If this field is altered the borderStyle property is ignored.
backgroundDisabled A UIImage representing the background image of the UITextField when it’s disabled.

Here is are some example of using each of the border styles

// Border Style None
[myTextField setBorderStyle:UITextBorderStyleNone];

// Border Style Line
[myTextField setBorderStyle:UITextBorderStyleLine];

// Border Style Bezel
[myTextField setBorderStyle:UITextBorderStyleBezel];

// Border Style Rounded Rect
[myTextField setBorderStyle:UITextBorderStyleRoundedRect];

The border style is not terribly exciting. However, you can really spruce up your UITextFields using the background property. Here is an example of setting the background property to this image.

myTextField.textAlignment = UITextAlignmentCenter;
myTextField.textColor = [UIColor whiteColor];
myTextField.borderStyle = UITextBorderStyleNone;
myTextField.background = [UIImage imageNamed:@"bg.png"];

and the result… Looks pretty good ehh? One GOTCHA that I want to point out here is, to get the background property to work correctly, you must set the boderStyle to anything other than UITextBorderStyleRoundedRect. Otherwise, the default UITextField will be displayed.
Setting the view’s background appearance

Managing Overlay Views

Another interesting way of customizing your UITextFields is to use an overlay. UITextField offers a left and right overlay for your UITextFields. Here are the properties:

clearButtonMode The circled X that gets displayed when typing. Used to clear out the text. Possible values: UITextFieldViewModeNever, UITextFieldViewModeWhileEditing, UITextFieldViewModeUnlessEditing, UITextFieldViewModeAlways
leftView The view that appears to the left inside a UITextField. This could be something like a magnifying glass for search.
leftViewMode Works like clearButtonMode, but toggles the leftView.
rightView Same as leftView, except it aligns to the right.
rightViewMode Same as leftViewMode but controls the rightView

Let’s take a look at how adjusting the leftView works:

UIImageView * myView = [[ UIImageView  alloc ]  initWithImage :
		[UIImage  imageNamed : @"wordpress.png" ]];
[myTextField  setLeftView :myView];
[ myTextField   setLeftViewMode: UITextFieldViewModeAlways];
[myView release ];

As you can see, the text aligns after the image. This is a very simple way to really spruce up your UITextFields.

The last thing we are going to discuss is showing and hiding the keyboard.

Showing and Hiding The Keyboard

To show the keyboard:

[myTextField becomeFirstResponder];

To hide the keyboard

[myTextField resignFirstResponder];

Well, I hope you have enjoyed this tutorial on the UITextField.  I would love to see links to some interesting custom UITextFields in the comments, so please post them.  Thanks for reading and happy iCoding!

iPhone Coding Tutorial – How To Make Spaces In UIAlertView’s

Have you ever wonder how to make spaces in a UIAlertView? or maybe even in a UITextView. Well today I am gonna show you guys how to do this in code.

1. Create A New Window Based Application
So lets do the usual process and open Xcode and go to “File” then “New Project.” Lets go ahead and do a Windows Based App. Name it whatever you like, I will name is “Spaces”

2. Implementing The Code
Now jump into the SpacesAppDelegate.m and under the applicationDidFinishLaunching method make your UIAlertView. Now when you get to messages, you can maybe do “Hi my name is Dewan Payroda! nnI like to code apps!” and thats it! nn makes a new line. In this case I did two of those, so it made two line breaks. The code is below how mines looked. Also if you want to watch a video tutorial on this click the link under the code.

- (void)applicationDidFinishLaunching:(UIApplication *)application {

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@”TEST”
message:@”Hi my name is Dewan Payroda. nnI like to code apps!”
delegate:self
cancelButtonTitle:@”Dismiss”
otherButtonTitles:nil];
[alert show];
[alert release];

// Override point for customization after application launch
[window makeKeyAndVisible];

}

Video Tutorial Here & Source Code Here

- AppStoreMod
YoutubeWebsiteTwitterXcode Video TutorialsAppStoreApps

iPhone Coding Tutorial – In Application Emailing

IMG_0001A lot of applications you see have an email button. When you click it then it will leave the application and take you to the Mail application. It can get really annoying leaving the application and then going back in after your done sending the email. This is just a great way to show off your app and make your app look more professional and make it easier on the user by filling in the To and Subject for them. They are also able to change the From to whatever email then want you to receive an email from just like you can do in the Mail app. So todays tutorial is gonna show you how to email within your application. We will be using the MessageUI framework and we will also include an attachment in the email. Theres a screenshot to the left of how it will look.

So lets get started…

1. Create A New View Based Application
You can name yours whatever you want, in the tutorial I will be referring it as the NameViewControllers.

2. Import The Frameworks

The first thing we need to do is import the framework. So go to your Frameworks folder in the Files In Pain section on the left. Open the folder and right click one of the frameworks and click “Reveal In Finder.” Heres a screenshot on what you should do.

Screen shot 2009-11-18 at 7.58.04 PM

Go ahead and look for the “MessageUI.framework” and highlight it then drag it into your frameworks folder. Make sure that when you click Add on the thing that makes sure you want to import it that “Copy items into destination group’s folder (if needed)” is not check. Thats a very important step or you will have big time problems and you do this with any frameworks you would ever use in the future.

3. Implementing The Code

Now that we have imported the framework lets get into some coding. So go ahead and jump in the NameViewController.H and make an IBAction for a button. Then copy that code and paste it in the NameViewController.M with curly brackets. Also make sure to add the button in Interface Builder and link it up with a Touch Up Inside method. You guys are at the point to knowing how to hook up actions and dragging stuff into Interface Builder. After that we want to on the top of the NameViewController.h import the framework. So on the top do #import “MessageUI/MessageUI.h” and the reason why we do this is because we must import out MessageUI framework to make calls to the associated header files. Now we need to also put in the delegate protocols for this framework. @interface NameViewController: UIViewController do this code <MFMailComposeViewControllerDelegate, UINavigationControllerDelegate>. Heres the code here for the NameViewController.H

#import <MessageUI/MessageUI.h>

@interface MailComposerViewController : UIViewController

<MFMailComposeViewControllerDelegate,UINavigationControllerDelegate>  {

}

-(IBAction)pushEmail;

@end


Now after your done with the .H jump into the .M viewcontroller. Now in your button action code do this:

-(IBAction)pushEmail {

MFMailComposeViewController *mail = [[MFMailComposeViewController alloc] init];

mail.mailComposeDelegate = self;

if ([MFMailComposeViewController canSendMail]) {

//Setting up the Subject, recipients, and message body.

[mail setToRecipients:[NSArray arrayWithObjects:@"email@email.com",nil]];

[mail setSubject:@"Subject of Email"];

[mail setMessageBody:@"Message of email" isHTML:NO];

//Present the mail view controller

[self presentModalViewController:mail animated:YES];

}

//release the mail

[mail release];

}

//This is one of the delegate methods that handles success or failure

//and dismisses the mail

- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error

{

[self dismissModalViewControllerAnimated:YES];

if (result == MFMailComposeResultFailed) {

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@”Message Failed!” message:@”Your email has failed to send” delegate:self cancelButtonTitle:@”Dismiss” otherButtonTitles:nil];

[alert show];

[alert release];

}

}


What if we wanted to include an image attachment to the email? Well its quite simple. Just add this to the code right under the part where you set up the Recipient, Subject, and the Message.

UIImage *pic = [UIImage imageNamed:@"Funny.png"];

NSData *exportData = UIImageJPEGRepresentation(pic ,1.0);

[mail addAttachmentData:exportData mimeType:@"image/jpeg" fileName:@"Picture.jpeg"];

Now we are setting up the MailComposer in the first part of the code in the action. Then we call a didFinishWithResult method where we are setting up if the email fails or sends. Also it sets up a Cancel button for you so we have to call the dismiss method so that it works. In the attachment code just edit the imageNamed:@”" with your images name.That is basically it! The source code is below for the people that just doesn’t wanna copy and paste or type… I am just jking with you guys. Happy iCoding!

iPhone Tutorial – In Application Emailing

iPhone Coding Tutorial – Inserting A UITextField In A UIAlertView

Screen shot 2009-11-09 at 8.12.11 AM copyThis will be a simple tutorial showing you how to put a UITextField in a UIAlertView. This is simple and just a couple lines if code. You will learn CGAffineTransform and coding UITextField programmatically.

Heres a screenshots of what we should get.

Screen shot 2009-11-09 at 8.12.11 AM

So lets go ahead and get started…

1. Create A New View Based Application
You can name it whatever you want, I am gonna name it TextFieldInAlert.

2. Implementing The Code
Jump in the viewcontroller.m or if you called it TextFieldInAlert then TextFieldInAlert.m Now find the -(void)viewDidLoad method. Uncomment it and put this code in there.

- (void)viewDidLoad {

[super viewDidLoad];

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@”Enter Name Here” message:@”this gets covered!”

delegate:self cancelButtonTitle:@”Dismiss” otherButtonTitles:@”OK!”, nil];

UITextField *myTextField = [[UITextField alloc] initWithFrame:CGRectMake(12, 45, 260, 25)];

[myTextField setBackgroundColor:[UIColor whiteColor]];

[alert addSubview:myTextField];

[alert show];

[alert release];

[myTextField release];

}

So we are basically calling a UIAlertView and then we are adding the UITextField programmatically. You might have noticed in the message part of the UIAlertView we put “this gets covered!”, if we didn’t put that sentence then the alerts buttons would go up more and the UITextField will be messed. You can try taking that line out and see what happens. Now Build and Run the app. Now you got the UITextField to be inside the UIAlertView. Now try tapping the UITextField. Uh oh, why is the Keyboard covering the UIAlertView? Well there is just a simple fix to this. We just add two more lines of code and it will fix that. Add this to your code

CGAffineTransform myTransform = CGAffineTransformMakeTranslation(0, 60);

[alert setTransform:myTransform];

So now your full code should be looking like this.

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@”Enter Name Here” message:@”this gets covered!” delegate:self cancelButtonTitle:@”Dismiss” otherButtonTitles:@”OK!”, nil];

UITextField *myTextField = [[UITextField alloc] initWithFrame:CGRectMake(12, 45, 260, 25)];

CGAffineTransform myTransform = CGAffineTransformMakeTranslation(0, 60);

[alert setTransform:myTransform];

[myTextField setBackgroundColor:[UIColor whiteColor]];

[alert addSubview:myTextField];

[alert show];

[alert release];

[myTextField release];

Now if you Build and Run, you will notice the UITextField is a little higher and when you tap the UITextField the Keyboard doesn’t cover it up anymore. That is what the CGAffineTransform was for. So that is basically it! There is a video tutorial also available and if you like video tutorial more then written ones you can check it out out by clicking HERE. You can download the source code below. Happy iCoding!

iPhone Tutorial – UITextField In A UIAlertView

Objective-C Tutorial: NSArray

Here at iCodeblog, we have been showing you guys how to create many different types of applications from the ground up.  Well, today I decided to do something different and get down to some of the nitty gritty of a structure we rely heavily on in objective-C.

The NSArray is a huge workhorse that we use quite frequently without even thinking about it.  The NSArray class isn’t just your ordinary array.  Not only does it provide random access, but it also dynamically re-sizes when you add new objects to it and has many methods to make our lives easier.  While I won’t go over every method in NSArray (there are quite a few), I will discuss some of the more important ones that are most commonly used.  Let’s take a closer look at this class.

Factory Methods

Factory methods are static methods that build new instances of NSArrays from given parameters and return them.  The table below details on all of the factory methods for the NSArray class.

+ (id)array Creates and returns an empty array
+ (id)arrayWithArray:(NSArray *)anArray Creates and returns an array containing the objects in another given array.
+ (id)arrayWithContentsOfFile:(NSString *)aPath Creates and returns an array containing the contents of the file specified by a given path. * The file must be of type .plist for this method to work
+ (id)arrayWithContentsOfURL:(NSURL *)aURL Similar to arrayWithContentsOfFile except it will load the .plist remotely from a given website. This would be a very simple way to get data from a web service.
+ (id)arrayWithObject:(id)anObject Creates and returns an array containing a given object. This will just be a 1 element array
+ (id)arrayWithObjects:(id)firstObj, … This method is used when you have multiple objects on hand and want easily insert them into an array. Make sure the last element you add is nil or this method won’t work.
+ (id)arrayWithObjects:(const id *)objects count:(NSUInteger)count Creates and returns an array that includes a given number of objects from a given C array.

Here is some example usage of building NSArrays with these factory methods…

// I am using strings, but you can add just about any object to an NSArray
 
// Creates an NSArray with one object
NSArray  * myArray = [NSArray arrayWithObject:@"foo"];
 
// Creates an NSArray with multiple objects. Don't forget to add nil as the last object
NSArray  * myArray2 = [NSArray arrayWithObjects:@"foo",@"bar",@"baz",nil];
 
// Creates an NSArray from another NSArray
NSArray * myArray3 = [NSArray arrayWithArray:myArray2];
 
// This will create an NSArray from data on iCodeBlog.  Go ahead and try it out, this file exists on our servers and contains valid data.
NSArray * myArray4 = [NSArray arrayWithContentsOfURL:[NSURL URLWithString:@"http://icodeblog.com/wp-content/uploads/2009/08/foo.plist"]];

You can also choose not to use factory methods and just use the normal NSArray initializers. They are pretty much the same as the factory methods only you do the allocation yourself. An example of this might be:

NSArray * foo = [[NSArray alloc] initWithObjects:@"foo",@"bar",@"baz",nil];

Accessing The NSArray

Apple has provided us with many great methods for getting data out of an NSArray as well as information about it.  Here is a table of methods and their descriptions.

- (BOOL)containsObject:(id)anObject Returns true if a given object is found in the array, false otherwise
- (NSUInteger)count Returns the size of the array
- (id)lastObject Returns the last object in the array (the one with the highest index)
- (id)objectAtIndex:(NSUInteger)index Gives you random access to the array. Returns the object at a given index.

These are just a few of the accessor methods of NSArray and most likely the only ones you will need to use.

Searching The Array

If you are looking for the index of an object in an array, there is really only one method you need to use. That method is indexOfObject: . An example of usage might be:

NSString * f = @"foo";
NSString * b = @"bar";
NSString * z = @"baz";
NSArray  * myArray2 = [NSArray arrayWithObjects:f,b,z,nil];
NSInteger idx = [myArray2 indexOfObject:b];
// This would return 1 (since NSArrays are 0 - indexed)

This is much cleaner code than looping over the entire array to find an object. It’s probably more efficient too as Apple is pretty clean in how they code things.

Sending Message To Objects In The Array

Ok, so this is pretty cool.  Say you have an array of objects that all need to do something.  For example, an array of bullets, and you want all of the bullets to move forward one pixel. Rather than looping over each bullet object in the bullets array and calling [bullet move], you can do it in one method call on the array.  This method is called – (void)makeObjectsPerformSelector:(SEL)aSelector and here is an example of usage.

// Lets pretend the bullet object has a method called move
// and there is an array of 50 bullets
 
[bullets makeObjectsPerformSelector:@selector(move)];

And that’s it… The move method will now be called on every bullet object in the array with this one method call. Very clean and easy to use. Now, if the method you want to call takes an argument, there is the – (void)makeObjectsPerformSelector:(SEL)aSelector withObject:(id)anObject method. This will allow you to pass an object to each method being called.

Sorting Arrays

Apple has provided us with some very slick ways to sort an NSArray. I will not go into too much detail here as I have a full tutorial planned dedicated to sorting arrays. For now, I will just show you how to sort an NSArray of NSStrings. The method we will be using is sortedArrayUsingSelector. Here is the example usage.

NSArray *sortedArray =
    [myArray2 sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
    // This will return a sorted array that looks like [@"bar",@"baz",@"foo"]

You can plug in any of the string compare functions there to compare the strings. If you are sorting an NSArray of custom objects (like users), you can overwrite the compare method for that object and pass compare in for the selector. Just make sure you remember the : at the end of the method.

Looping Through Arrays

So if you are reading this, I assume you have seen a for loop before. ex: for(int x=0; x < … This would most likely not be a good way to enumerate an NSArray as Apple has provided a much nice way for doing so. There are some situations where this method would be preferred (like when u need to calculate the indices or something). But in most cases, you will want to use the special for loop provided by Apple. If you have ever coded PHP, it is much like the foreach loop. Here is an example:

for(NSString * myStr in myArray2) {
    NSLog(myStr);
}

This will loop over myArray2 and pring each element in that array. Very clean and efficient.

Saving Arrays For Later

There is an Array of ways to save data on the iPhone (Pun intended). One way is to simply dump the array to a file. This will write out the NSArray to a plist file on disk that can be loaded later using the arrayWithContentsOfFile method of NSArray. That method is rightfully named writeToFile. The example usage for it is as follows.

NSArray  * myArray2 = [NSArray arrayWithObjects:@"foo",@"bar",@"baz",nil];
[myArray2 writeToFile:filePath atomically:YES];

And there you have it! You are probably wondering what the atomically variable means. Me too… Just kidding. If YES, the file will be written to a temp location and then renamed to its final destination. This is put in place to guarantee that the file won’t be corrupted even if the system crashes (rename will be much faster than write). Why is this needed you ask? Consider this scenario.

You want to write a huge array to disk to save it for later. When your app starts it checks the disk to see if this file exists, if it does it loads an NSArray from it. If it doesn’t it creates a new NSArray. Say the last time the app ran, the system crashed while the file was being written. If atomically was set to NO, the original file would be corrupt and now the application would be loading corrupt data every time it starts from now on (most likely causing a crash). However, if you set atomically to YES, the temp file would get corrupted and the app would never see it. That way, the next time the app starts it will create a new fresh NSArray and all will be good.

Good rule of thumb, set atomically to YES.

That concludes our tutorial on NSArray. If you have any questions or comments, feel free to post them in the comments section or write me on twitter.

WP Like Button Plugin by Free WordPress Templates