Sunday, October 19, 2014

NSURLSession in iOS 7.0


NSURLSession:
=============

 NSURL *URL = [NSURL URLWithString:@"http://example.com"];
 NSURLRequest *request = [NSURLRequest requestWithURL:URL];

 [NSURLConnection sendAsynchronousRequest:request
                                    queue:[NSOperationQueue mainQueue]
                        completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
     // ...
 }];

 -------------------------------------------------------------------------

Data tasks can be created with either an NSURL or NSURLRequest (the former being a shortcut for a standard GET request to that URL):


 NSURL *URL = [NSURL URLWithString:@"http://example.com"];
 NSURLRequest *request = [NSURLRequest requestWithURL:URL];

 NSURLSession *session = [NSURLSession sharedSession];
 NSURLSessionDataTask *task = [session dataTaskWithRequest:request
                                         completionHandler:
     ^(NSData *data, NSURLResponse *response, NSError *error) {
         // ...
     }];

 [task resume];

 -------------------------------------------------------------------------

Upload tasks can also be created with a request and either an NSData object for a URL to a local file to upload:


 NSURL *URL = [NSURL URLWithString:@"http://example.com/upload"];
 NSURLRequest *request = [NSURLRequest requestWithURL:URL];
 NSData *data = ...;

 NSURLSession *session = [NSURLSession sharedSession];
 NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request
                                                            fromData:data
                                                   completionHandler:
     ^(NSData *data, NSURLResponse *response, NSError *error) {
         // ...
     }];

 [uploadTask resume];


 -------------------------------------------------------------------------

Download requests take a request as well, but differ in their completionHandler. Rather than being returned all at once upon completion, as data and upload tasks, download tasks have their data written to a local temp file. It’s the responsibility of the completion handler to move the file from its temporary location to a permanent location.


 NSURL *URL = [NSURL URLWithString:@"http://example.com/file.zip"];
 NSURLRequest *request = [NSURLRequest requestWithURL:URL];

 NSURLSession *session = [NSURLSession sharedSession];
 NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request
                                                         completionHandler:
    ^(NSURL *location, NSURLResponse *response, NSError *error) {
        NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
        NSURL *documentsDirectoryURL = [NSURL fileURLWithPath:documentsPath];
        NSURL *documentURL = [documentsDirectoryURL URLByAppendingPathComponent:[response
suggestedFilename]];
        [[NSFileManager defaultManager] moveItemAtURL:location
                                                toURL:documentURL
                                                error:nil];
 }];

 [downloadTask resume];


 -------------------------------------------------------------------------


NSURLSessionConfiguration:
==========================


NSString *imageUrl =
@"http://www.raywenderlich.com/images/store/iOS7_PDFonly_280@2x_authorTBA.png";

NSURLSessionConfiguration *sessionConfig =
  [NSURLSessionConfiguration defaultSessionConfiguration];
 
 
 
NSString *userPasswordString = [NSString stringWithFormat:@"%@:%@", user, password];
NSData * userPasswordData = [userPasswordString dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64EncodedCredential = [userPasswordData base64EncodedStringWithOptions:0];
NSString *authString = [NSString stringWithFormat:@"Basic %@", base64EncodedCredential];
NSString *userAgentString = @"AppName/com.example.app (iPhone 5s; iOS 7.0.2; Scale/2.0)";


sessionConfig.HTTPAdditionalHeaders = @{@"Accept": @"application/json",
                                        @"Accept-Language": @"en",
                                        @"Authorization": authString,
                                        @"User-Agent": userAgentString};
                                                                              
sessionConfig.allowsCellularAccess = NO;
sessionConfig.timeoutIntervalForRequest = 30.0;
sessionConfig.timeoutIntervalForResource = 60.0;
sessionConfig.HTTPMaximumConnectionsPerHost = 1;




NSURLSession *session =
  [NSURLSession sessionWithConfiguration:sessionConfig
                                delegate:self
                           delegateQueue:nil];
                          
                          


// 1
NSURLSessionDownloadTask *getImageTask =
[session downloadTaskWithURL:[NSURL URLWithString:imageUrl]

    completionHandler:^(NSURL *location,
                        NSURLResponse *response,
                        NSError *error) {
        // 2
        UIImage *downloadedImage =
          [UIImage imageWithData:
              [NSData dataWithContentsOfURL:location]];
      //3
      dispatch_async(dispatch_get_main_queue(), ^{
        // do stuff with image
        _imageWithBlock.image = downloadedImage;
      });
}];

// 4
[getImageTask resume];


Delegates:
-----------

-(void)URLSession:(NSURLSession *)session
     downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
  // use code above from completion handler
}



-(void)URLSession:(NSURLSession *)session
     downloadTask:(NSURLSessionDownloadTask *)downloadTask
     didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
  NSLog(@"%f / %f", (double)totalBytesWritten,
    (double)totalBytesExpectedToWrite);
}


 -------------------------------------------------------------------------

REST API Call


//NSString *post = @"key1=val1&key2=val2";

NSString *post = [NSString stringWithFormat:@"key1=%@&key2=%@",[self urlEncodeValue:val1],[self urlEncodeValue:val2]];

NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]];

NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:@"http://www.nowhere.com/sendFormHere.php"]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postData];


- (NSString *)urlEncodeValue:(NSString *)str
{
    NSString *result = (NSString *) CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)str, NULL, CFSTR("?=&+"), kCFStringEncodingUTF8);
    return [result autorelease];
}


[NSURLConnection sendAsynchronousRequest:request
                                    queue:[NSOperationQueue mainQueue]
                        completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    
    
     if(!error){
    
         NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
        if(httpResponse.statusCode == 200){
       
        } else {
            NSLog(@"Invalid Response : %d", (int)httpResponse.statusCode);           
        }
    
     } else {
         NSLog("@"Error : %@", error);
     }
    
 }];


 

Friday, October 17, 2014

What is key-value coding ?


The idea behind key-value coding is pretty simple: instead of directly getting and setting specific properties on an object, key-value coding involves passing in a "key" (usually a string) and getting or setting the property associated with that key.


For example:
// Set a property directly...
someObject.someProperty = someValue;

// ...or set the same property using key-value coding
[someObject setValue:someValue forKey:@"someProperty"];

Pass generation in PHP

<?php

    ...Some Code...

    header('Content-Type: application/vnd.apple.pkpass');
    header('Content-Length: ' . filesize($filename));
    readfile($filename);
?>

Thursday, October 16, 2014

Vector Algebra


static inline CGVector TCVectorMultiply(CGVector vector, CGFloat m);

static inline CGVector TCVectorMinus(CGPoint p1, CGPoint p2)
{
    return CGVectorMake(
        p1.x - p2.x,
        p1.y - p2.y
    );
}

static inline CGFloat TCVectorLength(CGVector vector)
{
    return sqrtf(vector.dx * vector.dx + vector.dy * vector.dy);
}

static inline CGVector TCVectorUnit(CGVector vector)
{
    CGFloat invLen = 1.0 / TCVectorLength(vector);
    return TCVectorMultiply(vector, invLen);
}

static inline CGVector TCVectorMultiply(CGVector vector, CGFloat m)
{
    return CGVectorMake(
        vector.dx * m,
        vector.dy * m
    );
}

----------------------------------------------------------------


static inline CGPoint CGPointMultiplyScalar( const CGPoint a, const CGFloat b )
{
  return CGPointMake(a.x * b, a.y * b);
}


static inline CGPoint CGPointAdd( const CGPoint a, const CGPoint b)
{
  return CGPointMake(a.x + b.x , a.y + b.y);
}


Friday, October 10, 2014

Functions inside Structure in C

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct point
{
    int x;
    int y;
    void (*print)(const struct point*);
};

void print_x(const struct point* p)
{
    printf("x=%d\n", p->x);
}

void print_y(const struct point* p)
{
    printf("y=%d\n", p->y);
}

int main(void)
{
    struct point p1 = { 2, 4, print_x };
    struct point p2 = { 7, 1, print_y };

    p1.print(&p1);
    p2.print(&p2);

    return 0;
}
 
 

Friday, October 3, 2014

Image Processing in ObjC



Combine two UIImages
-----------------------------
- (UIImage *)addImage:(UIImage *)image1 toImage:(UIImage *)image2 { 
    UIGraphicsBeginImageContext(image1.size); 
 
    // Draw image1 
    [image1 drawInRect:CGRectMake(0, 0, image1.size.width, image1.size.height)]; 
 
    // Draw image2 
    [image2 drawInRect:CGRectMake(0, 0, image2.size.width, image2.size.height)]; 
 
    UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext(); 
 
    UIGraphicsEndImageContext(); 
 
    return resultingImage; 





Create a UIImage from a part of another UIImage:
------------------------------------------------------------
- (UIImage *)imageFromImage:(UIImage *)image inRect:(CGRect)rect { 
    CGImageRef sourceImageRef = [image CGImage]; 
    CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, rect); 
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef]; 
    CGImageRelease(newImageRef); 
    return newImage; 
}



Save UIImage to Photo Album:
--------------------------------------
UIImageWriteToSavedPhotosAlbum(image, self, @selector(imageSavedToPhotosAlbum: didFinishSavingWithError: contextInfo:), context); 
   
   
- (void)imageSavedToPhotosAlbum:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo { 
    NSString *message; 
    NSString *title; 
    if (!error) { 
        title = NSLocalizedString(@"SaveSuccessTitle", @""); 
        message = NSLocalizedString(@"SaveSuccessMessage", @""); 
    } else { 
        title = NSLocalizedString(@"SaveFailedTitle", @""); 
        message = [error description]; 
    } 
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title 
                                                    message:message 
                                                   delegate:nil 
                                          cancelButtonTitle:NSLocalizedString(@"ButtonOK", @"") 
                                          otherButtonTitles:nil]; 
    [alert show]; 
    [alert release]; 
}



Waze API


search for address:         waze://?q=

center map to lat / lon:     waze://?ll=,
navigate to lat / lon:         waze://?ll=,&navigate=yes
set zoom (minimum is 6):     waze://?z=


- (void) navigateToLatitude:(double)latitude
                  longitude:(double)longitude
{
  if ([[UIApplication sharedApplication]
    canOpenURL:[NSURL URLWithString:@"waze://"]]) {

      // Waze is installed. Launch Waze and start navigation
      NSString *urlStr =
        [NSString stringWithFormat:@"waze://?ll=%f,%f&navigate=yes",
        latitude, longitude];

      [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlStr]];

   } else {

      // Waze is not installed. Launch AppStore to install Waze app
      [[UIApplication sharedApplication] openURL:[NSURL
        URLWithString:@"http://itunes.apple.com/us/app/id323229106"]];
   }
}


=======================================================================

try
{
   String url = "waze://?q=Hawaii";
    Intent intent = new Intent( Intent.ACTION_VIEW, Uri.parse( url ) );
   startActivity( intent );
}
catch ( ActivityNotFoundException ex  )
{
  Intent intent =
    new Intent( Intent.ACTION_VIEW, Uri.parse( "market://details?id=com.waze" ) );
  startActivity(intent);
}

Thursday, October 2, 2014

Adding Rounded Corners to UIView


CGRect bounds = (UIView*).bounds;
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:bounds
                                               byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerTopRight)
                                                     cornerRadii:CGSizeMake(10.0, 10.0)];

CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = bounds;
maskLayer.path = maskPath.CGPath;

(UIView*).layer.mask = maskLayer;

Reversing Array in ObjC



@implementation NSArray (Reverse)

- (NSArray *)reversedArray {
    NSMutableArray *array = [NSMutableArray arrayWithCapacity:[self count]];
    NSEnumerator *enumerator = [self reverseObjectEnumerator];
    for (id element in enumerator) {
        [array addObject:element];
    }
    return array;
}

@end

@implementation NSMutableArray (Reverse)

- (void)reverse {
    if ([self count] == 0)
        return;
    NSUInteger i = 0;
    NSUInteger j = [self count] - 1;
    while (i < j) {
        [self exchangeObjectAtIndex:i
                  withObjectAtIndex:j];

        i++;
        j--;
    }
}

@end


Running Tasks,Localnotifications in Background:



- (void)applicationDidEnterBackground:(UIApplication *)application {
 
  if ([[UIDevice currentDevice] isMultitaskingSupported]) {
   
    UIApplication *application = [UIApplication sharedApplication];
   
    __block UIBackgroundTaskIdentifier background_task;
    background_task = [application beginBackgroundTaskWithExpirationHandler: ^ {
     
      NSLog(@"ExpirationHandler about to expire...");
//      [application endBackgroundTask: background_task];
//      background_task = UIBackgroundTaskInvalid;
    }];
   
   
    NSOperationQueue* operationQueue = [[NSOperationQueue alloc] init];
    [operationQueue addOperationWithBlock:^{
   
      // Perform long-running tasks without blocking main thread
     
      while(TRUE)
      {
        //backgroundTimeRemaining time does not go down.
       
        //NSLog(@"Background time Remaining: %f",[[UIApplication sharedApplication] backgroundTimeRemaining]);
       
        UIDevice *device              = [UIDevice currentDevice];
        NSLog(@"Battey Level : %f", (device.batteryLevel));
       
        if(device.batteryLevel == 0.20f) {
          NSLog(@"Should show alert view.....for local notifications");
         
          int currentBatteryLevel      = (int)(device.batteryLevel * 100);

         
          NSDate *now = [NSDate date];
          NSCalendar *calendar = [NSCalendar currentCalendar];
          NSDateComponents *components = [[NSDateComponents alloc] init];
          [components setSecond:5];
          NSDate *dateTime = [calendar dateByAddingComponents:components
                                                              toDate:now
                                                             options:0];
         
         
          UILocalNotification *localNotification = [[UILocalNotification alloc] init];
          localNotification.fireDate = dateTime;
          localNotification.alertBody = [NSString stringWithFormat:@"Battery Level : %d percent", currentBatteryLevel];
          localNotification.soundName = UILocalNotificationDefaultSoundName;
          //localNotification.applicationIconBadgeNumber = 1;
          [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
         
         
            [application endBackgroundTask: background_task];
            background_task = UIBackgroundTaskInvalid;
        }
       
        [[NSNotificationCenter defaultCenter] postNotificationName:@"UIDeviceBatteryLevelDidChangeNotification" object:self userInfo:nil];
       
        [NSThread sleepForTimeInterval:10]; //wait for 1 sec

      }
     
    }];
   
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
           
      // Wait until the pending operations finish
      [operationQueue waitUntilAllOperationsAreFinished];

     
      NSLog(@"ExpirationHandler is called");

    });
  }
}

UUID in iOS



// Get UUID value
NSUUID  *uuid = [NSUUID UUID];

// Convert UUID to string and output result
NSLog(@"UUID: %@", [uuid UUIDString]);


-----------------------------------------------------


CFUUIDRef uuid = CFUUIDCreate(NULL);
CFStringRef identifier = CFUUIDCreateString(NULL, uuid);
CFRelease(uuid);

NSString *uuidString = CFBridgingRelease(identifier);


-----------------------------------------------------

Parse Linker Errors


1.Remove -ObjC and -all_load in Other Linker Flags
2.Add -force_load to load only CocoaLibSpotify.

Example :
-force_load $(SRCROOT)/GoogleAdmob/fileName.a





NSURLAuthenticationChallenge




#pragma mark - NSURLConnection delegate for Handling HTTPS
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace*)protectionSpace {
  NSLog(@"Authentication String : %@", NSURLAuthenticationMethodServerTrust);
 
  NSLog(@"protectionSpace.authenticationMethod : %@", protectionSpace.authenticationMethod);
 
  //return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
 
  return YES;
}

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
 
  NSLog(@"challenge.protectionSpace.authenticationMethod : %@", challenge.protectionSpace.authenticationMethod);
 
  if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
    [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
    NSLog(@"************ CERTIFICATE DOWNLOADED ***************");
  }
  [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
 
}

Creating SHA1 for Android Apps



Susantas-MacBook-Pro-2:Desktop susantabehera$ keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v

Enter keystore password:
Alias name: androiddebugkey
Creation date: Mar 21, 2012
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Android Debug, O=Android, C=US
Issuer: CN=Android Debug, O=Android, C=US
Serial number: 4f695d8f
Valid from: Wed Mar 21 12:48:15 MYT 2012 until: Fri Mar 14 12:48:15 MYT 2042
Certificate fingerprints:
     MD5:  22:CF:6E:A9:BD:23:73:61:0E:25:A9:2E:3E:9D:C3:DB
     SHA1: 8D:87:F2:55:CE:E3:70:28:91:2C:86:BE:6C:F2:2C:1E:50:F5:22:D0
     Signature algorithm name: SHA1withRSA
     Version: 3
    
Susantas-MacBook-Pro-2:Desktop susantabehera$


Vibrate UIView



#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)


+ (void)vibrateView:(UIView*)view
{
    CABasicAnimation *shiverAnimationR;
    shiverAnimationR = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    shiverAnimationR.toValue = [NSNumber numberWithFloat:DEGREES_TO_RADIANS(1)];
    //shiverAnimationR.toValue = [NSNumber numberWithFloat:DEGREES_TO_RADIANS(-10)];
    shiverAnimationR.duration = 0.1;
    shiverAnimationR.repeatCount = 1000000.0; // Use A high Value
    shiverAnimationR.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];

    [view.layer addAnimation: shiverAnimationR forKey:@"shiverAnimationR"];


    CABasicAnimation * shiverAnimationL;
    shiverAnimationL = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    //shiverAnimationL 2.toValue = [NSNumber numberWithFloat:DEGREES_TO_RADIANS(10)];
    shiverAnimationL.toValue = [NSNumber numberWithFloat:DEGREES_TO_RADIANS(-1)];
    shiverAnimationL.duration = 0.1;
    shiverAnimationL.repeatCount = 1000000.0;
    shiverAnimationL.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];

    [view.layer addAnimation: shiverAnimationL forKey:@"shiverAnimationL"];


}

Set UILabel Vertically



NSString *string = @"Lorem Ipsum";
UIFont *font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];

UILabel *label = [[UILabel alloc] init];
label.font = font;
label.text = string;

CGSize size = [string sizeWithAttributes:@{NSFontAttributeName:font}];
label.frame = CGRectMake(40, 40, size.width, size.height);
[label.layer setAnchorPoint:CGPointMake(0.0, 0.0)];
label.transform = CGAffineTransformMakeRotation((M_PI) / 2);


[self.view addSubview:label];

Convert NSDictionary to NSString



Sometime we need to convert the dictionary(received from server or database)
to the JSON string. We can use this simple function.


+ (NSString*) convertDictionaryToString:(NSMutableDictionary*) dict
{
    NSError* error;
    NSDictionary* tempDict = [dict copy]; // get Dictionary from mutable Dictionary
    //giving error as it takes dic, array,etc only. not custom object.
    NSData* jsonData = [NSJSONSerialization dataWithJSONObject:tempDict
                                                       options:NSJSONReadingMutableLeaves error:&error];
    NSString* nsJson=  [[NSString alloc] initWithData:jsonData
                                             encoding:NSUTF8StringEncoding];
    return nsJson;

}

Convert Hex color code to UIColor



#define kBgColorCode    @"2c76c2"



[self.view setBackgroundColor:[Self colorWithHexString:kBgColorCode]];


+(UIColor*)colorWithHexString:(NSString*)hex
{
    NSString *cString = [[hex stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString];
  
    // String should be 6 or 8 characters
    if ([cString length] < 6) return [UIColor grayColor];
  
    // strip 0X if it appears
    if ([cString hasPrefix:@"0X"]) cString = [cString substringFromIndex:2];
  
    if ([cString length] != 6) return  [UIColor grayColor];
  
    // 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];
}


iOS appStoreReceiptURL into Base64 Encoded String



// this returns an NSDictionary of the app's store receipt, status=0 for good, -1 for bad
- (NSDictionary *) getStoreReceipt:(BOOL)sandbox {

    NSArray *objects;
    NSArray *keys;
    NSDictionary *dictionary;

    BOOL gotreceipt = false;

    @try {

        NSURL *receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];

        if ([[NSFileManager defaultManager] fileExistsAtPath:[receiptUrl path]]) {

            NSData *receiptData = [NSData dataWithContentsOfURL:receiptUrl];

            NSString *receiptString = [self base64forData:receiptData];

            if (receiptString != nil) {

                objects = [[NSArray alloc] initWithObjects:receiptString, nil];
                keys = [[NSArray alloc] initWithObjects:@"receipt-data", nil];
                dictionary = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];

                NSString *postData = [self getJsonStringFromDictionary:dictionary];

                NSString *urlSting = @"https://buy.itunes.apple.com/verifyReceipt";
                if (sandbox) urlSting = @"https://sandbox.itunes.apple.com/verifyReceipt";

                dictionary = [self getJsonDictionaryWithPostFromUrlString:urlSting andDataString:postData];

                if ([dictionary objectForKey:@"status"] != nil) {

                    if ([[dictionary objectForKey:@"status"] intValue] == 0) {

                        gotreceipt = true;

                    }
                }

            }

        }

    } @catch (NSException * e) {
        gotreceipt = false;
    }

    if (!gotreceipt) {
        objects = [[NSArray alloc] initWithObjects:@"-1", nil];
        keys = [[NSArray alloc] initWithObjects:@"status", nil];
        dictionary = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];
    }

    return dictionary;
}



- (NSDictionary *) getJsonDictionaryWithPostFromUrlString:(NSString *)urlString andDataString:(NSString *)dataString {
    NSString *jsonString = [self getStringWithPostFromUrlString:urlString andDataString:dataString];
    NSLog(@"%@", jsonString); // see what the response looks like
    return [self getDictionaryFromJsonString:jsonString];
}


- (NSDictionary *) getDictionaryFromJsonString:(NSString *)jsonstring {
    NSError *jsonError;
    NSDictionary *dictionary = (NSDictionary *) [NSJSONSerialization JSONObjectWithData:[jsonstring dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&jsonError];
    if (jsonError) {
       dictionary = [[NSDictionary alloc] init];
    }
    return dictionary;
}


- (NSString *) getStringWithPostFromUrlString:(NSString *)urlString andDataString:(NSString *)dataString {
    NSString *s = @"";
    @try {
        NSData *postdata = [dataString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
        NSString *postlength = [NSString stringWithFormat:@"%d", [postdata length]];
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
        [request setURL:[NSURL URLWithString:urlString]];
            [request setTimeoutInterval:60];
        [request setHTTPMethod:@"POST"];
        [request setValue:postlength forHTTPHeaderField:@"Content-Length"];
        [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
        [request setHTTPBody:postdata];
        NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
        if (data != nil) {
            s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        }
    }
    @catch (NSException *exception) {
        s = @"";
    }
    return s;
}


// from http://stackoverflow.com/questions/2197362/converting-nsdata-to-base64
- (NSString*)base64forData:(NSData*)theData {
    const uint8_t* input = (const uint8_t*)[theData bytes];
    NSInteger length = [theData length];
    static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
    uint8_t* output = (uint8_t*)data.mutableBytes;
    NSInteger i;
    for (i=0; i < length; i += 3) {
        NSInteger value = 0;
        NSInteger j;
        for (j = i; j < (i + 3); j++) {
            value <<= 8;

            if (j < length) {
                value |= (0xFF & input[j]);
            }
        }
        NSInteger theIndex = (i / 3) * 4;
        output[theIndex + 0] =                    table[(value >> 18) & 0x3F];
        output[theIndex + 1] =                    table[(value >> 12) & 0x3F];
        output[theIndex + 2] = (i + 1) < length ? table[(value >> 6)  & 0x3F] : '=';
        output[theIndex + 3] = (i + 2) < length ? table[(value >> 0)  & 0x3F] : '=';
    }
    return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
}


=======================================================================

Just heads up if you are getting a 21004 error, dont forget to send your application shared secret... like this NSString *password = @"your shared secret string"; objects = [[NSArray alloc] initWithObjects:receiptString, password, nil]; keys = [[NSArray alloc] initWithObjects:@"receipt-data", @"password", nil];