Blog Archives

5 Third Party iOS Libraries I Have Found Useful Lately (iPhone Programming Tutorials)

Posted by brandontreb at iPhone Programming Tutorials

As I mature as a developer, I try to rely on other people’s code more an more. Why build something from scratch when a solution already exists that you can fit in your project. In Pocket MUD Pro, I used 13 3rd party libraries and am using quite a bit more in the project that I’m currently working on. I figured that I would share some of the libraries that I have been using so that it might save you some time in the future.

1. CocoaAsyncSocket

Link: github.com/robbiehanson/CocoaAsyncSocket

Many of my applications involve TCP or UDP networking. There is a lot of boiler plate code involved in every networked application, and CocoaAsyncSocket solves much of that for you.

2. Appirater

Link: github.com/arashpayan/appirater/

Screenshot

Hopefully, you have heard of this one or a similar library by now. It’s very challenging to get users to want to review your applications, let alone give you a positive review. AppiRater allows you to prompt a user to rate your application based on either number of launches or “significant events” which you specify.

3. Zip Archive

Link: code.google.com/p/ziparchive/

I try to ship small applications that download assets upon launch. A good way to send these assets over the wire is to zip them up and stick them on your server. I have written an article about this on iCodeBlog.

4. Quick Dialog

Link: github.com/escoz/QuickDialog

Creating forms in iOS is pretty painful. It usually involves custom table cells and a lot of delegate nonsense. QuickDialog takes away some of this pain and allows you to easily create iOS forms. You can even design them using JSON.

QuickDialog Screenshot

5. TSMiniWebBrowser

Link: github.com/tonisalae/TSMiniWebBrowser

Often times, you want a quick and dirty browser in your application. I generally use it to point to in-app documentation or take the user to a page after tapping on a link. It’s quick and easy.

Screenshot

I hope you find some value in this list. I’d love to hear about the libraries you use frequently.

Happy Coding!

Unzipping Files Using ZipArchive (iPhone Programming Tutorials)

Posted by brandontreb at iPhone Programming Tutorials

In this tutorial, I am going to demonstrate how you can zip and unzip files from within your iOS applications. We will be using a third party library called ZipArchive to achieve this. While there are a couple solutions out there to zip and unzip files, I feel that the ZipArchive library was the fastest and easiest way to get up and running.

Why Would I want To Unzip Files?

That’s a great question. There are a number of reasons why you might want to support zipping and unzipping files inside of your applications. Here are just a few:

Apple’s 50 MB App Store Download Cap

Apple has imposed a 50MB download limit over 3G on applications downloaded to appease carriers and not hog all of their bandwidth. One way to circumvent this is to keep your binaries very small, and download the resources your application needs. The best way to package these resources is of course, a zip file. So the process (as you will see demoed below), is to open your app, check for resource updates, download the zip file, and unzip it. Now you can ship smaller applications, that fetch their resources dynamically.

Dynamic Updates To Content

I touched on this above. When your application needs updated assets, the common practice is to submit an update to the App Store. This could take up to a week for Apple to Review and publish. A faster approach is to zip your assets up and stick them on a server somewhere (even your Dropbox) and have your app download and unzip them. This way, whenever you want to make asset-based changes to your application, you won’t need to submit another copy of it to the store.

Downloading Zip Files From The Web

One huge downfall of Safari and the Mail app is, they are unable to open zipped files. It would be nice to offer some sort of support to view zipped archives on your device. Many of the “download” apps in the store support this, and you can too with some help from ZipArchive.

Setting Up Your Project

Head over to code.google.com/p/ziparchive/ and checkout a copy of ZipArchive. Or you can just type this into your terminal.

svn checkout http://ziparchive.googlecode.com/svn/trunk/ziparchive-read-only

Once you have cloned the repository, delete the MakeFile file from the minizip folder. We will let XCode build our files. Now, drag this minizip folder as well as the ZipArchive.h and ZipArchive.mm files into your project, making sure to check “Create groups for any added folders”. Also, be sure your target is checked.

Note: No ARC Support

If you are using an ARC enabled project, you will need to tell the compiler not to use ARC for ZipArchive. To do this, click on the project in the left hand column. Then click on your target in the middle column and select the “Build Phases” tab.

Expand the “Compile Sources” area, locate ZipArchive.mm and double click on it. In the box that pops up, type in -fno-objc-arc and click Done.

Linking libz

The last step is to link your project against libz.1.2.5.dylib. From the Build Phases screen you navigated to above, expand the Link Binary With Libraries section and click the “+” button to add a new library. Search the list for libz.1.2.5.dylib, select it and click Add.

Now, compile your project and it should succeed with no errors. One thing to note is ZipArchive might produce some warnings, they are not a big deal, but if you are a warning Nazi (you should be), dig into the code and see if you can solve them yourself.

Downloading And Unzipping Files

I will now show you how easy it is to download a zip file from the web, unzip its contents, and use them in your project. The method of which we will download the files is very basic and most likely wouldn’t be used in production without further error reporting and checking.

The sample project has a view that looks like this:

It’s basically a UIImageView and a UILabel. Inside of the view controller I have set up IBOutlets for these two items. Make sure and download the sample project to see the implementation details. We will be downloading a zip file from the web that contains an image and a text file which you can see displayed in the screenshot above. Once unzipped, the image will be set as the viewable image in our UIImageView and the textual contents of the .txt file will be displayed inside of the UILabel.

**1. Import the ZipArchive headers **

#import "ZipArchive.h"

2. Download the the zip file

    // 1      dispatch_queue_t queue = dispatch_get_global_queue(                                                        DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);     dispatch_async(queue, ^{         NSURL *url = [NSURL URLWithString:@"http://www.icodeblog.com/wp-content/uploads/2012/08/zipfile.zip"];         NSError *error = nil;         // 2         NSData *data = [NSData dataWithContentsOfURL:url options:0 error:&error];           if(!error)         {                     // 3             NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);             NSString *path = [paths objectAtIndex:0];             NSString *zipPath = [path stringByAppendingPathComponent:@"zipfile.zip"];               [data writeToFile:zipPath options:0 error:&error];               if(!error)             {                 // TODO: Unzip             }             else             {                 NSLog(@"Error saving file %@",error);             }         }         else         {             NSLog(@"Error downloading zip file: %@", error);         }       });

This preliminary code downloads a zip file from iCodeBlog and saves it to the caches directory for the application.

  1. Creates a dispatch queue in which to run our code on with default priority.
  2. Quick and dirty way of fetching data from the web.
  3. Resolves the path to the caches directory and writes out the downloaded data to a local zip file

Now that you have it downloading the file to disk, it’s time to unzip that file and make use of it’s contents.

3. Unzipping the downloaded file

The last step here is to unzip the file you just downloaded. To be clear, it was save to the path /Library/Caches/zipfile.zip and once extracted, it’s contents will be inside of the Caches folder as well.

Replace the //TODO: Unzip in the code above, with the following code:

ZipArchive *za = [[ZipArchive alloc] init]; // 1 if ([za UnzipOpenFile: zipPath]) {           // 2           BOOL ret = [za UnzipFileTo: path overWrite: YES];     if (NO == ret){} [za UnzipCloseFile];       // 3     NSString *imageFilePath = [path stringByAppendingPathComponent:@"photo.png"];     NSString *textFilePath = [path stringByAppendingPathComponent:@"text.txt"];     NSData *imageData = [NSData dataWithContentsOfFile:imageFilePath options:0 error:nil];     UIImage *img = [UIImage imageWithData:imageData];     NSString *textString = [NSString stringWithContentsOfFile:textFilePath          encoding:NSASCIIStringEncoding error:nil];       // 4                dispatch_async(dispatch_get_main_queue(), ^{         self.imageView.image = img;         self.label.text = textString;     });

Here is an explanation of what’s going on.

  1. Opens the file and unzips it in memory
  2. Writes the unzipped contents out to a given path (Caches folder)
  3. Makes use of the unzipped files
  4. Updates the UI (on the main thread of course) with the newly fetched data.

It really is that simple.

Zipping Files

Now you are going to see how to go the other way and zip up some files on disk. Again, this could be particularly handy when you want to allow your users to share groups of files via the web or email.

If you completed the steps above, your caches folder should have some files lying around that we can just zip up again and send off. We are going to zip up the two files you previously unzipped, stuff them into a new zip file, and write that out to the documents directory.

In my sample project, I have created a new button at the top that says “Zip Files” which links to an IBAction called zipFilesButtonPressed: when tapped. That is where I will be doing the zipping:

- (IBAction)zipFilesButtonPressed:(id)sender {     // 1     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);     NSString *docspath = [paths objectAtIndex:0];       // 2     paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);     NSString *cachePath = [paths objectAtIndex:0];       // 3     NSString *zipFile = [docspath stringByAppendingPathComponent:@"newzipfile.zip"];              // 4     ZipArchive *za = [[ZipArchive alloc] init];     [za CreateZipFile2:zipFile];       // 5     NSString *imagePath = [cachePath stringByAppendingPathComponent:@"photo.png"];     NSString *textPath = [cachePath stringByAppendingPathComponent:@"text.txt"];       // 6     [za addFileToZip:imagePath newname:@"NewPhotoName.png"];     [za addFileToZip:textPath newname:@"NewTextName.txt"];       // 7     BOOL success = [za CloseZipFile2];         NSLog(@"Zipped file with result %d",success);   }

Here is what’s going on:

  1. Resolve the path to the documents directory. We will need this when determining the path to write out our new zip file.
  2. Resolve the path to the caches directory. This is used to fetch the files that will be zipped up.
  3. Determines the path the zip file we will be writing out.
  4. Instantiates the ZipArchive object and tells it to create a new “in-memory” zip file. Note, the file won’t be written out until you call the corresponding CloseZipFile2 method.
  5. Resolve the path to the files that will be zipped up.
  6. Add the files to the zip archive. You can add as many files as you would like here. You can even add directories (ie you could have added the entire caches directory if you wanted to).
  7. Write out the zip file and close it. Just to test, we log the result to ensure that the zipping was successful.

After running through the application, tapping on the “Zip Files” button, look inside of the Application’s Documents folder (located ~/Library/Application Support/iPhone Simulator/[iOS Version]/Applications/[Unique ID]/Documents]. It should contain a single zip file called newzipfile.zip. If you unzip it, you should see the two files that you stuffed in there extracted.

Conclusion

You have now seen how to zip and unzip files on iOS devices using the ZipArchive library. You can download the sample project at the bottom of this post. As always, if you have any questions or comments, feel free to write them in the comments of this post or write them to me on Twitter @brandontreb.

Happy iCoding!

Download The Sample Project

How to Add GPS to Your iOS App – Part 1 (iPhone Programming Tutorials)

Posted by Shawn Grimes at iPhone Programming Tutorials

CoreLocation Graphic

In Part 1 of this series, I will introduce you to the very basics of CoreLocation services and getting the location of the device currently being used.

About CoreLocation

The CoreLocation framework provides your app with the ability to get a device’s current location, provided the user of the device has granted your app access to that information.

Location services are provided in two major ways using this framework:

  1. Standard Location Services– This service provides the most accurate location information using a variety of methods including celluar, wifi, and GPS.

    • Most accurate.
    • Consumes the most power and can take a longer time to acquire.
    • Can only be used when your application is in the foreground.
  2. Significant Change Location Services – This service uses cellular data to determine a general idea of where the device is located.

    • Fastest and uses the least amount of power to determine the location.
    • Can also be used to notify your app when a significant change in the location has occurred even if your app is not in focus.

Project Files:

You can download the project files at this github repository: github.com/shawngrimes/Location-and-Map-Sample

Adding Location Frameworks

The first step to adding location services to your project is to add the CoreLocation framework.

Link Binary With Libraries
  1. Select your target and go to the “Build Phases” tab.
  2. Click the “+” button under “Link Binary With Libraries”
  3. Select the CoreLocation framework and click “Add”
Add Core Location Framework

Location Manager

With location services, you create an instance of CLLocationManager. There is usually one instance of this per app so I feel a good place for this is in the App Delegate and then each view can access the current location from the App Delegate.

To start, open your App Delegate header file:

  1. Add #import <CoreLocation/CoreLocation.h> to the top
  2. Specify that your app delegate complies with the Core Location Delegate protocol by changing your @interface line with @interface CFAAppDelegate : UIResponder <UIApplicationDelegate, CLLocationManagerDelegate>
  3. Specify a CLLocationManager property by adding @property (strong, nonatomic) CLLocationManager *locationManager right before the @end statement.

Your App Delegate header file should now look similar to the following:

#import <UIKit/UIKit.h>   //Add Location Framework #import <CoreLocation/CoreLocation.h>   //Specify this app delegate complies with the location manager delegate @interface CFAAppDelegate : UIResponder &lt;UIApplicationDelegate, CLLocationManagerDelegate&gt;   @property (strong, nonatomic) UIWindow *window;   //Add a location manager property to this app delegate @property (strong, nonatomic) CLLocationManager *locationManager;   @end

Creating The Location Manager Object

Switch over to the App Delegate implementation file (.m), and we are going to create our location manager object. The first thing we should do, since we created it as a property of our app delegate, is synthesize the property so add @synthesize locationManager=_locationManager; under the line that reads @synthesize window = _window;.

#import "CFAAppDelegate.h"   @implementation CFAAppDelegate   @synthesize window = _window; @synthesize locationManager=_locationManager;

Now that our property is synthesized, we can create the object. I usually create it in the method application didFinishLaunchingWithOptions:. A Location Manager object is created similar to any other object but there are three important properties you should set after you have alloc’d/init’d.

  1. .purpose – The purpose property is displayed to the user of your app when they are prompted to allow your app to use their location. It gives you a chance to explain what your app is going to do with their location information.
  2. .desiredAccuracy – The desired accuracy property allows you to tell the device how accurate you would like the location information to be. This should be set based on your application’s needs. Don’t set this property to kCLLocationAccuracyBest if you only need to know what city they are in. NOTE: This is the “desired” accuracy, it is not guaranteed. The device will determine the best available information and provide it to you but you are not, however, guaranteed any level of accuracy.
  3. .distanceFilter – The distance filter property tells the location manager how far a device needs to move (horizontally vs. an altitude change) before triggering a new location event. It is measured in meters. You can set the property to kCLDistanceFilterNone to be notified of all events (this is also the default value).

The completed creation of our location manage looks like this:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];     // Override point for customization after application launch.     self.window.backgroundColor = [UIColor whiteColor];     [self.window makeKeyAndVisible];       if(self.locationManager==nil){         _locationManager=[[CLLocationManager alloc] init];         //I'm using ARC with this project so no need to release           _locationManager.delegate=self;         _locationManager.purpose = @"We will try to tell you where you are if you get lost";         _locationManager.desiredAccuracy=kCLLocationAccuracyBest;         _locationManager.distanceFilter=500;         self.locationManager=_locationManager;     }       return YES; }

If you run this now, you should not notice any change in the way your application runs, you also won’t start receiving location information just yet. That comes next…

Starting Location Services

Now that we have our location manager configured, we want to start getting the location. To start the standard location service, you should first check to make sure that location services are enabled. This is done with a simple call to [CLLocationManager locationServicesEnabled] so after we set up our location manager above and before the return YES;, add the following code:

    if([CLLocationManager locationServicesEnabled]){         [self.locationManager startUpdatingLocation];     }

NOTE: If location services are not enabled and you start updating location services, the user will be prompted to enable location services. This could be annoying to the end user if they have to answer “No” every time your app launches.

If you run your app now, you will notice that the user is prompted to enable location services (and it will include the message from the .prompt property of our location manager object).

EnableLocationServicesPrompt

Receiving Location Changes

We’ve started location services, but now we need to start receiving updates to location changes. This is all done through the CLLocationManagerDelegate protocol. There are a number of available methods to implement for this delegate but the three most important are probably:

  1. – locationManager:didUpdateToLocation:fromLocation:
  2. – locationManager:didFailWithError:
  3. – locationManager:didChangeAuthorizationStatus:

– locationManager:didUpdateToLocation:fromLocation:

Let’s start with receiving an update in location and how to handle that. In our App Delegate implementation file (.m), add the following method placeholder below the @synthesize … statements and above - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method:

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{   }

One of the first things I like to do is check the timestamp of the newLocation detected. When you first start updating location services, the location manager will receive the last known location of the device, this could be hours or days old depending on the last time location services were used. In my apps, I like to make sure that I have a recent location. This following code will only use a location that has been found in the last 15.0 seconds:

    NSDate* eventDate = newLocation.timestamp;     NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];     if (abs(howRecent) &lt; 15.0)     {         //Location timestamp is within the last 15.0 seconds, let's use it!     }

The next check that I like to perform is to see how accurate the newLocation is. This can be done by looking at the .horizontalAccuracy property. This property tells you how accurate your location information is. As I stated above, you can request to have very accurate locations but you are not guaranteed it. In the illustration below, the newLocation.coordinate is the location the device thinks it is, but in truth the orange circle of the .horizontalAccuracy says that it could be anywhere in that circle.

horizontalAccuracy

Your application’s need will determine how accurate of a location you need. Again, if you just need the city the user is in, you won’t need it to be as accurate as if you were trying to find something within walking distance. In the code below, I have set my accuracy threshold to 35.0 meters. This is pretty broad but I have found that it works well indoors as well as out. Insert the following code right after the comment //Location timestamp is within the last 15.0 seconds, let's use it!

        //Location timestamp is within the last 15.0 seconds, let's use it!         if(newLocation.horizontalAccuracy&lt;35.0){             //Location seems pretty accurate, let's use it!             NSLog(@"latitude %+.6f, longitude %+.6f\n",                   newLocation.coordinate.latitude,                   newLocation.coordinate.longitude);             NSLog(@"Horizontal Accuracy:%f", newLocation.horizontalAccuracy);               //Optional: turn off location services once we've gotten a good location             [manager stopUpdatingLocation];         }

The code above will print the new location to the console and then turn off location services. This is an optional step but if you don’t need location services anymore, it’s a smart thing to turn them off to conserve your user’s battery.

This is what our complete delegate method looks like:

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{     NSDate* eventDate = newLocation.timestamp;     NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];     if (abs(howRecent) &lt; 15.0)     {         //Location timestamp is within the last 15.0 seconds, let's use it!         if(newLocation.horizontalAccuracy&lt;35.0){             //Location seems pretty accurate, let's use it!             NSLog(@"latitude %+.6f, longitude %+.6f\n",                   newLocation.coordinate.latitude,                   newLocation.coordinate.longitude);             NSLog(@"Horizontal Accuracy:%f", newLocation.horizontalAccuracy);               //Optional: turn off location services once we've gotten a good location             [manager stopUpdatingLocation];         }     } }

Now we can run the project again. If you didn’t authorize the app to use location services before, go ahead and do that now. We haven’t done anything with the location at this point except print it out to the console. If you don’t know how to see the console, make sure Xcode is the active window (NOT the simulator) and press ??C

If you are running the project on the simulator and not a device, you may not see any results in the console window. This is because the simulator does not have location services turned on by default. You can simulate a location by selecting the location services simulation in the console window:

Simulate Location

You can also simulate a location in the Simulator by using the Debug menu.

Simulator Location Services

Once a location has been selected, you may need to restart the app to get the new location to show in the console window:

Location In Console

Because we built the location manager into the App Delegate, you can access the device’s current location anywhere in your code by including the AppDelegate header file (.h) in your view controller’s implementation file (.m):

#import "CFAAppDelegate.h"

Then whenever you need to access the location, you can use the following bit of code:

//Make sure location services are enabled before requesting the location if([CLLocationManager locationServicesEnabled]){       CFAAppDelegate *appDelegate=(CFAAppDelegate *)[UIApplication sharedApplication].delegate;     CLLocation *currentLocation=appDelegate.locationManager.location;       //Do what you want with the location... }

About: Shawn Grimes
Shawn is a mobile app developer for ELC Technologies. He is a co-author of the book, iOS 5 Recipes: A Problem-Solution Approach (Recipes Apress). You can follow him on twitter @shawng. Shawn also works with high school students to teach them app development skills through the APPlied Club Program.

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 &lt;UIActionSheetDelegate, UIAlertViewDelegate&gt;  {   	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

WP Like Button Plugin by Free WordPress Templates