.gitignore for iOS projects

You just started to use git with your iOS projects and wants to know which files you should’t track for version control? Here is a list of files you should’t track which using git –

*~
.DS_Store

# old skool
.svn

# Exclude the build directory
build/*

# Exclude temp nibs and swap files
*~.nib
*.swp


# Exclude user-specific XCode 3 and 4 files
*.mode1
*.mode1v3
*.mode2v3
*.perspective
*.perspectivev3
*.pbxuser
*.xcworkspace
xcuserdata
*.xcodeproj/ !*.xcodeproj/project.pbxproj

 
#    NB: also, whitelist the default ones, some projects need to use these
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3



# osx noise
.DS_Store
*.swp
*.lock
profile

You just need to create a .gitignore file in your project directory and put the above content in that file.

Check iOS version and write conditional code

I strongly recommend not to use iOS version numbers to write conditional code. There is usually a more reliable method of checking whether a particular feature available or not. But if you are in a deadly situation and hardly needed the version number then you can get iOS version number by UIDevice class. Here is the real code –


NSString *currSysVer = [[UIDevice currentDevice] systemVersion];

Here is how you can use this to write conditional code –


// A system version of 3.1 or greater is required to use CADisplayLink. The NSTimer
// class is used as fallback when it isn't available.
NSString *reqSysVer = @"3.1";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
    displayLinkSupported = TRUE;

Above code works great but writing this condition is real pain every time. The solution of this is Macros. We can use Macros in objective c and reduce the line of code in above code.

Here is real code using Macros –

/*
 *  System Versioning Preprocessor Macros
 */ 

#define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)


And how we can use these Macros to write conditional code –


/*
 *  Usage
 */ 

if (SYSTEM_VERSION_LESS_THAN(@"4.0")) {
    ...
}

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"3.1.1")) {
    ...
}

Hope these Macros will save someone’s time.

Detecting user inactivity/idle time since last touch on screen

Recently I required to find inactivity of screen in one of my iPad project.  Here is the steps by which I completed this task.

Step 1 –  Add a class (IdleTimeCheck) in your project which subclass UIApplication. In the implementation file, override the sendEvent: method like so:


- (void)sendEvent:(UIEvent *)event {
[super sendEvent:event];

// Only want to reset the timer on a Began touch or an Ended touch, to reduce the number of timer resets.
NSSet *allTouches = [event allTouches];
if ([allTouches count] > 0) {
// allTouches count only ever seems to be 1, so anyObject works here.
UITouchPhase phase = ((UITouch *)[allTouches anyObject]).phase;
if (phase == UITouchPhaseBegan || phase == UITouchPhaseEnded)
[self resetIdleTimer];
}
}

- (void)resetIdleTimer {
if (idleTimer) {
[idleTimer invalidate];
[idleTimer release];
}

idleTimer = [[NSTimer scheduledTimerWithTimeInterval:maxIdleTime target:self selector:@selector(idleTimerExceeded) userInfo:nil repeats:NO] retain];
}

- (void)idleTimerExceeded {
NSLog(@"idle time exceeded");
}

where maxIdleTime and idleTimer are instance variables.

Step 2 – Modify your UIApplicationMain function in main.m file to use your UIApplication subclass class as principal class.

int retVal = UIApplicationMain(argc, argv, @"IdleTimeCheck",nil);

And its done.

Hope it help someone who is looking for something like this.

Headphone plug-in plug-out event in iOS

To get the headphone plug-in plug-out event we need to employ a property listener callback function. The system invokes the callback when a user plugs in or unplugs a headset, or docks or undoes the device – thereby adding or removing an audio connection. The system also invokes the property listener callback when a Bluetooth device connects or disconnects.

Defining a Property Listener Callback Function

To respond to a route change, a property listener callback function must:

  • Identify the nature of the route change
  • Branch, depending on the specific route change and the current audio context (for example, recording, playback, or stopped)
  • Take or invoke appropriate action

Here is the example of this type of callback function. To see a similar callback function in working project you should see AddMusic sample code by Apple.

void audioRouteChangeListenerCallback (
void                   *inUserData,                                 // 1
AudioSessionPropertyID inPropertyID,                                // 2
UInt32                 inPropertyValueSize,                         // 3
const void             *inPropertyValue                             // 4
)

{

if (inPropertyID != kAudioSessionProperty_AudioRouteChange) return; // 5
MainViewController *controller = (MainViewController *) inUserData; // 6
if (controller.appSoundPlayer.playing == 0 ) {                      // 7
return;
} else {
CFDictionaryRef routeChangeDictionary = inPropertyValue;        // 8
CFNumberRef routeChangeReasonRef = CFDictionaryGetValue (routeChangeDictionary,CFSTR (kAudioSession_AudioRouteChangeKey_Reason));
SInt32 routeChangeReason;
CFNumberGetValue (routeChangeReasonRef, kCFNumberSInt32Type, &routeChangeReason);
if (routeChangeReason ==  kAudioSessionRouteChangeReason_OldDeviceUnavailable) {  // 9

[controller.appSoundPlayer pause];
UIAlertView *routeChangeAlertView =    [[UIAlertView alloc] initWithTitle: @"Playback Route Changed"  message: @"Audio output was changed." delegate:nil cancelButtonTitle: @"Ok" otherButtonTitles:nil];
[routeChangeAlertView show];

}

}

}

Here’s how this code works:

  1. A pointer to data that you provide when initializing your audio session.In an Objective-C class file, such as a view controller class, you place the property listener callback function outside of the class implementation block. Because of this, the callback needs a reference to the controller object to be able to send messages to it. You provide this reference when initializing your audio session.
  2. The identifier for the property that this callback function gets notified about.
  3. The size, in bytes, of the data in the inPropertyValue parameter.
  4. The current value of the property that this callback function is monitoring. Because the property being monitored is the kAudioSessionProperty_AudioRouteChange property, this value is a CFDictionary object.
  5. Ensures that the callback was invoked for the correct audio session property change.
  6. Initializes a MainViewController object instance to the reference passed in by the inUserData parameter. This allows the callback to send messages to your view controller object—typically defined in the same file that implements the callback.
  7. If application sound is not playing, there’s nothing to do, so return.
  8. This line and the next several lines determine the reason for the route change. The one route change of interest in this playback-only example is that an output device, such as a headset, was removed.
  9. If an output device was indeed removed, then pause playback and display an alert that allows the user to stop or resume playback.

Registering Your Property Listener Callback with the Audio Session

Your application can listen for hardware and route change events by way of the property mechanism in Audio Session Services. For example, to listen for route change events, you register a callback function with your audio session object, as shown here.

AudioSessionPropertyID routeChangeID =  kAudioSessionProperty_AudioRouteChange;    // 1

AudioSessionAddPropertyListener (                                  // 2

routeChangeID,                                                 // 3

audioRouteChangeListenerCallback,                                      // 4

userData                                                       // 5

);

Here’s how this code works:

  1. Declares and initializes a variable to the identifier for the property you want to monitor.
  2. Registers your property listener callback function with your initialized audio session.
  3. The identifier for the property you want to monitor.
  4. A reference to your hardware listener callback function.
  5. Data you want the audio session to pass back to your callback function.

Automatic Reference Counting (ARC) in Xcode 4.2

Xcode 4.2 now includes a new feature called Automatic Reference Counting aka. ARC which automates memory management for Objective-C objects. ARC makes memory management much easier, greatly reducing the chance that your program will have memory leaks. First, Xcode reviews your project to determine whether there are items that cannot be converted (and that you must therefore change manually). Then, Xcode rewrites your source code to use ARC.

ARC works by adding code at compile time to ensure that objects live as long as necessary, but no longer. Conceptually, it follows the same memory management conventions as manual reference counting, by adding the appropriate retain, release, and autorelease method calls for you.

ARC is supported in Xcode 4.2 for Mac OS X v10.6 and v10.7 (64-bit applications) and for iOS 4 and iOS 5. Weak references are not supported in Mac OS X v10.6 and iOS 4.

Instead of you having to remember when to use retain, release, and autorelease, ARC evaluates the lifetime requirements of your objects and automatically inserts the appropriate method calls for you at compile time. The compiler also generates appropriate dealloc methods for you. In general, if you’re only using ARC the traditional Cocoa naming conventions are important only if you need to interoperate with code that uses manual reference counting.

A complete and correct implementation of a Person class might look like this:

@interface Person : NSObject
@property (nonatomic, strong) NSString *firstName;
@property (nonatomic, strong) NSString *lastName;
@property (nonatomic, strong) NSNumber *yearOfBirth;
@property (nonatomic, strong) Person *spouse;
@end

@implementation Person
@synthesize firstName, lastName, yearOfBirth, spouse;
@end

Using ARC, you could implement a contrived method like this:

- (void)contrived {
    Person *aPerson = [[Person alloc] init];
    [aPerson setFirstName:@"William"];
    [aPerson setLastName:@"Dudney"];
    [aPerson:setYearOfBirth:[[NSNumber alloc] initWithInteger:2011]];
    NSLog(@"aPerson: %@", aPerson);
}

ARC takes care of memory management so that neither the Person nor the NSNumber objects are leaked.

You could also safely implement a takeLastNameFrom: method of Person like this:

- (void)takeLastNameFrom:(Person *)person {
    NSString *oldLastname = [self lastName];
    [self setLastName:[person lastName]];
    NSLog(@"Lastname changed from %@ to %@", oldLastname, [self lastName]);
}

ARC ensures that oldLastName is not deallocated before the NSLog statement.

ARC Enforces New Rules
To work, ARC imposes some new rules that are not present when using other compiler modes. The rules are intended to provide a fully reliable memory management model; in some cases, they simply enforce best practice, in some others they simplify your code or are obvious corollaries of your not having to deal with memory management. If you violate these rules, you get an immediate compile-time error, not a subtle bug that may become apparent at runtime.

  • You cannot explicitly invoke dealloc, or implement or invoke retain, release, retainCount, or autorelease.The prohibition extends to using @selector(retain), @selector(release), and so on.

    You may implement a dealloc method if you need to manage resources other than releasing instance variables. You do not have to (indeed you cannot) release instance variables, but you may need to invoke [systemClassInstance setDelegate:nil] on system classes and other code that isn’t compiled using ARC.

    Custom dealloc methods in ARC do not require a call to [super dealloc] (it actually results in a compiler error). The chaining to super is automated and enforced by the compiler.

    You can still use CFRetain, CFRelease, and other related functions with Core Foundation-style objects (see “Managing Toll-Free Bridging”).

  • You cannot use NSAllocateObject or NSDeallocateObject.You create objects using alloc; the runtime takes care of deallocating objects.
  • You cannot use object pointers in C structures.Rather than using a struct, you can create an Objective-C class to manage the data instead.
  • There is no casual casting between id and void *.You must use special casts that tell the compiler about object lifetime. You need to do this to cast between Objective-C objects and Core Foundation types that you pass as function arguments. For more details, see “Managing Toll-Free Bridging”.
  • Cannot use NSAutoreleasePool objects.ARC provides @autoreleasepool blocks instead. These have an advantage of being more efficient than NSAutoreleasePool.
  • You cannot use memory zones. There is no need to use NSZone any more—they are ignored by the modern Objective-C runtime anyway.

To allow interoperation with manual retain-release code, ARC imposes some constraints on method and variable naming:

You cannot give a property a name that begins with new.

Where is MainWindow.xib in Xcode 4.2 ?

In Xcode 4.2 the MainWindow.xib is not included for some of the project templates. Its means now we have to generate GUI elements by code or we can reconstruct the MainWindow.xib in project. I am describing you the second option here.

If you create a new project in XCode 4.2, and choose the Empty Application template to start from, change nothing and try running it in your iPhone 5.0 simulator, you will see an empty – black – screen. The only thing you get from the template is an AppDelegate.h and AppDelegate.m.

We’ll now reconstruct the MainWindow.xib file in our project. So the next thing is now to create a empty user interface file. Choose iOS > User Interface > Empty as template. The name of this file is not very important but we’ll use MainWindow.xib because this name is familiar to us.

Now select the Empty MainWindow.xib file we just created in previous step.

Change the Class of File’s Owner to UIApplication

Now drop a Object from Library to Objects in xib file.

Change the class of that object to the AppDelegate class

sd

Now add a window to objects pane.

Now we need to bind this window object to our code. To do this we have to add IBOutlet to window object in AppDelegate.h file. You code of AppDelegate.h should look like this –
</pre>
#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) IBOutlet UIWindow *window;

@end

Note the IBOutlet just before UIWindow.

Now continue with editing MainWindow.xib file –

Control-Drag from the delegate outlet of the File Owner to the xAppDelegate object.

Control-Drag from the window outlet of the xAppDelegate to the Window.

Navigate to the project, and in the Summary tab, select MainWindow as the Main Interface.

We are almost done now..  But there is one more thing we need to fix. In AppDelegate.m, there was actually code that creates a window as well, so we have to delete this code.

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

We are done now

How to find IP Address of iPhone

Programmatically get IP Address of iPhone/iPad/iPod

The iOS SDK does not provide any simple way to get IP address of device programmatically. So the only way left is to get it by c code. So here we go –

Step 1 – Add these header file in your code –

 #include &amp;lt;ifaddrs.h&amp;gt;
#include &amp;lt;arpa/inet.h&amp;gt;
 

Step 2 – And here is the real code –


- (NSString *)getIPAddress { 
	
	NSString *address = @&amp;quot;error&amp;quot;; 
	struct ifaddrs *interfaces = NULL; 
	struct ifaddrs *temp_addr = NULL; 
	int success = 0; 
	// retrieve the current interfaces - returns 0 on success 
	success = getifaddrs(&amp;amp;interfaces); 
	if (success == 0) { 
		// Loop through linked list of interfaces 
		temp_addr = interfaces; 
		while(temp_addr != NULL) { 
			if(temp_addr-&amp;gt;ifa_addr-&amp;gt;sa_family == AF_INET) { 
				// Check if interface is en0 which is the wifi connection on the iPhone 
				if([[NSString stringWithUTF8String:temp_addr-&amp;gt;ifa_name] isEqualToString:@&amp;quot;en0&amp;quot;]) { 
					// Get NSString from C String 
					address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr-&amp;gt;ifa_addr)-&amp;gt;sin_addr)]; 
					
					
				} 
				
			} 
			
			temp_addr = temp_addr-&amp;gt;ifa_next; 
		} 
	} 
	// Free memory 
	freeifaddrs(interfaces); 
	return address; 
	
} 

Hope it saves someone’s time!

How to “add existing frameworks” in Xcode 4?

Are you not getting how to add existing frameworks in xcode 4?

Are you not getting how to add existing frameworks in xcode 4?
Well here is the right way of doing it –

1. In the project navigator, select your project
2. Select your target
3. Select the ‘Build Phases’ tab
4. Open ‘Link Binaries With Libraries’ expander
5. Click the ‘+’ button
6. Select your framework
7. (optional) Drag and drop the added framework to the ‘Frameworks’ group

How to prevent apps to being installed on wrong or incapable devices

If you app absolutely depends on a feature you should prevent the user from installing the app on their device if that particular feature is not available.

There may be cases when your app does not run because the device does not have front camera (or any such feature which is required to run the app). You can always check the device capabilities before using the special feature (check my this post if you don’t know how), But if you app absolutely depends on the feature you should prevent users from installing your app. The real question here is how can you prevent users from installing the app. The answer is UIRequiredDeviceCapabilities key in your info.plist file.

UIRequiredDeviceCapabilities (Array or Dictionary – iOS) lets iTunes and the App Store know which device-related features an application requires in order to run. iTunes and the mobile App Store use this list to prevent customers from installing applications on a device that does not support the listed capabilities.
If you use an array, the presence of a given key indicates the corresponding feature is required. If you use a dictionary, you must specify a Boolean value for each key. If the value of this key is true, the feature is required. If the value of the key is false, the feature must not be present on the device. In both cases, omitting a key indicates that the feature is not required but that the application is able to run if the feature is present.
You should include keys only for the features that your application absolutely requires. If your application can accommodate missing features by avoiding the code paths that use those features, do not include the corresponding key.
Here is a list of all the keys and their meaning –

telephony
Include this key if your application requires (or specifically prohibits) the presence of the Phone application. You might require this feature if your application opens URLs with the tel scheme.

wifi
Include this key if your application requires (or specifically prohibits) access to the networking features of the device.

sms
Include this key if your application requires (or specifically prohibits) the presence of the Messages application. You might require this feature if your application opens URLs with the sms scheme.

still-camera
Include this key if your application requires (or specifically prohibits) the presence of a camera on the device. Applications use the UIImagePickerController interface to capture images from the device’s still camera.

auto-focus-camera
Include this key if your application requires (or specifically prohibits) auto-focus capabilities in the device’s still camera. Although most developers should not need to include this key, you might include it if your application supports macro photography or requires sharper images in order to do some sort of image processing.

front-facing-camera
Include this key if your application requires (or specifically prohibits) the presence of a forward-facing camera. Applications use the UIImagePickerController interface to capture video from the device’s camera.

camera-flash
Include this key if your application requires (or specifically prohibits) the presence of a camera flash for taking pictures or shooting video. Applications use the UIImagePickerController interface to control the enabling of this feature.

video-camera
Include this key if your application requires (or specifically prohibits) the presence of a camera with video capabilities on the device. Applications use the UIImagePickerController interface to capture video from the device’s camera.

accelerometer
Include this key if your application requires (or specifically prohibits) the presence of accelerometers on the device. Applications use the classes of the Core Motion framework to receive accelerometer events. You do not need to include this key if your application detects only device orientation changes.

gyroscope
Include this key if your application requires (or specifically prohibits) the presence of a gyroscope on the device. Applications use the Core Motion framework to retrieve information from gyroscope hardware.

location-services
Include this key if your application requires (or specifically prohibits) the ability to retrieve the device’s current location using the Core Location framework. (This key refers to the general location services feature. If you specifically need GPS-level accuracy, you should also include the gps key.)

gps
Include this key if your application requires (or specifically prohibits) the presence of GPS (or AGPS) hardware for greater accuracy when tracking locations. If you include this key, you should also include the location-services key. You should require GPS only if your application needs more accurate location data than the cell or Wi-fi radios might otherwise allow.

magnetometer
Include this key if your application requires (or specifically prohibits) the presence of magnetometer hardware. Applications use this hardware to receive heading-related events through the Core Location framework.

gamekit
Include this key if your application requires (or specifically prohibits) Game Center (iOS 4.1 and later.)

microphone
Include this key if your application uses the built-in microphone or supports accessories that provide a microphone.

opengles-1
Include this key if your application requires (or specifically prohibits) the presence of the OpenGL ES 1.1 interfaces.

opengles-2
Include this key if your application requires (or specifically prohibits) the presence of the OpenGL ES 2.0 interfaces.

armv6
Include this key if your application is compiled only for the armv6 instruction set. (iOS v3.1 and later.)

armv7
Include this key if your application is compiled only for the armv7 instruction set. (iOS v3.1 and later.)

peer-peer
Include this key if your application requires (or specifically prohibits) peer-to-peer connectivity over Bluetooth. (iOS v3.1 and later.)

How to remove gloss/shine effect from iPhone app icon

You can remove the icon gloss from iPhone app icon.

By default, when building an application with Xcode, your icon will have a round beveling of the corners and a shine added over the top of the icon.
You can override this default by adding this following key in your info.plist file.

<key>UIPrerenderedIcon</key>
<true/>