How to switch the code/build for the device or simulator

“My Pacakge” uses AdMob for showing ad in the application. The bad thing about AdMob library is it is not compatible with iOS 4 simulator (so many linking error occurs). I found the way to avoid these errors in the apple document. Switching code with pre-processor macros and exclude AdMob library from simulator build are the answer.

Compiling Source Code Conditionally for iOS Applications
There may be times when you need to run code on the simulator but not on a device, and the other way around. On those occasions, you can use the preprocessor macros TARGET_OS_IPHONE and TARGET_IPHONE_SIMULATOR to conditionally compile code.

So I changed the code like below to remove AdMob lib dependency for the iPhone simulator build.

#if TARGET_IPHONE_SIMULATOR
  UIView *ad;
#else
  AdMobView *ad;
#endif

One more thing necessary for switching the code is library linking. Build setting needs conditional linking otherwise linking error occurs.

Opening Project info dialog then select Build tab. Find “Other Linker Flags” setting and select “Add Build Setting Condition” from Action menu (lower left corner menu).

Custom Linker Setting

You can pick up conditions of sdk (device or simulator and its versions) and specify library or framework link settings (or other build settings).

Link:

Editing Conditional Build Settings (developer.apple.com)

Now you can automatically switch setting based on device or simulator.

How to trigger MKAnnotationView’s callout view without touching the pin? – Stack Overflow

But there is a catch to get benvolioT's solution to work, the code

for (id currentAnnotation in mapView.annotations) {
  if ([currentAnnotation isEqual:annotationToSelect]) {
    [mapView selectAnnotation:currentAnnotation animated:FALSE];
  }
}

should be called from – (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView, and nowhere else.

The sequence in which the various methods like viewWillAppear, viewDidAppear of UIViewController and the – (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView is called is different between the first time the map is loaded with one particular location and the subsequent times the map is displayed with the same location. This is a bit tricky.

via How to trigger MKAnnotationView’s callout view without touching the pin? – Stack Overflow.

Functions for CGRect

In the cocoa (cocoa touch) framework, CGRect structure are used in many places because its rendering system depends on Core Graphics library. Here are the useful functions for CGRect structure.

Function Description
CGRectMake() Creates CGRect structure from integer values

// creates CGRect with  x=0, y=0, width=100, height=100
CGRect rect = CGRectMake(0, 0, 100, 100);
CGRectFromString() Creates CGRect structure from string

// creates CGRect with x=10, y=20, width=100, height=200
CGRect rect = CGRectFromString(@"{{10, 20}, {100, 200}}");
NSStringFromCGRect() Creates NSString object for specified CGRect structure. It is same format as the argument for CGRectFromString().

CGRect rect = CGRectMake(0, 0, 100, 100);

// outputs {{0, 0}, {100, 100}}
NSLog(@"%@", NSStringFromCGRect(rect));
CGRectEqualToRect() Checks whether given two CGRect are equal in both size and position.

CGRect rect1 = CGRectMake(0, 0, 100, 100);
CGRect rect2 = CGRectMake(10, 20, 100, 100);

// returns false
CGRectEqualToRect(rect1, rect2);
CGRectIntersection() Returns the intersection of two rectangles. Note that if two rectangles do not intersect, it returns the null rectangle.

CGRect rect1 = CGRectMake(0, 0, 100, 100);
CGRect rect2 = CGRectMake(10, 20, 100, 100);
CGRect intersect = CGRectIntersection(rect1, rect2);

// returns {{10, 20},{90, 80}}
NSLog(@"%@", NSStringFromCGRect(intersect));
CGRectIsNull() Checks null

CGRect rect1 = CGRectMake(0, 0, 100, 100);
CGRect rect2 = CGRectMake(200, 200, 100, 100);
CGRect intersect = CGRectIntersection(rect1, rect2);

// returns YES (1)
NSLog(@"%d", CGRectIsNull(intersect));

There are more functions for this purpose. Check Apple’s website for the detail.

How to change the carrier name in the iPhone simulator

iPhone simulator shows “Carrier” as default carrier name. You can change this name whatever text you want.

1. Open ~/Library/Application Support/iPhone Simulator/User/Library/Preferences/com.apple.springboard.plist file with Property List Editor application

2. Add a new Row with key name “SBFakeCarrier”.

3. Set its value as whatever you want.

Property List Editor

4. Save plist file and that’s it. You will see the text you entered in step 3 in the iphone simulator.

Open URL from application

Pretty simple. This call terminates the application and starts Mobile Safari browser with specified URL.

  [[UIApplication sharedApplication] openURL: [NSURL URLWithString: @"http://www.apple.com/"]];

How to remember the setting (user defaults) easily

NSUserDefautls object automatically loads and saves small information. Along with primitive value like BOOL, integer or float, NSUserDefaults can handle objects like NSArray, NSData, NSDictionary, NSString.

// Save a default
[[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"ShowWarning"];

// Read  BOOL warning value from NSUserDefaults
BOOL showWarning = [[NSUserDefaults standardUserDefaults] boolForKey:@"ShowWarning"];

setObject: method is for setting class object and boolForKey: method is specifically used for getting BOOL value.

Capture view contents into an UIImage object

By combining UIGraphicsBeginImageContext() and -renderInContext in CALayer, you can draw contents into a image (UIImage) object. It is like screen capture.

UIGraphicsBeginImageContext(view.frame.size);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

CGContextTranslateCTM() modifies the x- and y- coordinates (otherwise it starts from (0,0)). By using CGContextTranslateCTM(), you can change the start capturing point so that it can capture limited area in the UIScrollView content.

CGSize pageSize = CGSizeMake(320, 480);
int currentPage = 2;
UIGraphicsBeginImageContext(pageSize);
CGContextRef resizedContext = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(resizedContext, 320 * currentPage, 0);
[scrollView.layer renderInContext:resizedContext];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Ref:
Capture UIImage with offset into UIScrollView

Set border around the view

There is no border property in UIView…. classes but we can access CALayer class to set border. Since layer property is defined in the UIView class, all of UIView inherited class can use this property to set border. It needs to have #import <QuartzCore/QuartzCore.h> to access CALayer.

view.layer.borderWidth = 1;
view.layer.borderColor = [[UIColor grayColor] CGColor];

Accessing AppDelegate instance

AppDelegate object can access from any class in the same application like below. Methods or properties shared between controllers can be defined under application delegates.

SomeAppDelegate *appDelegate
  = (SomeAppDelegate *)[[UIApplication sharedApplication] delegate];

How to access special directory on the iphone device

Use NSSearchPathForDirectoriesInDomains(). First argument “NSDocumentDirecotry” is the key to specify special directory, in this case Document directory under the application. The method returns absolute path expression.

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                               NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSLog(@"NSDocumentDirectory is %@", documentsDirectory);

Following is the list of the special directory key and result. Some keys are defined in the header file but actually they return nothing.

NSApplicationDirectory: /var/mobile/Applications/{APPID}/Applications
NSDemoApplicationDirectory: /var/mobile/Applications/{APPID}/Applications/Demos
NSDeveloperApplicationDirectory: /var/mobile/Applications/{APPID}/Developer/Applications
NSAdminApplicationDirectory: /var/mobile/Applications{APPID}/Applications/Utilities
NSLibraryDirectory: /var/mobile/Applications/{APPID}/Library
NSDeveloperDirectory: /var/mobile/Applications/{APPID}/Developer
NSUserDirectory: Not found
NSDocumentationDirectory: /var/mobile/Applications{APPID}/Library/Documentation
NSDocumentDirectory: /var/mobile/Applications{APPID}/Documents
NSCoreServiceDirectory: Not found
NSDesktopDirectory: /var/mobile/Applications/{APPID}/Desktop
NSCachesDirectory: /var/mobile/Applications/{APPID}/Library/Caches
NSApplicationSupportDirectory: /var/mobile/Applications/{APPID}/Library/Application Support
NSDownloadsDirectory: /var/mobile/Applications/{APPID}/Downloads
NSAllApplicationsDirectory: /var/mobile/Applications/{APPID}/Applications
NSAllLibrariesDirectory: /var/mobile/Applications{APPID}/Library