XCode IPhone Programming Tips

As I work my way through XCode development I'll list some discovered tips here.

1. Don't create your projects in the Developer folder. It breaks git version control and your project can even be deleted when you update your development tools. That should be one of the first things they tell you but it's some kind of gotcha secret. Who says Apple doesn't have a sense of humor?

2. XCode 4 has local git version control built in. Use it! It's one of the first things you should understand about this environment. When you create a new project, make sure local Git is checked. It's that simple to get started with your project the right way. Now you are able to commit your changes with a couple clicks. Using version control will save your hide if you are at all experimental and forgetful like me.

3. Guess what? Contrary to popular belief, XCode with Cocoa does have automatic garbage collection. But it's not well documented yet. It's called ARC (Automatic Reference Counting. This is the way to go for new projects. And if you are an old Xcode programmer, you can even convert your project using Edit/Refactor/Convert to Objective-C ARC. The old MRR (Manual Memory Management) is harder to work with than even C, the language that Objective-C is based on. 

4  Here are some helpful libs you should get.
However, you do NOT want to use ASIHTTPRequest mentioned in the above article. Instead use AFNetworking. https://github.com/gowalla/AFNetworking  The reason being that this very popular async networking lib is no longer supported. What's more it does not support the new ARC automatic memory management.

5. Facebook SDK with upload progress bar? Don't bother trying to use a progress bar with the ios facebook sdk when uploading photos or videos. They did not provide the necessary delegate support in the SDK. I had to subclass the SDK and write my own support. If anyone desperately is interested in knowing how I did it, let me know and I could post an example.

6. How to mix ARC (new memory management) with old MRR sdks. I want to use ARC for my new projects, but many of the SDKs such as Facebook were written before ARC and there is no telling when they will update them for IOS 5.  So, here's the trick: 

1. Convert the files you want to use ARC. For example change all property statements to use strong instead of retain and remove all your old object release statements.

2. Change your Build settings for Objective-C Automatic Reference Counting from No to Yes.

3. Change your main.m file to this:

#import <UIKit/UIKit.h>

int main(int argc, char *argv[]) {
   
    @autoreleasepool {
        int retVal = UIApplicationMain(argc, argv, nil, nil);
        return retVal;
    }
}

4. Turn off ARC for any files like those in the Facebook IOS SDK that have not been converted. Here's how:

-  Select your Project.
- Then Target.
- Choose Build Phase.
- Multi-select the files for which you want to disable ARC.
- Hit the Enter Key.
- Then in the pop-up box enter:  -fno-objc-arc

There ya go. Now you can build your project with the new ARC compiler feature, avoid those mean memory leaks and even avoid dangling pointers because ARC assigns a nil to released objects. 

7. Capture still captures from live video frames and upload to facebook. I've done a lot of research and read many blogs. Could not find any correct solutions. Here's the requirements:

- Use AVFoundation and captureStillImageAsynchronouslyFromConnection: to grab a photo with your own low level camera solution.


- Save the image with proper orientation to the device.


- Upload to Youtube with the correct orientation with size reduced to match facebook's maximum photo size.

The problem is that all photos captured this way are oriented right regardless of the actual orientation of the phone. Here's what the resultant UIImage has:

UIImage orientation = UIImageOrientationRight regardless of device orientation
UIImage size = (width & height) are based on the camera resolution. This is good in my opinion.

Ok, so if you save the image using writeImageToSavedPhotosAlbum:[savedImage , you will see the photo saved in the gallery correctly. That's the first trick. However, then uploading the photo to facebook using the same UIImage will show portrait photos always rotated on their side. I've seen elaborate and strange solutions for this, non of which seem to work entirely and are slow. So here's a function that will save and upload any photo captured from a vid frame using AVFoundation.



- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
    [[self scanningLabel] setHidden:YES];
    if (error != NULL)
    {
        [[self scanningLabel] setHidden:YES];
        [self removeSayCheese];
        savedImage = nil;
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Photo Error!" message:@"Unable to Save" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
        [alert show];
        [alert release];
        adBanner.hidden = false;
        curImage.hidden = true;
        blankbg.hidden = true;
    }
    else
    {
        [[self scanningLabel] setHidden:YES];
 
        int fbWidth = savedImage.size.width;
        int fbHeight = savedImage.size.height;
      
        if (savedImage.size.width > 2048)
        {
            if (savedImage.size.width > savedImage.size.height)
            {
                fbWidth = 2048;
                fbHeight = 1536;
            } else
            {
                fbHeight = 2048;
                fbWidth = 1536;
            }
        }
       
        if (fbHeight > fbWidth)
        {
            // Swap & size
            UIGraphicsBeginImageContext(CGSizeMake(fbWidth, fbHeight));
            [savedImage drawInRect:CGRectMake(0, 0, fbWidth, fbHeight)];
            savedImage = [UIGraphicsGetImageFromCurrentImageContext() retain];
            UIGraphicsEndImageContext();
        } else
        {
            // Size only
            UIGraphicsBeginImageContext(CGSizeMake(fbWidth, fbHeight));
            [savedImage drawInRect:CGRectMake(0, 0, fbWidth, fbHeight)];
            savedImage = [UIGraphicsGetImageFromCurrentImageContext() retain];
            UIGraphicsEndImageContext();
        }
        [self cameraUpload];
        savedImage = nil;
    }
}