The Mobile Galaxy The New Mobile Era Has Come | Mobile – A Time To Remember

10Dec/110

Got Git? HOWTO git and github

Thanks to Steven Bristol .

From :http://lesseverything.com/blog/archives/2008/03/25/got-git-howto-git-and-github/

Share
6Dec/110

iPhone Program Crashes and Stability Issues

If you’re running into frequent iPhone program crashes, here are some tips for getting better stability.

Application memory management issues

Generally, it caused by memory management, such as a instance un-alloc, released, un-expected copy. This kind issues is easy to find through unit test and functionality test.

Apple firmware compatibility issues

As the IOS version change, API maybe different, sometimes it is serious and kill the app.

For example:

In IOS 5, the following statement is fine:

UIBarButtonItem* rightBtn= [[UIBarButtonItem alloc] initWithTitle:@"Upload" style:UIBarButtonItemStylePlain target:self action:@selector(upload)];

rightBtn.tintColor=[UIColor redColor]; // it will crash in IOS 4.0

In IOS 4.2.1

-(void)finishedTakePicture:(UIImage*)img{

_stillimage =[img copy]; // This run fine in IOS 4.2.1, but it will crash in IOS 4.1

// solution:   [_stillimage setValue:img forKey:@"image"];

}

So checking each IOS version API difference is most important to avoid random crash. generally this kind issues can not be found through unit test or simulator debug.

How to automatically check API diff maybe a interesting topic for iPhone testing.

For getting better stability, we have to do testing through three aspects:

Unit test and functionality test

Memory management test

IOS version compatibility test
PS: A list of all firmware:

Share
25Nov/110

Memory Management Advice – iphone

I am a little unclear about some of the conventions in memory management. I have tried to follow Slick and Duncan's advice and follow this style:

in .h

Class *_var

@property (nonatomic, retain) Class *var

in .m@synthesize var = _var;When assigning the variable

either (for example with UITextView):

self.var = [[[UITextView alloc] initWithFrame:(such and such frame)] autorelease];

(autorelease to avoid two retains)

or

UITextView *tempTextView = [[UITextView alloc] initWithFrame:(so on and so so)];
self.var = tempTextView;
[tempTextView release];

In dealloc

self.var = nil; (does the release automatically due to synthesize)

So, assuming I am doing this right, the question comes up in what I do when I am working with these variables. Do I use the instance variable or property when working with the variable in non "self.var = " purposes.

for instance:

If var is a UITextView, Do I use:

self.var.userInteractionEnabled = NO;
self.var.text = @"Some Text";

OR

_var.userInteractionEnabled = NO;
_var.text = @"Some Text";

Basically,

When is the property accessed when changing the "sub properties" vs. the instance variable. It seems like both work but I assume that one would have a preferred way above another.

I was under the impression that I should only call the property when directly assigning. e.g.

self.var = something;

Additionally, when adding a subView to a view (assuming a UITextView var), would I say:

[self.view addSubView: self.var];

or

[self.view addSubview:_var];

btw, I've color coded Instance Variables as Slick suggested in red but I am confused as it seems like everything shows up as an instance variable (including self.var) in red. The only time something shows up not red is like:

[something setSomething:self.var];

Where "var" is not red.

Otherwise:

self.var =

or

_var =

var is red.

I feel like this is a huge fundamental thing I am missing and although I have created a great number of successful apps, I keep having minor bugs haunt me that are associated with memory problems. All the tutorials you follow assign instance variables and properties with the same exact name so it isn't clear what is going on and why it works.

Thanks!
James

Share
21Nov/110

What is MailCore?

MailCore is a Cocoa framework designed to ease the pain of dealing with e-mail protocols by adding a nice Objective-C/Cocoa interface to the C library Libetpan!. MailCore makes the process of sending e-mail easy by hiding the nasty details like MIME composition from you. Instead, there is a nice interface for composing messages and then there is a single method required to send the message. Checking e-mail on an IMAP server is a more complex beast, but MailCore makes the job much simpler but presenting everything as a set of abstract objects like Messages, Folders and Accounts. Note, however, that MailCore is not multithreaded so any calls made will potentially block and not every IMAP detail is abstracted away. Also, MailCore stores everything in memory so if you want to save state to disk it has to be done by hand.

 

Sending E-mail

Sending e-mail with MailCore is very easy, it takes care of all the details like MIME encoding, and the SMTP protocol. First, start by creating a CTCoreMessage instance. Then set the subject, body, from, and atleast one to, bcc, or cc recipient. One detail to note is that the to, cc, bcc attributes take an NSSet of CTCoreAddress recipients.

CTCoreMessage *testMsg = [[CTCoreMessage alloc] init];
[testMsg setTo:[NSSet setWithObject:[CTCoreAddress addressWithName:@"Monkey" email:@"monkey@monkey.com"]]];
[testMsg setFrom:[NSSet setWithObject:[CTCoreAddress addressWithName:@"Someone" email:@"test@someone.com"]]];
[testMsg setBody:@"This is a test message!"];
[testMsg setSubject:@"This is a subject"];

Once the message attributes have been set, all that is left is sending the message usingCTSMTPConnection:

[CTSMTPConnection sendMessage:testMsg server:@"mail.test.com" username:@"test" password:@"test" port:25 useTLS:YES shouldAuth:YES];
[testMsg release];

That's all

 

Working with IMAP

Working with IMAP through MailCore is quite easy. First you need to instantiate aCTCoreAccount object and establish a connection like so:

CTCoreAccount *account = [[CTCoreAccount alloc] init];
[account connectToServer:@"mail.theronge.com" port:143 connectionType:CONNECTION_TYPE_PLAIN authType:IMAP_AUTH_TYPE_PLAIN login:@"test" password:@"none"];

If by any chance it fails to make a connection an exception will be thrown. Now that we have a connection to the server we can go ahead and get a list of folders. Note: I use the term folder in place of mailbox; the IMAP spec uses the term mailbox but I get that confused with account.

NSSet *subFolders = [account subscribedFolders];

If we take a look at the resulting NSSet, we see that what is returned is a set of NSStrings with folder path's.

<NSCFSet: 0x309d60> (INBOX.Test.Test22, INBOX, INBOX.TheArchive, INBOX.Test, INBOX.Trash)

We can use one of those strings to create a CTCoreFolder object or we can just pass in a path, for example this sets up a connection to the INBOX on the server.

CTCoreFolder *inbox = [account folderWithPath:@"INBOX"];

Now that we have a connection to a folder we can start to do more interesting things, like we can get a set of the messages in the particular folder, or we can delete the folder, or remove the folder from the subscribed list, check the CTCoreFolder for more information. For this particular example I am going to get a list of the messages in the INBOX (0 as the end index indicates that the entire inbox should be loaded).

NSSet *messageList = [inbox messageListFromIndex:1 toIndex:0];

Like the with folders, what is returned is a set of NSString's containing unique message identifiers (UID).

<NSCFSet: 0x309d60> (1142229815-5, 1142229815-6, 1142229815-7, 1142229815-8, 1142229815-10, 1142229815-1, 1142229815-9, 1142229815-2, 1142229815-11, 1142229815-3, 1142229815-4)

You might be wondering about the parameter to messageListFromIndex: now, it's exists because of a limitation of IMAP. IMAP was designed to be a protocol where you would always be connected to the server, it wasn't until later that people got the idea using IMAP as an offline protocol. Therefore, IMAP generally returns the entire list of message UID's, but this can be very time consuming for very large folders, and by a large folder I'm talking over 5000 messages. To download only new messages and not every message each time, you can save the last message UID you received. Since you have the last message UID you know the next UID has to be one after it. For example, if you receive the UID 1142229815-4 then you know the next UID has to be 1142229815-5. So if you pass 1142229815-4 into messageListFromIndex: it will only retrieve message with a higher UID.

While UID's are not supposed to change, a folder can change the message UID's on rare occasions. It's important to make sure that the cached UID"s are still valid by using the isUIDValid method. If a bad UID was used there is potential for data loss, since the former UID might not reference the message you intend on deleting. If you save a UID, you should make sure that the server is still using the same UID, otherwise start over by passing nil into messageListFromIndex.

Now back to working with messages, to retrieve with a particular message you need to use the method messageWithUID inside of CTCoreFolder. The resulting object will be of typeCTCoreMessage, from there you can retrieve the subject, body and other things by using the message object.

Share
21Nov/110

Capture IOS Screen code

1.
UIGraphicsBeginImageContextWithOptions(pageView.page.bounds.size, YES, zoomScale);
        [pageView.page.layer renderInContext:UIGraphicsGetCurrentContext()];
        UIImage *uiImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
2.
- (UIImage *) glToUIImage {
    
    DWScrollView *pageView = [self getActivePageView];
       pageView.page.backgroundColor = [UIColor clearColor];
  //  self.backgroundColor=[UIColor clearColor];
    NSInteger myDataLength = 320 * 308 * 4;
    
    // allocate array and read pixels into it.
    GLubyte *buffer = (GLubyte *) malloc(myDataLength);
    glReadPixels(0, 0, 320, 308, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
    
    // gl renders "upside down" so swap top to bottom into new array.
    // there's gotta be a better way, but this works.
    GLubyte *buffer2 = (GLubyte *) malloc(myDataLength);
    
    for(int y = 0; y <308; y++)
    {
        for(int x = 0; x <320 * 4; x++)
        {
            if(buffer[y* 4 * 320 + x]==0)
                buffer2[(307 - y) * 320 * 4 + x]=1;
            else
                buffer2[(307 - y) * 320 * 4 + x] = buffer[y* 4 * 320 + x];
        }
    }
    
    // make data provider with data.
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL);
    
    // prep the ingredients
    int bitsPerComponent = 8;
    int bitsPerPixel = 32;
    int bytesPerRow = 4 * 320;
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
    
    // make the cgimage
    CGImageRef imageRef = CGImageCreate(320, 308, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
    
    // then make the uiimage from that
    UIImage *myImage = [UIImage imageWithCGImage:imageRef];
    UIImageWriteToSavedPhotosAlbum(myImage, nil, nil, nil);
    return myImage;
}

3.
// get screen
- (void)grabScreen {
    unsigned char buffer[320*480*4];
    glReadPixels(0,0,320,480,GL_RGBA,GL_UNSIGNED_BYTE,&buffer);
    
    CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, &buffer, 320*480*4, NULL);
    CGImageRef iref = CGImageCreate(320,480,8,32,320*4,CGColorSpaceCreateDeviceRGB(),kCGBitmapByteOrderDefault,ref,NULL,true,kCGRenderingIntentDefault);
    CGFloat width = CGImageGetWidth(iref);
    CGFloat height = CGImageGetHeight(iref);
    size_t length = width*height*4;
    uint32_t *pixels = (uint32_t *)malloc(length);
    CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8, 320*4, CGImageGetColorSpace(iref), kCGImageAlphaLast | kCGBitmapByteOrder32Big);
    CGContextTranslateCTM(context, 0.0, height);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextDrawImage(context, CGRectMake(0.0, 0.0, width, height), iref);
    CGImageRef outputRef = CGBitmapContextCreateImage(context);
    UIImage *outputImage = [UIImage imageWithCGImage:outputRef];
    
    UIImageWriteToSavedPhotosAlbum(outputImage, nil, nil, nil); 
    
    CGContextRelease(context);
    CGImageRelease(iref);
    CGDataProviderRelease(ref);
} 
4.
CGImageRef UIGetScreenImage();
void SaveScreenImage(NSString *path)
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    CGImageRef cgImage = UIGetScreenImage();
        void *imageBytes = NULL;
        if (cgImage == NULL) {
                CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
                imageBytes = malloc(320 * 480 * 4);
                CGContextRef context = CGBitmapContextCreate(imageBytes, 320, 480, 8, 320 * 4, colorspace, kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big);
                CGColorSpaceRelease(colorspace);
                for (UIWindow *window in [[UIApplication sharedApplication] windows]) {
                        CGRect bounds = [window bounds];
                        CALayer *layer = [window layer];
                        CGContextSaveGState(context);
                        if ([layer contentsAreFlipped]) {
                                CGContextTranslateCTM(context, 0.0f, bounds.size.height);
                                CGContextScaleCTM(context, 1.0f, -1.0f);
                        }
                        [layer renderInContext:(CGContextRef)context];
                        CGContextRestoreGState(context);
                }
                cgImage = CGBitmapContextCreateImage(context);
                CGContextRelease(context);
        }
    NSData *pngData = UIImagePNGRepresentation([UIImage imageWithCGImage:cgImage]);
    CGImageRelease(cgImage);
        if (imageBytes)
                free(imageBytes);
    [pngData writeToFile:path atomically:YES];
    [pool release];
}

5.
  + (UIImage *)imageWithScreenContents
{
     CGImageRef cgScreen = UIGetScreenImage();
     if (cgScreen) {
         UIImage *result = [UIImage imageWithCGImage:cgScreen];
         CGImageRelease(cgScreen);
         return result;
     }
     return nil;
}
Share
20Nov/110

FoneMonkey – Automation Testing Tool for iOS Apps

 

 

Credit to:

Rishabh Software

 

From:http://www.rishabhsoft.com/blog/fonemonkey-automation-testing-tool-for-ios-apps

The growing popularity of mobile applications requires that companies adopt strategies and have automated testing solutions designed specifically for the needs of their mobile applications. Due to its nature, it is always a challenge to have automation testing for mobile applications.

I have been getting many customer inquiries about automation testing tools for mobile apps. So far, there have not been many companies offering free tools, but now there’s hope for all mobile apps developers and testers. Gorilla Logic, an IT-consultancy company has launched an open-source automation testing tool for iOS apps, by the name of FoneMonkey.

FoneMonkey is an easy to learn tool that can be used effectively by both groups, to develop and test. FoneMonkey offers the possibilities to save a script, load, read and conveniently modify it. The user can create test suites that automate the execution of the operation sequences of the users and check the results. FoneMonkey is designed to support developers and quality control tests. Tests of FoneMonkey can be easily incorporated into continuous integration environments. FoneMonkey fills a huge void in the area of ​​agile development and showed pragmatism through automated testing for iOS apps.

FoneMonkey Features

  • Robust script recording and playback — more comprehensive recording and playback for user interactions, including taps, keyboard input, dragging, and scrolling for all Cocoa Touch components.
  • Code generation options –  generation of ready-to-run test scripts in Objective-C under OCUnit, or JavaScript under Apple’s UI Automation tools
  • Optimized for both iPhone and iPad platforms and user interfaces
  • Works on both simulators and real devices
  • Completely automated test playbacks

A few disadvantages of FoneMonkey

  • It does not support Flex andAndroid application
  • It does not support testing of HTML-based apps delivered through UIWebView

 

FoneMonkey gives you the ability to easily record, edit and add verification steps to scripts by simply interacting with your apps on the iOS device. So, are you looking to get your iOS Apps tested?

Share
28Oct/110

10 iPhone Memory Management Tips

From:http://akosma.com/2009/01/28/10-iphone-memory-management-tips/

  • Respond to Memory Warnings
  • Avoid Using Autoreleased Objects
  • Use Lazy Loading and Reuse
  • Avoid UIImage’s imageNamed:
  • Build Custom Table Cells and Reuse Them Properly
  • Override Setters Properly
  • Beware of Delegation
  • Use Instruments
  • Use a Static Analysis Tool
  • Use NSZombieEnabled

 

 

Share
28Oct/110

iPhone Basics: Memory Management

One of the biggest sources of confusion for new iPhone developers is memory management. If you’re accustomed to using convenient, garbage-collected scripting languages, you may be wondering why memory management is even necessary. Although Cocoa does support garbage collection, it was deemed too great an overhead for a phone platform. Therefore, it’s important for developers to know how to allocate and release objects correctly.

By following some simple guidelines, you can avoid the majority of memory management problems.

1. If you allocate an object, you should release it once you’re done.

When you allocate an object, you “own” that object, and you’re responsible for releasing it when you’ve finished using it:

Widget* widget = [[Widget alloc] init];
// Do something with widget...
[widget release];

You can think of release as saying relinquish ownership of this object, rather than destroy this object. Behind the scenes, Cocoa performs reference counting to keep track of ownership. If no one claims ownership, the object will be destroyed, and the memory it occupied will be reclaimed.

2. If you did not allocate an object directly, you should not release it.

Once you get the hang of release, it’s tempting to go around releasing objects when you shouldn’t. A common example is when you’re using factory methods:

NSString* label = [NSString stringWithFormat:@"Title: %@", widget.title];
// Do something with label
[label release] // Whoops, incorrect.

In this example, a new string object has been created, but we didn’t allocate it, and we don’t own it. Therefore, we must not call release here — doing so can cause an over-release, which can crash your app.

tip: How is this object released?

Behind the scenes, NSString has called autorelease on the string before returning it, which we’ll look at in a moment.

3. If you need an object, you should retain it (and release it when you’re done).

This rule applies when we receive an object that’s been created by someone else. For example, consider a setter method:

- (void)setName:(NSString*)newName;
{
    [newName retain];   // we need the new string object.
    [name release];     // we don't need the old string any more.
    name = newName;
}

retain signals that we claim ownership of the object; it will not be destroyed when the original owner releases it. But, now that we own the object, we must release it when we no longer need it. Under the hood, retain and release update the reference count of the object, incrementing and decrementing respectively.

Following this pattern simplifies memory management a great deal. When passing an object to a method, we can assume it will be retained (if necessary) and we can release it immediately afterwards:

UIButton* button = [[UIButton alloc] initWithFrame:myFrame];
[self.view addSubview:button]    // Here we can assume that view
                                 // has retained button,
[button release]                 // we can safely release it.

Another common example arises when we use collection objects, which retain the objects added to them:

NSMutableArray* widgetList = [[NSMutableArray alloc] init];
// ...
Widget* widget = [[Widget alloc] init];
[widgetList addObject:widget];           // retains widget
[widget release];                        // we can release widget
//...
[widgetList release] // objects in collection will be released.

4. If you create an object and don’t retain control of it, use autorelease.

Say you want to create your own factory method for Widget. Here, we create a new Widget object and return it from a class method:

+ (Widget*)createBetterWidget
{
    Widget* widget = [[Widget alloc] init];
    [widget setAwesome:11];
    return [widget autorelease];
}

We’re still responsible for releasing the object, so we call autorelease before returning it. autoreleasesignals that the object should be released “eventually.” The object is added to a pool that’s cleared at the end of an application run loop.

It may seem tempting to autorelease everything as a solution for memory management, however this is not recommended, as it’s possible for your app to run out of memory before the autorelease pool is drained.

The best approach is to take a simple, unambiguous approach to allocating and releasing objects. Follow these simple rules and you’ll be well on the way to creating bug-free and efficient code.

For in-depth coverage of these topics, the Apple Memory Management Programming Guide is essential reading for new developers.

Share
26Oct/110

IOS 5 & S/MIME

In  testing, iOS 5 was able to obtain recipients’ certificates through Exchange and Active Directory automatically.

This behavior, and the settings involved, is actually quite similar to how Outlook handles S/MIME as well.

How to manage individual message signing and encryption? It is very user unfriendly to sign and encrypt individual messages, as you need to make a change in general settings-> mail, contacts… every time

Share
26Oct/110

How to Create your PKCS12 Certificate

This Library is designed to use a PKCS12 format Certificate file, which includes the Private Key and Certificate in a single container. This page will show you how to generate this file using the Certificates you downloaded from iPhone Developer Program Portal in either OSX's Keychain or using OpenSSL.

Details

OSX Keychain

After you've created the appropriate Push Notification Certificate in iPhone Developer Program Portal you should have downloaded a file named something like apn_developer_identity.cer. If you have not done so already, you should open/import this file into Keychain, into your login section.

Finally, if you filter Keychain to show your login container's Certificates, you should see your Certificate listed. Expand the certificate, and there should be a Key underneath/attached to it.

Right Click or Ctrl+Click on the appropriate Certificate and choose Export. Keychain will ask you to choose a password to export to. Pick one and remember it. You should end up with a .p12 file. You will need this file and the password you picked to use the Notification and Feedback Libraries here.

OpenSSL

Here is how to create a PKCS12 format file using open ssl, you will need your developer private key (which can be exported from the keychain) and the CertificateSigningRequest???.certSigningRequest (Note your filename may differ)

  1. Convert apn_developer_identity.cer (der format) to pem:

openssl x509 -in apn_developer_identity.cer -inform DER -out apn_developer_identity.pem -outform PEM

  1. Next, Convert p12 private key to pem (requires the input of a minimum 4 char password):

openssl pkcs12 -nocerts -out private_dev_key.pem -in private_dev_key.p12

  1. (Optional): If you want to remove password from the private key:

openssl rsa -out private_key_noenc.pem -in private_key.pem

  1. Take the certificate and the key (with or without password) and create a PKCS#12 format file:

openssl pkcs12 -export -in apn_developer_identity.pem -inkey private_key_noenc.pem -certfile CertificateSigningRequest??.certSigningRequest -name "apn_developer_identity" -out apn_developer_identity.p12

Share