Friday, 17 August 2012

Unzipping Files In iOS Using ZipArchive


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 zippedfiles. 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 http://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 Librariessection 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!

Wednesday, 8 August 2012

Methods for CUT, COPY n PASTE in any iPhone App.


// for cut operation

-(IBAction)cut {
  [self copy];
  textPad.text = @"";
}


// for copy operation

-(IBAction)copy {

        NSString *copyString = [[NSString alloc] initWithFormat:@"%@",[textPad text]];
        UIPasteboard *pb = [UIPasteboard generalPasteboard];
        [pb setString:copyString];
}

// for paste Operation

-(IBAction)paste {
        UIPasteboard *pb = [UIPasteboard generalPasteboard];
        textPad.text = [pb string];
}

Send Email With Attached Files from Iphone application


 step 1 :

- add MessageUI framework

step 2 :

 #import "MessageUI/MessageUI.h" 

- add MFMailComposeViewControllerDelegate to .h file

step 3 :

- code in .m file on an clicked event of send Button

 if ([MFMailComposeViewController canSendMail])
        {
            // csv file path details for attachments
            NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
            NSString *documentsDirectory = [paths objectAtIndex:0];
            NSString *filename =@"test.csv";
            NSString *fullPathToFile = [documentsDirectory stringByAppendingPathComponent:filename];
            NSData *myData = [NSData dataWithContentsOfFile:fullPathToFile]; 
            
            // pdf file path details for attachments
            NSString *filename1 =@"NewPDF.pdf";
            NSString *pdfPath = [documentsDirectory stringByAppendingPathComponent:filename1];
            NSData *myData1 = [NSData dataWithContentsOfFile:pdfPath];
            

            
            MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
            mailer.mailComposeDelegate = self;
            
            NSMutableArray *arr = [[NSMutableArray alloc]init];
            [arr addObject:emailText.text];
            [mailer setToRecipients:arr];
            
            [mailer setSubject:@"Vehicle Expenses from myConsultant"];
            
            NSString *emailBody = @"";
            [mailer setMessageBody:emailBody isHTML:NO];
            
            [mailer addAttachmentData:myData mimeType:@"text/csv" fileName:filename];
            [mailer addAttachmentData:myData1 mimeType:@"text/pdf" fileName:filename1];
            
            [self presentModalViewController:mailer animated:YES];
            
            [mailer release]; 
        }
        else
        {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Failure"
                                                            message:@"Your device doesn't support the composer sheet"
                                                           delegate:nil
                                                  cancelButtonTitle:@"OK"
                                                  otherButtonTitles:nil];
            [alert show];
            [alert release];
        }

    }

step 4 : // add delegate method anywhere in .m class file

- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{ 
    // Notifies users about errors associated with the interface
    switch (result)
    {
        case MFMailComposeResultCancelled:
            break;
        case MFMailComposeResultSaved:
            break;
        case MFMailComposeResultSent:
            break;
        case MFMailComposeResultFailed:
            break;
            
        default:
        {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Email" message:@"Sending Failed - Unknown Error :-("
                                                           delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];
            [alert show];
            [alert release];
        }
            
            break;
    }
    [self dismissModalViewControllerAnimated:YES];
}



Only the thing is that you have a file available on a path you given for attachment 

so enjoy Love coding, iCoding 




Wednesday, 1 August 2012

How to use NSAttributedString in iOS 6


infoString
=@"This is an example of Attributed String";

NSMutableAttributedString *attString=[[NSMutableAttributedString alloc] initWithString:infoString];
NSInteger _stringLength=[infoString length];

UIColor *_black=[UIColor blackColor];
UIFont *font=[UIFont fontWithName:@"Helvetica-Bold" size:30.0f];
[attString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, _stringLength)];
[attString addAttribute:NSForegroundColorAttributeName value:_black range:NSMakeRange(0, _stringLength)];



               






UIColor *_red=[UIColor redColor];
UIFont *font=[UIFont fontWithName:@"Helvetica-Bold" size:72.0f];
[attString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, _stringLength)];
[attString addAttribute:NSStrokeColorAttributeName value:_red range:NSMakeRange(0, _stringLength)];
[attString addAttribute:NSStrokeWidthAttributeName value:[NSNumber numberWithFloat:3.0] range:NSMakeRange(0, _stringLength)];















UIColor *_red=[UIColor redColor];
UIFont *font=[UIFont fontWithName:@"Helvetica-Bold" size:72.0f];
[attString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, _stringLength)];
[attString addAttribute:NSStrokeColorAttributeName value:_red range:NSMakeRange(0, _stringLength)];
[attString addAttribute:NSStrokeWidthAttributeName value:[NSNumber numberWithFloat:-3.0] range:NSMakeRange(0, _stringLength)];












UIColor *_red=[UIColor redColor];
UIColor *_green=[UIColor greenColor];
UIFont *font=[UIFont fontWithName:@"Helvetica-Bold" size:72.0f];
[attString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, _stringLength)];
[attString addAttribute:NSForegroundColorAttributeName value:_green range:NSMakeRange(0, _stringLength)];
[attString addAttribute:NSStrokeColorAttributeName value:_red range:NSMakeRange(0, _stringLength)];
[attString addAttribute:NSStrokeWidthAttributeName value:[NSNumber numberWithFloat:-3.0]range:NSMakeRange(0, _stringLength)];














UIColor *_green=[UIColor greenColor];
UIFont *font=[UIFont fontWithName:@"Helvetica-Bold" size:72.0f];

NSShadow *shadowDic=[[NSShadow alloc] init];
[shadowDic setShadowBlurRadius:5.0];
[shadowDic setShadowColor:[UIColor grayColor]];
[shadowDic setShadowOffset:CGSizeMake(0, 3)];
              
[attString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, _stringLength)];
[attString addAttribute:NSForegroundColorAttributeName value:_green range:NSMakeRange(0, _stringLength)];
[attString addAttribute:NSShadowAttributeName value:shadowDic range:NSMakeRange(0, _stringLength)];
                



















UIColor *_red=[UIColor redColor];
UIFont *font=[UIFont fontWithName:@"Helvetica-Bold" size:72.0f];
[attString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, _stringLength)];
  [attString addAttribute:NSForegroundColorAttributeName value:_red range:NSMakeRange(0, _stringLength)];              
  [attString addAttribute:NSKernAttributeName value:[NSNumber numberWithInt:5] range:NSMak








UIColor *_red=[UIColor redColor];
UIFont *font=[UIFont fontWithName:@"Helvetica-Bold" size:30.0f];
[attString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, _stringLength)];
[attString addAttribute:NSForegroundColorAttributeName value:_red range:NSMakeRange(0, _stringLength)];
[attString addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInt:2] range:NSMakeRange(0, _stringLength)];








UIColor *_blue=[UIColor blueColor];
UIColor *_blueL=[UIColor colorWithRed:0 green:0 blue:0.5 alpha:0.7];
UIFont *font=[UIFont fontWithName:@"Helvetica-Bold" size:30.0f];
                
[attString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, _stringLength)];
[attString addAttribute:NSForegroundColorAttributeName value:_blue range:NSMakeRange(0, _stringLength)];
[attString addAttribute:NSBackgroundColorAttributeName value:_blueL range:NSMakeRange(0, 20)];