Wednesday, August 1, 2012

Public, Private, and Protected Instance Variables

Classes can set instance variables as private, protected, and public. You use the compiler directives @private, @protected, and @public to declare the visiblity of instance variable.

The public directive allows any class access to the public variables.
The private directive ensures private variables are only visible to the class which declares it.
The protected directive ensures protected variables are only visible to the declaring class and its descendants.

Thursday, July 5, 2012

Alternative way to replace UIGetScreenImage()

CGImageRef screen = UIGetScreenImage();

The above code is one line of code to capture the screen, but Apple does not open the above API UIGetScreenImage() for the public app. i.e. fail to upload to Apple for approval. So the alternative way to capture screen and save it are listed as below.

- (void)captureAndSaveImage
{    
    
    // Capture screen here... and cut the appropriate size for saving and uploading
    UIGraphicsBeginImageContext(self.view.bounds.size);
    [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
   
    // crop the area you want 
    CGRect rect;
    rect = CGRectMake(0, 10, 300, 300);    // whatever you want
    CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], rect);
    UIImage *img = [UIImage imageWithCGImage:imageRef]; 
    CGImageRelease(imageRef);
    UIImageWriteToSavedPhotosAlbum(img, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
    imageView.image = img; // show cropped image on the ImageView     
}

// this is option to alert the image saving status
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
    UIAlertView *alert;
    
    // Unable to save the image  
    if (error)
        alert = [[UIAlertView alloc] initWithTitle:@"Error" 
                                           message:@"Unable to save image to Photo Album." 
                                          delegate:self cancelButtonTitle:@"Dismiss" 
                                 otherButtonTitles:nil];
    else // All is well
        alert = [[UIAlertView alloc] initWithTitle:@"Success" 
                                           message:@"Image saved to Photo Album." 
                                          delegate:self cancelButtonTitle:@"Ok" 
                                 otherButtonTitles:nil];
    [alert show];
    [alert release];
}


Tuesday, July 3, 2012

Base64 encode/decode method

//put it on the top of xxx.m
static char base64EncodingTable[64] = {
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
    'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
- (void)testBase64
{

    NSString *testStr = @"000000";

    NSString *encodedStr = [self base64StringFromData:testStr];
    NSLog(@"%@", encodedStr);

    NSData *data = [self base64DataFromString:encodedStr];
    NSString decodedStr = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"decoded string is %@ for %@", decodedStr, testStr);

}


// encode method
-(NSString *) base64StringFromData:(NSString *)str
{
    
    NSData* data=[str dataUsingEncoding:NSUTF8StringEncoding];
    int length = str.length;    
    
    unsigned long ixtext, lentext;
    long ctremaining;
    unsigned char input[3], output[4];
    short i, charsonline = 0, ctcopy;
    const unsigned char *raw;
    NSMutableString *result;
    
    lentext = [data length]; 
    if (lentext < 1)
        return @"";
    result = [NSMutableString stringWithCapacity: lentext];
    raw = [data bytes];
    ixtext = 0; 
    
    while (true) {
        ctremaining = lentext - ixtext;
        if (ctremaining <= 0) 
            break;        
        for (i = 0; i < 3; i++) { 
            unsigned long ix = ixtext + i;
            if (ix < lentext)
                input[i] = raw[ix];
            else
                input[i] = 0;
        }
        output[0] = (input[0] & 0xFC) >> 2;
        output[1] = ((input[0] & 0x03) << 4) | ((input[1] & 0xF0) >> 4);
        output[2] = ((input[1] & 0x0F) << 2) | ((input[2] & 0xC0) >> 6);
        output[3] = input[2] & 0x3F;
        ctcopy = 4;
        switch (ctremaining) {
            case 1: 
                ctcopy = 2; 
                break;
            case 2: 
                ctcopy = 3; 
                break;
        }
        
        for (i = 0; i < ctcopy; i++)
            [result appendString: [NSString stringWithFormat: @"%c", base64EncodingTable[output[i]]]];
        
        for (i = ctcopy; i < 4; i++)
            [result appendString: @"="];
        
        ixtext += 3;
        charsonline += 4;
        
        if ((length > 0) && (charsonline >= length))
            charsonline = 0;
    }     
    return result;
}


// decode method
- (NSData *)base64DataFromString: (NSString *)string
{
    unsigned long ixtext, lentext;
    unsigned char ch, inbuf[4], outbuf[3];
    short i, ixinbuf;
    Boolean flignore, flendtext = false;
    const unsigned char *tempcstring;
    NSMutableData *theData;
    
    if (string == nil)
    {
        return [NSData data];
    }
    
    ixtext = 0;
    
    tempcstring = (const unsigned char *)[string UTF8String];
    
    lentext = [string length];
    
    theData = [NSMutableData dataWithCapacity: lentext];
    
    ixinbuf = 0;
    
    while (true)
    {
        if (ixtext >= lentext)
        {
            break;
        }
        
        ch = tempcstring [ixtext++];
        
        flignore = false;
        
        if ((ch >= 'A') && (ch <= 'Z'))
        {
            ch = ch - 'A';
        }
        else if ((ch >= 'a') && (ch <= 'z'))
        {
            ch = ch - 'a' + 26;
        }
        else if ((ch >= '0') && (ch <= '9'))
        {
            ch = ch - '0' + 52;
        }
        else if (ch == '+')
        {
            ch = 62;
        }
        else if (ch == '=')
        {
            flendtext = true;
        }
        else if (ch == '/')
        {
            ch = 63;
        }
        else
        {
            flignore = true; 
        }
        
        if (!flignore)
        {
            short ctcharsinbuf = 3;
            Boolean flbreak = false;
            
            if (flendtext)
            {
                if (ixinbuf == 0)
                {
                    break;
                }
                
                if ((ixinbuf == 1) || (ixinbuf == 2))
                {
                    ctcharsinbuf = 1;
                }
                else
                {
                    ctcharsinbuf = 2;
                }
                
                ixinbuf = 3;
                
                flbreak = true;
            }
            
            inbuf [ixinbuf++] = ch;
            
            if (ixinbuf == 4)
            {
                ixinbuf = 0;
                
                outbuf[0] = (inbuf[0] << 2) | ((inbuf[1] & 0x30) >> 4);
                outbuf[1] = ((inbuf[1] & 0x0F) << 4) | ((inbuf[2] & 0x3C) >> 2);
                outbuf[2] = ((inbuf[2] & 0x03) << 6) | (inbuf[3] & 0x3F);
                
                for (i = 0; i < ctcharsinbuf; i++)
                {
                    [theData appendBytes: &outbuf[i] length: 1];
                }
            }
            
            if (flbreak)
            {
                break;
            }
        }
    }
    
    return theData;

}

****************************************************
Output in console:

Decoded string is MDAwMDAw for testStr 000000;

Tuesday, June 26, 2012

php: get input and write text file, then return

Put the following codes in the server side to receive the inputs from Apps.

<?php
     
    // assign the input to the variables
    $method = $_POST['method'];
    $name = $_POST['name']; // variable to be received by server
    $id = $_POST['userID']; // variable to be received by server
    echo " user name: ".$name ." id: ". $id. " method: ". $method; // echo the received data to the Apps
    
    
    // write text file with above two variables
    $file = "file.txt";
    $fh = fopen( $file, 'w' );
    $carriageReturn = "\n";
    fwrite( $fh, $method );
    fwrite( $fh, $carriageReturn );
    fwrite( $fh, $name );
    fwrite( $fh, $carriageReturn );
    fwrite( $fh, $id );
    fclose( $fh );
   
    
    
?>

php: return data in json

In server side, the following code can return the data in JSON format to client(Apps).

<?php

     
    $name = "Ben";
    $id = "id1234";
    $method = "get data";
    
    // build result in json format
    $arr = array("result" => "success",
                 "uid" => $id,
                 "data"=>array("name"=>$name, 
                               "id"=>$id, 
                               "method"=>$method 
                               
                               )
                 );
    
    echo json_encode($arr);
    
    
?>

php: generates Token with random string

The following code generate the random string with certain length to the client. It can be used to create the token and send to client's apps.

<?php
    
    // generate random string
    function random_gen($length)
    {
        $random= "";
        srand((double)microtime()*1000000);
        $char_list = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        $char_list .= "abcdefghijklmnopqrstuvwxyz";
        $char_list .= "1234567890";
        // Add the special characters to $char_list if needed
        
        for($i = 0; $i < $length; $i++)  
        {    
            $random .= substr($char_list,(rand()%(strlen($char_list))), 1);  
        }  
        return $random;
    } 
    
    $random_string = random_gen(30); //This will return a random 30 character string
    echo "New Token: ".$random_string;
    
   
?>

Monday, June 25, 2012

Distribute beta App over the air

Now it is not necessary to send ipa file and distribution profile to beta tester for Apps testing. There is a distribution OTA method, the apps can be uploaded to server and let tester to install it from server.

1. to create a provisioning distribution profile for Ad Hoc build with the selected iDevices (devices' UDID are registered in the portal).
2. in Xcode, associate this provisioning distribution profile with your build. In the Code Signing section choose the new Provisioning Profile.
3. Build and Archive.
4. Click on the Share button, and choose Distribute for Enterprise – fill in the URL to the location where you plan to host the application.
5. Upload ipa, plist and icon files to the server you typed in step 4.
6. Build the HTML to let iDevice to access and install the app.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html>
<head> 
  <title>OTA Test App</title> 
</head> 
<body>
  
    <br><font size = "20">You are invited to test new app.</font></br>
    <br><<font size="15"><a href="itms-services://?action=download-manifest&url=http://www.yourwebsite.com">Tap Here to Install the Application</a></font>
  </br>