VoidAsterisk.org

How to register a custom URL scheme in iOS

  • Open the main plist file (project_name-info.plist).
  • Add a new row with key “URL types” (“CFBundleURLTypes”).
  • Under “Item 0”, Add a new row “URL identifier” (“CFBundleURLName”) and add a unique identifier to it (e.g. domain+appname like the row “Bundle identifier” (“CFBundleIdentifier”) “com.domain.${PRODUCT_NAME:rfc1034identifier}”).
  • Still under “Item 0”, add a new row “URL Schemes” (“CFBundleURLSchemes”).
  • Under this rows’s own “Item 0”, add the URL scheme prefix (e.g “appname”)

(Source: iphonedevelopertips.com)

How to create a iOS static library and link via XCode

  • Create a new project, select “Cocoa Touch Static Library”.
  • Add your library code there, ensure it builds.
  • Pick your public relevant .h files, right click on them and select “Set Role” -> “Public”.
  • On Finder, after a build, check if there are folders like “build/{Debug}-{iphone{os,simulator}}/usr/local/include/*.h” with the .h files just set to public, as well as the library (lib*.a) at “”build/{Debug}-{iphone{os,simulator}}/”.
  • On the real project, create a folder group called “Dependencies” (optional, just for organization purposes).
  • From the Finder, drag the library xcode project (the blue .xcodeproj icon) into the real project XCode’s Dependencies folder. Ensure “Copy items…” is unchecked.
  • On the XCode sidebar, open the “Targets”, “project name” so you can see the “Link Binary with Libraries” icon.
  • On the XCode sidebar, open the library project and drag the “lib*.a” into the just opened “Link Binary with Libraries” icon.
  • On the XCode sidebar, open “Targets”, “project name”, run “Get Info” (Command-i).
  • On the “Target “project name” Info” window, pick “General” tab, “Direct Dependencies” “+” icon, click on the library project icon.
  • Still on the “Target “project name” Info” window, pick “Build”. On the “Search in build settings”, enter “header search”.
  • On the “Header Search Path” item, add a new entry with the relative path of the library in the format (including the quotes, just in case any folder has spaces or special chars) “${PROJECT_DIR}/../{LibrariesFolder}/{LibraryFolder}/build/${BUILD_STYLE}-${PLATFORM_NAME}/usr/local/include” (notice no “/” at the end)
  • Alternatively (specially if for some reason the “usr/local/include” is non existent, one can also set a folder like “${PROJECT_DIR}/../{LibrariesFolder}/{LibraryFolder}” (notice again the lack of “/” at the end, and the quotes around), and tick the “Recursive” checkbox.
  • Build the project.

Additional links: http://www.clintharris.net/2009/iphone-app-shared-libraries/

(Source: amateurinmotion.com)

How to calculate NSDate of midnight in iOS

- (NSDate *)midnightUTC {
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    [calendar setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];

    NSDateComponents *dateComponents = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit
                                                   fromDate:self];
    [dateComponents setHour:0];
    [dateComponents setMinute:0];
    [dateComponents setSecond:0];

    NSDate *midnightUTC = [calendar dateFromComponents:dateComponents];
    [calendar release];

    return midnightUTC;
}

Links: Billy Tobon answer at StackOverflow

(Source: stackoverflow.com)

How to measure time in nanoseconds

For example, for simple profiling.

#include <mach/mach_time.h>

// run this once
mach_timebase_info_data_t timer;
mach_timebase_info(&timer);

// this returns the current time in nanos, but not in a perfectly human readable format - e.g. don't expect it to be number-of-nanos-since-1970 or something, like the unixtime.
uint64_t start_time = mach_absolute_time();

// do something that takes time

// now calc the elapsed time
uint64_t now = mach_absolute_time();
int64_t elapsed = now - start_time;
elapsed *= timer.numer;
elapsed /= timer.denom;
printf("Elapsed time: %lld ns\n", elapsed);

How to show an CGImage into the screen

Here’s two of the ways to show an CGImage into the screen.

The first is to use the proper UIImageView and UIImage objects:

CGImage cgImage = ...; // the CGImage to show
UIImageView *imageView = ...; // the UIView to show into
imageView.image = [UIImage imageWithCGImage:cgImage];

The second one, faster it seems, is to load the image directly into the frame buffer:

CGImage cgImage = ...; // the CGImage to show
CALayer *layer = ...; // the CALayer to show into
layer.incoming = (id)cgImage;

To get a layer to show the image, just create a new CALayer, or reuse the layer from a UIView, using the UIView as a simple way to position the image at the right place.

(Source: iphonedevsdk.com)

How to enable HTTP GZip in NSURLConnection

For reference, the Cocoa NSURLConnection library *does* support transparent GZIP response decompression by default.

To enable it just set the corresponding HTTP header:

NSMutableURLRequest* req = [[NSMutableURLRequest alloc] init];
NSMutableDictionary* headers = [[NSMutableDictionary alloc] init];
[headers setObject:@"gzip, deflate" forKey:@"Accept-Encoding"];
// other headers
[req setAllHTTPHeaderFields:headers];
// continue request

How to handle touch in iOS

For the simplest version, add the following to your UIViewController:

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    NSSet* allTouches = [event allTouches];
    switch ([allTouches count]) {
        case 1: { // one finger 
            UITouch* touch = [[allTouches allObjects] objectAtIndex:0];
            switch ([touch tapCount]) {
                case 1: { // single tap
                    // do something
                    break;
                }
                case 2: { // double tap
                    // do something
                    break;
                }
            }
            break;
        }
    }
}

Now that we know how to deal with single an double taps, I’ll have to ask you to completely forget about this code. One of the things that saddens me the most are the apps that expect a single finger to be pressed, neglecting the whole multi-touch capability of the iOS devices. This gets more visible when the apps are used by kids - they will always either use more than one finger to try something (sometimes even the whole hand), or will put a finger on one corner of the screen while holding the iThing, and try to press something else on the other corner with the fingers of the other hand. Stop thinking from a PC perspective! Always expect multiple touches and process each touch and each finger as if a single finger would have been used.

(Source: iphonesdkarticles.com)

How to start in landscape mode in iOS

On the main info.plist file:

<key>UIInterfaceOrientation</key>
<string>UIInterfaceOrientationLandscapeRight</string>
<key>UISupportedInterfaceOrientations</key>
<array>
    <string>UIInterfaceOrientationLandscapeRight</string>
    <string>UIInterfaceOrientationLandscapeLeft</string>
</array>

Note: In case we’d want to support only a single landscape mode (either “right” or “left”, it would be possible to skip the UIViewController and have the window move the status via the UIApplication and have the view be rotated manually, but in this example we want to support both landscape modes so we can e.g. rotate the iThingy and still see the stuff at the right orientation.

Now we need a UIViewController with the following code:

- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation {
 return (interfaceOrientation == UIInterfaceOrientationLandscapeRight || interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}

And one possible trick to ensure the view size is correct after the rotation (in this case because of the space used by the status bar), load the stuff after the view is rotated with something like this:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    // does not work on the iPhone simulator if(fromInterfaceOrientation == UIInterfaceOrientationPortrait)

    if(!shown) {
        shown = YES; // add "BOOL shown;" to the interface
        [self show];
    }
}

How to convert coordinates into distance

Example in Objective-C / C:

const int earth = 6371; // in KM

float lat1 = 51.2318; // point 1
float lon1 = 6.7641; // point 1
float lat2 = 50.9446; // point 2
float lon2 = 6.9592; // point 2

float d = convert(lat1, lon1, lat2, lon2); // result in KM

float convert(float lat1, float lon1, float lat2, float lon2) {
    float rlat1 = lat1 * M_PI / 180;
    float rlat2 = lat2 * M_PI / 180;
    float rlon1 = lon1 * M_PI / 180;
    float rlon2 = lon2 * M_PI / 180;
    return acos(
            sin(rlat1) * sin(rlat2) +
            cos(rlat1) * cos(rlat2) * cos(rlon2-rlon1)
           ) * earth;

(Source: movable-type.co.uk)

How to crop an image in iOS

Or how to cut multiple sprites from a single image:

UIImage* largeImage = ...;
UIImage* crop = [self crop:largeImage rect:CGRectMake(x, y, w, h)];

- (UIImage*)crop:(UIImage *)largeImage rect:(CGRect)cropRect {
    CGImageRef imageRef = CGImageCreateWithImageInRect(
        [largeImage CGImage], cropRect);
    UIImage* crop = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
    return crop;

(Source: stackoverflow.com)