Category Archives: iOS

Understanding CALayer anchorPoint and position property

For me understanding position and anchorPoint was easiest when I started comparing it with my understanding of frame.origin in UIView. A UIView with frame.origin = (20,30) means that the UIView is 20 points from left and 30 points from top of its parent view. This distance is calculated from which point of a UIView? Its calculated from top-left corner of a UIView.

In layer anchorPoint marks the point (in normalized form or unit-coordinates i.e. 0 to 1) from where this distance is calculated so e.g. layer.position = (20, 30) means that the layer anchorPoint is 20 points from left and 30 points from top of its parent layer. By default a layer anchorPoint is (0.5, 0.5) so the distance calculation point is right in the center of the layer. The following figure will help clarify my point:

anchorPoint also happens to be the point around which rotation will happen in case you apply a transform to the layer.

Advertisements

Supporting Custom URL Schemes in iOS App

To enable your iOS app to respond to custom URLs from third party application you need to do some changes. If you want the app to respond to click of following url scheme:

talsa://article/ios?id=201244075

The URL should follow format: scheme://host/path?query and the following changes need to be done in xcode project .plist file:

plist

The app delegate should provide a similar custom implementation:

-(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
    if ([[url absoluteString] hasPrefix:@"talsa"]) //talsa
    {
        NSDictionary* parameters = [self parseQueryString:[url query]];
        NSString* articleId = [parameters valueForKey:@"id"];
        if (articleId != nil)
        {
            //do something here, open a view or whatever
        }
        return YES;
    }
    return NO;
}

- (NSDictionary *)parseQueryString:(NSString *)query
{
    NSMutableDictionary *dict = [[[NSMutableDictionary alloc] init] autorelease];
    NSArray *pairs = [query componentsSeparatedByString:@"&"];

    for (NSString *pair in pairs)
    {
        NSArray *elements = [pair componentsSeparatedByString:@"="];
        NSString *key = [[elements objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        NSString *val = [[elements objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

        [dict setObject:val forKey:key];
    }
    return dict;
}

In circumstances where url is more complicated e.g. it included another url as input parameter then URL would need to be specified in URL encoded form: http://www.w3schools.com/TAGS/ref_urlencode.asp i.e.

URL in encoded form:

scheme://url_identifier/ios?accesscode=123456789&callback=http%3A%2F%2Fwww%2Efoo%2Ecom

URL in normal form:

scheme://url_identifier/ios?accesscode=123456789&callback=http://www.foo.com

Shake animation to a UIView or UIButton

I think button shake is such a nice effect that could be applied to different views especially in cases where you want to indicator an error. On a mobile device where you are limited for screen space a shake effect is even more elegant.

Lets see the button shake in action first:

And here is the small objectiveC code that you can use to produce a similar effect for any UIView, call startShake on the view you want to shake:

- (void) startShake:(UIView*)view
{
    CGAffineTransform leftShake = CGAffineTransformMakeTranslation(-5, 0);
    CGAffineTransform rightShake = CGAffineTransformMakeTranslation(5, 0);

    view.transform = leftShake;  // starting point

    [UIView beginAnimations:@"shake_button" context:view];
    [UIView setAnimationRepeatAutoreverses:YES]; // important
    [UIView setAnimationRepeatCount:5];
    [UIView setAnimationDuration:0.06];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(shakeEnded:finished:context:)];

    view.transform = rightShake; // end here & auto-reverse

    [UIView commitAnimations];
}

- (void) shakeEnded:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
{
    if ([finished boolValue]) {
        UIView* item = (UIView *)context;
        item.transform = CGAffineTransformIdentity;
    }
}

FAQ on iOS5 Storyboard

Designing iOS user interface with storyboard was introduced in iOS5. It helps to know of the following classes: UIStoryboardUIStoryboardPopoverSegueUIStoryboardSegue. The recommended practice is to have one storyboard for the entire application. I’ll address some of the common questions related to storyboard.

1. How do you pass data between two view controllers in storyboard?
You do that by overriding – [UIViewController prepareForSeque:sender:]. It is invoked on the source view controller and data can be passed back to source view controller by providing implementation of your own custom delegate. The source view controller can be accessed by [segue sourceViewController] and destination view controller can be accessed by [segue destinationViewController].

2. What is a static table view cell?
Table view cells that you can design inline and don’t need a data source. For static cells to work the view needs to be in a UITableViewController.

3. What is a dynamic table view cell?
The most common way of providing a table view cell. You can design it in the xib and it needs a table view data source. A very nice feature of storyboard.

4. How do you set which view controller is the first one to show?
Select a view controller and in Utilities pane go to Attributes Inspector, there check the property ‘Is Initial View Controller’.

5. How to add navigation controller to an existing view controller in storyboard?
From Menu you do: (Editor -> Embed In -> Navigation Controller)

6. How do you set delegate of destination view controller during transition?
Inside – [UIViewController prepareForSeque:sender:] you do [segue destinationViewController].delegate = self

7. How do you programmatically load a storyboard in AppDelegate or for that matter anywhere else?
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@”MainStoryboard” bundle:nil];
self.window.rootViewController = (UINavigationController*)[storyboard instantiateInitialViewController];

(MainStoryboard is name of your storyboard file, replace it in case you use a different name)

See also -[UIStoryboard instantiateViewControllerWithIdentifier:]

8. How do you access a storyboard from within a view controller?
– [UIViewController storyboard]

9. How do you provide a custom segue?
By subclassing UIStoryboardSegue and overriding – [UIStoryboardSegue perform]. Inside method perform you can access source and destination view controllers by [self sourceViewController], [self destinationViewController]

10. How do you close a view controller opened as modal through segue transition?
-[UIViewController dismissModalViewControllerAnimated:]

11. How do you programmatically perform a segue transition?
The segue has to be specified by an identifier in the xib and then the source view controller can call
– [UIViewController performSegueWithIdentifier:sender:]

Feel free to leave a comment if you like any other questions answered.