Pages

Showing posts with label iPhone. Show all posts
Showing posts with label iPhone. Show all posts

Wednesday, February 1, 2012

[Code Snippet] Read application bundle identificator from plist.

Hi mates!!

A lot of work, so as usually we have not time to update the blog as we want, but today's we've get 5 free minutes to post a new code snippet.

I know, because I just tried to do it, that most of you have tried to read application bundle Id from the plist asi usual, getting the path to the plist file, obtaining its values and getting the correct key.

There's a shorter way to accomplish that, just using NSBundle infoDictionary property that returns us the values stored in our Project-Info.plist.


        NSString* appID = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];

I hope this will be useful for everyone, but now I may continue developing. Turning back to my XCode!

Regards!

Thursday, January 12, 2012

New iphone apps

We have released to app store two new apps based on geolocated photography and oriented to hunting and fishing fans.

First of both was Hunting Log, in which you can store geolocated photos of your hunted pieces and share it with your friends via Twitter and Facebook.

Fisherman's Log has the same functionallity but oriented to fishing lovers.

You can find more info about these apps and our complete portfolio for iOS, Android and Windows Phone in our website: www.fiveflamesmobile.com

Aborting performSelectorInBackgroud:withEvent

First of all, happy 2012. Our best wishes to all of our readers in this new year.

Once again we have to apologize our readers for the lack of updates, but we have a lot of work, maybe there will be some changes in our work and we don't have so much time to update the blog.

Today's entry is not a code snippet as usual, is a little trick for when we are performing any task in background and we want to cancel it. For example, I want to accomplish it when a user taps back button during an array data loading performing in background.

The only way to abort a background task is to define a class boolean variable accesible for any method.

BOOL cancelBackgroundTask

set it to NO when you lauch the task

cancelBackgroundTask = NO;
[self performSelectorInBackground:@selector(bgTask) withObject:nil];

If the user makes any action that should abort the background task, just change the boolean value

cancelBackgroundTask = NO;

And at last, in background task you have to check this variable periodically with an NSTimer or a worse approach but maybe usefull is to check it before perform any action.

if (!cancelBackgroundTask)
    [self loadData];

if (!cancelBackgroundTaks)
    [self presentData];

In this easy way you could abort a background task. This derived of the lack of a function to abort or cancel directly a thread.

I hope this help, enjoy it!

Thursday, December 15, 2011

[Code Snippet] Rounded corners for UIView

We are very sorry about the lack of updates for the block, but now we are overloaded of projects and have no much time to write new posts :(

Here is a little and useful code snippet to round the corners of any UIView (UIWebView, UIImageView, etc...)

You have just to link your binaries with QuartzCore library and import it in the .h file.

#import <QuartzCore/QuartzCore.h>

And in .m file, you have to use this code snippet to round the corners. In the examble I've did it with a UIImageView

[imgView.layer setBorderColor:[UIColor blackColor].CGColor];
[imgView.layer setBorderWidth:1.0f];
                    
[imgView.layer setCornerRadius:10];
[imgView setClipsToBounds:YES];

With this four lines of code, you'll give your app a better look and feel.

Enjoy it!!

P.S. Don't forget to visit our web to see a complete catalogue of our apps.

Wednesday, November 16, 2011

[Code Snippet] Accesing to SSL server trust web services

This code snippet completes the two previous post that says how to connect to a REST service and consume it synchronous and asynchronously.

When we have to access a HTTPS web service first thing that we should think is how to store the trusted root certificate in our iPhone or iPad. Our device has installed some of the most used certificates (you can check the list here) and for this snippet we asume that the server uses Verisign, GoDaddy or any other common SSL certificate, so we have yet installed it.

To accomplish this task you should implement the next functions of NSURLConnection delegate:


- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection
{
    return TRUE;}
-(void)connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    NSLog(@"Challenge cancelled");}
-(BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
   // Server Trust authentication method
    return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
  
    //Here we told the OS that validate the server certificate against our credential storage.
    [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];       
    NSLog(@"Reto superado");}

If we just want to bypass the authentication, instead of useCredential, we should use continueWithoutCredential method in didReceiveAuthenticationChallenge.

    //Bypass without credentials
    [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];

I hope this code snippet could be useful for you, enjoy it!

NOTE: This can be used only with NSURLConnection, just for asynchronous request.

Thursday, October 13, 2011

[Code Snippet] Geolocating photos with reverse geocoding.

Sometimes you have an app which takes a photo, and you want to geolocate it obtaining current latitude, longitude and altitude from the GPS, but generally for the user this info is not useful, it has not a Reverse Geocoder in its brain so the user should prefer to see a name than three numbers.

In this code snippet we're going to se how to accomplish this.

First thing to do is to add the required frameworks to our app.

CoreLocation Framework
MapKit Framework

Next, in your .h file you have to import these frameworks and implement the protocols that we need.

#import <corelocation corelocation.h>
#import <mapkit mapkit.h>

@interface geolocatingPhotoViewController : UIViewController <UIImagePickerControllerDelegate,  CLLocationManagerDelegate, MKReverseGeocoderDelegate>

Let's take the photo with UIImagePickerController and when we've token it, we call CLLocationManager to get our position.

UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init]; imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentModalViewController:imagePicker animated:YES];
[imagePicker release]; 

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo {
self.imageViewCaptura.image = image;
[picker dismissModalViewControllerAnimated:YES];
CLLocationManager * locationManager = [[CLLocationManager alloc] init]; locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; [locationManager startUpdatingLocation];
}

Once we have our image stored in a UIImageView and we have to wait the CLLocationManager to get our position coordinates. When we have it, we stop the location and call the reverse geocoding to start getting the location name.

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
[locationManager stopUpdatingLocation];
[locationManager release];
capture.longitude = newLocation.coordinate.longitude;
capture.latitude = newLocation.coordinate.latitude;
capture.altitude = newLocation.altitude;

CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(capture.latitude, capture.longitude);
MKReverseGeoCoder *reverserGeoCoder = [[MKReverseGeocoder alloc] initWithCoordinate:coordinate];
reverserGeoCoder.delegate = self; 
[reverserGeoCoder start];
}

At last, if MKReverseGeoCoder was able to get the coordinates info, we only has to get the data and show it.
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark {
if (placemark)
{
NSString *strLocation = [NSString stringWithFormat:@"%@, %@ (%@)", placemark.locality, placemark.administrativeArea, placemark.country]; self.textFieldLocation.text = strLocation;
}
NSLog(@"Location info: %@", strLocation );
}

We should control if GKReverseGeocoder wasn't able to retrieve our position information implementing didFailWithError function.

And that's all, now you know how to present location info to the user when it takes a photo.

Enjoy it!

Thursday, October 6, 2011

[Code Snippet] Send GET and POST data to web services asynchronously.

Last post talks about sending post and get values to a web service synchronously using NSURLConnection sendSynchronousRequest:(NSURLRequest)request method. Today we'll explain how to do the same request but asynchronously in background.

Firstly, we have to declare some instance variables:


    NSURLConnection *urlConnection;
    NSURL *loginURL;
    NSMutableData *responseData;


The initial code is like synchronous method, we have to prepare the NSURL object, and load the NSMutableURL object with the URL, the parameters and setting the correct headers value.

NSURL *url = [NSURL urlWithString:@"http://www.fiveflamesmobile.com/login.php?from=mobile"];
NSString *formValues = [NSString stringWithFormat:@"name=%@&device=%@", @"FiveFlames", @"iPhone"];
NSData *formData = [formValues dataUsingEncoding:NSUTF8StringEncoding];
[urlRequest setHttpBody:formData];

And now, instead of invoke sendSynchronousRequest method, we have just to initialize the NSURLConnection object with our request and set the delegate to the class that implements the delegate methods, in this case, our class.


urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

And now we've just to implement the delegate methods. You haven't to put any protocol declaration in .h file.

Basic methdos to implement are:

Will send request is invoked just before to send the request, and we keep the "real" URL stored in our class variable.

- (NSURLRequest *)connection:(NSURLConnection *)connection
             willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse
{
    [urlConnection release];
    urlConnection =  [[request URL] retain];
    
    NSLog(@"URL Recibida: %@:", [[request URL] absoluteString]);
    
    return request;
}

If we have store some data into NSURLRequest HttpBody property, this method will be invoked just after have sent them.

- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
{
    NSLog(@"Petición enviada");
}


The method didFailWithError is invoked when the NSURLConnection fails so is time to check the error.

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"Error: %@", [error description]);    
}

The method didReceiveResponse is invoked when the server and the client establish the connection, so we have to initialize here the container in which the response will be saved.

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    responseData = [[NSMutableData alloc] init];
    [responseData setLength:0];   
}

This method is invoked when data is received (obviously). If the amount of data is small, it will be invoked once, but if the amount of data is big, this method will be invoked repeatedly. We just to add the received data to the container.

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [responseData appendData:data];
    NSLog(@"Data sin decodificar: %@", data);
}


At last, connectionDidFinishLoading is invoked when the response is totally stored in our variable, so now it's time to log it, parse it or do whatever you want to do with it.

- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{
    //Log de la respuesta para depuración
    
    NSString *strResponse = [[NSString alloc] initWithBytes:[responseData bytes]
                                                     length:[responseData length
                                                   encoding:NSUTF8StringEncoding];
    NSLog(@"\n--------- Received Response ---------\n");
    NSLog(@"%@", strResponse);
    NSLog(@"\n--------- End of received response ---------\n");
    
    [strResponse release];
    
}

This is a very basic implementation of an asynchronous request.  We'll try to show you how to make SSL asynchronous connections, but we reserve it for another post.

Enjoy the code!

Friday, September 23, 2011

[Code Snippet] Send GET and POST data to web services.

It has been two weeks with a lot of work and a seriously lack of time to update the blog, but we are back again.

This week code snippet is about sending data to web services, XML and JSON are most used technologies used today but maybe some of your has to send data to an older php web page that receives data from a form by GET, POST or both of them. How could we accomplish that?

Let's see a code snippet to do it synchronously, later we'll publish a new entry with the asynchronous method.

First thig to do is to create the NSURL object which we are going to make the request to. If it has any GET parameters we should put them in the URL String.

NSURL *url = [NSURL urlWithString:@"http://www.fiveflamesmobile.com/login.php?from=mobile"];

After that we have to create a NSMutableURLRequest in order to put the post parameter.

NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setHttpMethod:@"POST"];

And now we only have to put in the HTTPBody the form variables as URL encoding like "key1=value1&key2=value2..." as a NSData object.

NSString *formValues = [NSString stringWithFormat:@"name=%@&device=%@", @"FiveFlames", @"iPhone"];
NSData *formData = [formValues dataUsingEncoding:NSUTF8StringEncoding];
[urlRequest setHttpBody:formData];

And now, we only just to make the request and save the response.

NSURLResponse *response;
NSError *error;

NSData *responseData = [NSURLConnection sendSynchronousRequest:urlRequest response:&response error:&error];

NSLog (@"Response: %@", responseData);

That's all, with this code snippet you could keep your older php or asp pages and reuse it to develop a server-client iOS app.

Enjoy it!

Wednesday, August 24, 2011

[Code Snippet] Custom UINavigationBar back button

Back from my holidays, I come back with my weekly wednesday's code snippet.

Sometimes when we work with UINavigationcontroller we want to custom the back button for a more visual image, or just an arrow. Today let's see how to create a custom back button with our own image for the UINavigationBar.

First of all, you have to implement in viewDidLoad the next piece of code

    if ([self.navigationController.viewControllers count] > 1)
    {
        //Creating our custom back button
        UIButton *home = [UIButton buttonWithType:UIButtonTypeCustom];
        [home setTitle:@"Volver" forState:UIControlStateNormal];
       
        UIImage *homeImage = [UIImage imageNamed:@"backbutton.png"];
       
        [home setBackgroundImage:homeImage forState:UIControlStateNormal];
        home.frame = CGRectMake(0, 0, 80, 30);
       
        [home addTarget:self action:@selector(cancel:) forControlEvents:UIControlEventTouchUpInside];
       
        UIBarButtonItem *cancelButton = [[[UIBarButtonItem alloc]
                                          initWithCustomView:home] autorelease];
        self.navigationItem.leftBarButtonItem = cancelButton;
    }
After that, we just have to implement the selector to pop the view controller and back to the previous one:

-(IBAction)cancel:(id)sender{
    [self.navigationController popViewControllerAnimated:YES];
}
And that's all. Now you can improve your UI with a custom back button. Enjoy it

Thursday, August 4, 2011

[Code Snippet] Dynamic height for UITableViewCell

Hi there, let's see a new code snippet this week that's very useful when we are loading dinamic text in UITableView cells and we don't know which its exactly lenght is, so we have to adapt both UILabel and UITableViewCell height.

First thing to do is calculate the UITableViewCell height inside heightForRowAtIndexPath:(NSIndexPath)indexPath. That's the first of the two methods that we have to implement for UITableViewDataSource protocol in order to calculate the total of cell height. Be careful because you have to add all cell heights for any control that are docked vertically.

Obtaining the text size of the label is quite easy, we only have to specify the label widht, the font size, line break mode and text content, and we'll obtain a CGSize variable storing the label size.
   
    CGSize labelSize = CGSizeMake(labelWidth, 20000.0f);
    CGSize textSize = [@"Lorem ipsum dolor" sizeWithFont:[UIFont systemFontOfSize: 12.0f] constrainedToSize:labelSize lineBreakMode:UILineBreakModeWordWrap];
   
    cellHeight = textSize.height + 21.0f + 30; //Adding other control heights
   
    return cellHeight;
Next, you have to implement cellForRowAtIndexPath method for dinamic resizing of the UILabel which shows our text. Using the same method described before you can set label's frame to show text completely.

    UILabel *textDescription = (UILabel*)[cell viewWithTag:3];
    textDescription.text = @"Lorem ipsum dolor...";
    CGSize labelSize = CGSizeMake(labelWidth, 20000.0f);
    CGSize textSize = [rssItem.descripcion sizeWithFont:[UIFont systemFontOfSize: 12.0f] constrainedToSize:labelSize lineBreakMode:UILineBreakModeWordWrap];
    [txtDescripcion setFrame:CGRectMake(13.0f, 45.0f,
                                          labelWidht, textSize.height)];

And that's all to dynamic resizing of UILabels and UITableViewCells for show unknow length text. I hope this had helped you

NOTE: A good practise is to have the label widht defined as a constant, in our case labelWidth.

Thursday, July 28, 2011

[Code Snippet] Add UIButton programatically

I have not so much time to update the blog, but I have to maintance the wednesday's code snippet so today's code snippet is about one of those things that are very easy to do, but difficult to remember: add a UIButton programatically to our view.

To add a basic UIButton programatically, just instance it, give it a frame and obviously a selector for the TouchInside (click) event, and that's all.

Code snippet is like that

UIButton *myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[myButton addTarget:self
           action:@selector(myButton_click:)
 forControlEvents:UIControlEventTouchDown];
[myButton setTitle:@"My title" forState:UIControlStateNormal];
myButton.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
[view addSubview:myButton];

- (IBAction) myButton_click:(id)sender
{
    NSLog(@"Button clicked");
}

Good programming!!!!

Wednesday, July 20, 2011

[Code Snippet] Scheduling local notifications

Sometimes we want to create an app that notifies the user some information when a selected date/time is reached, for that reason Apple included local notifications since iOS 4.1

The use of local notifications is much easier than PUSH notifications, that needs to implement a server-side web app for sending PUSH notifications through Apple Push Notification (APN) service.

To use local notifications, you only have to instantiate NSLocalNotification class, set it's fire date and time, its message, sound and any other fields that you could need and schedule it in local notification scheduler, and iOS do the rest for you.

Here is a sample code

UILocalNotification *localNotif = [[UILocalNotification alloc] init];

if (localNotif == nil)
     
return;

localNotif.fireDate = itemDate;
localNotif.timeZone = [NSTimeZone defaultTimeZone];

// Set the action button
localNotif.alertAction = @”View”
//This sets the alert text to the current text in the textfield.

localNotif.alertBody = @"Charle's birthday";

//This sets the sound name of the notification.
localNotif.soundName = UILocalNotificationDefaultSoundName;

//You can also set the badge number of the application.
localNotif.applicationIconBadgeNumber = 1;

// Schedule the notification
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];

[localNotif release];

I hope this could be useful for you, enjoy it!!

Wednesday, July 13, 2011

[Code Snippet] Store a NSArray of custom objects into NSUserDefaults

We're  back from holidays, it has been two weeks without updates, so now it's time for doing it.

Sometimes we have to cache some kind of information, or store it easily because we don't need to make searches on them, just we want to recover ir quickly. In this case using SQLite for local storage is a big solution for a little problem, and store the information as a XML based file lead us to write a serializer and a custom XMLParser, so the best option to accomplish that is store it in NSUserDefaults.

Maybe you have already stored basic information like NSString or NSNumber objects in user defaults, so you know that it is an easy way to store a NSObject into a NSDictionary.

But maybe you want to store a little array of information, for example a little shop list with identification number, and description, so you have created a object like this.

@interface ShopItem : NSObject
{
        int numberID;
        NSString *description;
}

@property (nonatomic, assign) int numberID;
@property (nonatomic, retain) NSString *description;

@end

So, how could we store a NSArray containing some of this objects into NSUserDefaults? Store the NSArray object into NSUserDefaults as usually cause our app to crash, so we have to serialize and deserialize the NSArray of custom objects implementing NSCoding protocol in our custom NSObject to encode key-value pairs for each property of our custom object.

@interface ShopItem : NSObject <NSCoding>
{
        int numberID;
        NSString *description;
}

@property (nonatomic, assign) int numberID;
@property (nonatomic, retain) NSString *description;

@end
@implementation ShopItem

@synthesize number, description, shoppingDate;

- (void)encodeWithCoder:(NSCoder *)coder;
{
    [coder encodeObject:description forKey:@"description"];
    [coder encodeInteger:numberID forKey:@"numberID"];
}

- (id)initWithCoder:(NSCoder *)coder;
{
    self = [[ShopItem alloc] init];
    if (self != nil)
    {
        description = [coder decodeObjectForKey:@"description"];
        numberID = [coder decodeIntegerForKey:@"numberID"];
    }  
    return self;
}

@end

Once we have implemented NSCoding protocol in the custom object, we are able to store our NSArray in NSUserDefaults like that

[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:objectArray] forKey:@"savedArray"];

To retrieve our NSArray again, we should recover the NSArrayObject from NSUserDefaults, check that it's not nil (be careful, if you try to decode a nil array, you'll get an EXC_BAD_ACCESS exception) and unarchive it.

NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:@"savedArray"];
if (dataRepresentingSavedArray != nil)
{
        NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray];
        if (oldSavedArray != nil)
                objectArray = [[NSMutableArray alloc] initWithArray:oldSavedArray];
        else
                objectArray = [[NSMutableArray alloc] init];
}

With this pieces of code, you could store and retrieve little sets of information in your NSUserDefaults local storage.

I hope this helps you.

Wednesday, June 22, 2011

[Code Snippet] Playing video streaming in our iPhone App

Hi there. Today's code snippet is another easy one, just for playing video streaming embedded in our app using Media Player Framework.

First thing to do is to import the headers that we need

#import <MediaPlayer/MediaPlayer.h>

After that we'll have to instantiate the MPMoviePlayerController and add it as a subview to our actual view. We could set the MPMoviePlayer controller frame, to get a full screen player or not.


MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL:
                                            [NSURL URLWithString:@"http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"]];
   
    [player.view setFrame: self.view.bounds];  // player's frame must match parent's
    [self.view addSubview: player.view];
   
    [player prepareToPlay];
    [player play];

Two things to take care:

First one: Take care about the supported stream formats for iOS, if the video streaming is not played maybe because the streaming is not transmitted in the correct formats. Review the stream formats and the best practices for iOS streaming here

Second one: Video player is another control yet, so you can add controls onto it like UILabels, UIButtons and make your streaming a bit interactive for the user. Just add the control with addView method and you can use it.

I hope this code snippet could be useful for you. Now I'm inmersed into interoperability between Microsoft Azure cloud computing framework and iPhone so it's possible that in a few weeks there are some articles about that.

Wednesday, June 15, 2011

[Code Snippet] Implementing UIActionSheets

This week code snippet is about how to implement UIActionSheet in our UIViewController to present actions like a context menu. Like my previous post, this is so easy but have it previously implemented could save us some valious time.

To show the UIActionSheet, instance UIActionSheet and show it with this piece of code.

UIActionSheet *popupQuery = [[UIActionSheet alloc] initWithTitle:@"Share" delegate:self cancelButtonTitle:@"Cancelar" destructiveButtonTitle:nil otherButtonTitles:@"Facebook", @"Twiter", @"E-mail", nil];
        popupQuery.actionSheetStyle = UIActionSheetStyleBlackOpaque;
   
    [popupQuery showInView:self.view];
    [popupQuery release];

Cancel button will hide our action sheet when is pushed, destructive button will appear in red background and any other button will appears as normal. Both, destructive and the other buttons behaviour has to be declared implementing UIActionSheetDelegate clickedButtonAtIndex.


-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
     if (buttonIndex == 0) {
       
         NSLog(@"Button Facebook clicked");

    } else if (buttonIndex == 1) {
       
        NSLog(@"Button Twitter clicked");;

    } else if (buttonIndex == 2) {

        NSLog(@"Button Email clicked");
       
    }
}

With this piece of code you can implement a context menu like behaviour in your view. Take note that you have not to implement cancel button index click behaviour.





I hope this code snippet helps you, enjoy it!!!

Wednesday, June 8, 2011

[Code Snippet] Sending emails from our app with MessageUI framework

Hello everybody, I've been very busy last days, too much work, so this week I'll bring you an easy code snippet that everybody should know but could be useful to have it here for cut & past simply.

When we want to use the iOS' email composer from our app, first thing to do is to link MessageUI framework with our binaries, and obviously import it in our header file.

#import <MessageUI/MessageUI.h>

For using it, you have to implement in your class the MFMailComposeViewControllerDelegate

@interface MyViewController : UIViewController <MFMailComposeViewControllerDelegate>

After that, to invoke the MFMailComposer is so easy, just instance it and preload all the email fields that you want: To, cc, bcc, subject... and present it as a modal view controller. Don't forget setting the mailComposeDelegate property to the class which implements MFMailComposeViewControllerDelegate, usually the same class that invokes MFMailComposeViewController.:

    MFMailComposeViewController *mailView = [[MFMailComposeViewController alloc] init];
    mailView.mailComposeDelegate = self;
    mailView.navigationBar.tintColor = [UIColor colorWithRed:0.36078431 green:.015686275 blue:.0078431373 alpha:1];
    [mailView setToRecipients:[NSArray arrayWithObject:@"fiveflamesmobile.blogspot.com"]];
   
    [self presentModalViewController:mailView animated:YES];
   
    [mailView release];

After those steps we have to implement de MFMailComposrDelegateProtocol as this:

#pragma mark -
#pragma mark MFMailComposeViewControllerDelegate

- (void) mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
    [self dismissModalViewControllerAnimated:YES];
   
    UIAlertView *alert = nil;
   
    if (result == MFMailComposeResultSent)
    {
        alert = [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"EmailEnviado", "") message:NSLocalizedString(@"EmailExito", "") delegate:self cancelButtonTitle:NSLocalizedString(@"Aceptar", "") otherButtonTitles:nil] autorelease];
       
    } else if (result == MFMailComposeResultSaved) {
       
        alert = [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"EmailGuardado", "") message:NSLocalizedString(@"EmailBorradores", "") delegate:self cancelButtonTitle:NSLocalizedString(@"Aceptar", "") otherButtonTitles:nil] autorelease];
       
    } else if (result == MFMailComposeResultFailed) {
       
        alert = [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"EmailNoEnviado", "") message:NSLocalizedString(@"EmailFallo", "") delegate:self cancelButtonTitle:NSLocalizedString(@"Aceptar", "") otherButtonTitles:nil] autorelease];
    }
   
    [alert show];
}

Be careful, I've user localizated string to show the message in the alert view, but maybe I'll write about that in next code snippets. And with this few lines of code you will be able to send emails with the iOS mail client.

So that's all for today. More and better (I'll try it) the next week.

Wednesday, June 1, 2011

[Code Snippet] When keyboard shows...

Sometimes we have a lot of UITextField controls in our UIView, but what happends when the keyboard is shown??? The UITextFields that are at the bottom of the UIView are hidden behind the keyboard and users don't know what they're writing.

Today's code snipett tries to help the developer to avoid this issue. What we shall do is to move the UIView up when keyboard shows and move it down again when keyboards hides. To accomplish that we have tu use observers,  and implement the two methods that will be called when keyboards shows and hides.

First, we have to add the observers to NSNotificationCenter default center for the events of showing and hiding the keyboard Implements this in viewDidLoad method.

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
 After that we implement both methods. We have to calculate the height at our hidden UITextField is, for adding or substract it from view's frame origin in order to move the UIView up and down. If we have more than one UITextField controls we shall to detect which is the first responder and sets the position accord to it.

- (void) keyboardWillShow: (NSNotification*) aNotification;
{   
    int position = 0;
   
   
    if ([textField1 isFirstResponder])
        position = 100;
    else if ([textField2 isFirstResponder])
        position = 150;
           
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];
    CGRect rect = [[self view] frame];
    rect.origin.y -= position;
    [[self view] setFrame: rect];
    [UIView commitAnimations];
   
}

- (void) keyboardWillHide: (NSNotification*) aNotification;
{
    int position = 0;
   
   
    if ([textField1 isFirstResponder])
        position = 100;
    else if ([textField2 isFirstResponder])
        position = 150;
   
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];
    CGRect rect = [[self view] frame];
    rect.origin.y += position;
    [[self view] setFrame: rect];
    [UIView commitAnimations];
}

And with this code snippet you will have a professional application that provides a good user experience and an animated interface when editing.

Enjoy it!

Sunday, May 29, 2011

[iPhone-app] Valladolid WiFi

Valladolid WiFi is a smart utility application which helps the user to look for public WiFi access points located in Valladolid. From tourist to Valladolid citizens they could use the applications for find a public wifi in a pub, hotel or university and get connected.

At the moment there is only Valladolid WiFi at app store, but we are looking for people who wants to bring this application to their city all over the world. We only need that people send us the name, address and location of their business whith public WiFi and we'll put it into the application database (we need a minimum of 15 WiFi point to launch a city personalized app) and it's for FREE.

If you are interested, please contact me: fiveflamesmobile@gmail.com

Name: Valladolid WiFi
Language: Spanish
Category: Utilities
Cost: Free

Valladolid WiFi AppStore Link

Wednesday, May 25, 2011

[Code Snippet] Custom UINavigationItem title

Last week I was working in an iPhone navigation based project, the customer wanted to have its own corporative colors in the application, and for the UINavigationBar too.

There was no problem with whole color for buttons and bar, using the UINavigationBar tintColor proprerty I set the desired color, but when the UINavigationItem title time becomes it was more difficult. We have to forget the UINavigationItem title proprerty and work with titleView one. This proprerty can be fulfilled with any UIView object, in my case I used a UILabel, but I have to set a different titleView for my different UIViewControllers so I encapsulated this in the function that I make available for you.

+ (UILabel*) labelForNavigationItem:(NSString*)text
{
   
   
    UILabel *titleView = [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 120, 30)] autorelease];
    [titleView setFont:[UIFont boldSystemFontOfSize:16.0]];
    titleView.backgroundColor = [UIColor clearColor];
    titleView.textAlignment = UITextAlignmentCenter;
    titleView.textColor  = [UIColor colorWithRed:.80784314 green:.77647079 blue:.50980392 alpha:1.0];
    titleView.textColor = [UIColor whiteColor];
    titleView.text = text;
   
    return titleView;
}
And assign the corresponding proprerty on viewDidLoad function

self.navigationItem.titleView = labelForNavigationItem:@"Menu";
That's all.

But at last I found a problem that I wasn't able to accomplish. I want to keep the standard UINavigationController backButton, but how could I change its font color? I think its no possible (at least without using an image), but if someone has any answer I would be grateful.

Enjoy it!

Wednesday, May 18, 2011

[Code Snippet] Hex Color (HTML) to "iOS RGB"

Most of the available applications at mobile markets are games or marketing apps, so our customers wants a very visual interface, an interface which attract the potential users or only embed the corporation logo and colours into the app's look & feel.

But most of developers have one handicap: We don't know about graphic design, color combination and logo designs, although some customer don't take care about that, so we have to work with a designer which makes all that graphic work. In most cases the designer give us the colors in RGB mode (0-255), so we have to convert them to "Mac RGB" (0 to 1) dividing each value between 255. But, what happends when the designer give us the colors on hexadecimal (HTML) coding?.

Today's code snippet tries to solve that with this little function that you can use to convert from hexadecimal to "MAC RGB" whith only a call.


+ (UIColor *) colorWithHexString: (NSString *) stringToConvert
{
NSString *cString = [[stringToConvert stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString];

// String should be 6 or 8 characters
if ([cString length] < 6) return DEFAULT_VOID_COLOR; // strip 0X if it appears if ([cString hasPrefix:@"0X"]) cString = [cString substringFromIndex:2]; if ([cString length] != 6) return DEFAULT_VOID_COLOR; // Separate into r, g, b substrings NSRange range; range.location = 0; range.length = 2; NSString *rString = [cString substringWithRange:range]; range.location = 2; NSString *gString = [cString substringWithRange:range]; range.location = 4; NSString *bString = [cString substringWithRange:range]; // Scan values unsigned int r, g, b; [[NSScanner scannerWithString:rString] scanHexInt:&r]; [[NSScanner scannerWithString:gString] scanHexInt:&g]; [[NSScanner scannerWithString:bString] scanHexInt:&b]; return [UIColor colorWithRed:((float) r / 255.0f) green:((float) g / 255.0f) blue:((float) b / 255.0f) alpha:1.0f]; }




I stole this piece of code from this Ars Tecnica's article where you could find more about UIColor conversions in.

Enjoy it!