Monday, June 16, 2014

Short tutorial for NSLayoutConstraint

When I started developing Jano I was still creating my interfaces using the initWithFrame constructor. This approach was... painful :). So I started to search for other ways to create the interface. Of course, there was the option to use XIBs, but I did not want that. This is how I found the NSLayoutConstraint class.

In this post I will use the NSLayoutConstraint class to add a label to an UIViewController on a IOS app.

Setting things up

For this demonstration I will use the Achievements view controller in my app. This is where you can see the achievements that you get in the app, the badges, the points, etc.

I prefer to create the interface elements in a separate class so I that my ViewController remains as clean as possible. Here I have the AchivementsViewController and the AchievementsViewControllerInterfaceTool.

The AchievementsViewController.h is defined as follows:



#import <UIKit/UIKit.h> 

#import "AchievementsViewControllerInterfaceTool.h"



@interface AchievementsViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> 



@property (nonatomic, strong) UILabel *lblTest;

@property (nonatomic, strong) UITableView *tableView;



@end


The AchievementsViewControllerInterfaceTool.h is defined as follows:

#import <Foundation/Foundation.h>

#import "AchievementsViewController"



@class AchievementsViewController;

@interface AchievementsViewControllerInterfaceTool : NSObject





@property (nonatomic, strong) AchievementsViewController* controller;





-(id)initWithController:(AchievementsViewController*)controller;

-(void)AddTestLabel;

-(void)AddTableView;



@end


Since both classes will reference one another (thus creating a circular dependency), in the interface tool I will add a forward declaration to the AchievementsViewController class: @class AchievementsViewController.

I will also add a table view using this class, but here I will show only how to add a UILabel to the view.

This is how AchievementsViewControllerInterfaceTool.m looks like:

#import "AchievementsViewControllerInterfaceTool.h"



@implementation AchievementsViewControllerInterfaceTool
@synthesize controller = _controller;

-(id)initWithController:(AchievementsViewController *)controller
{
       self = [super init];
       if (self) {

          _controller = controller;

       }
       return self;
}


-(void)AddTestLabel
{

_controller.lblTest = [[[UILabel alloc] init] autorelease];
_controller.lblTest.text = @"Achievements View Controller";
_controller.lblTest.translatesAutoresizingMaskIntoConstraints = NO;

[_controller.view addSubview:_controller.lblTest];
UILabel *lbl = _controller.lblTest;

NSArray * constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-100-[lbl]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(lbl)];


[_controller.view addConstraints:constraints];

NSLayoutConstraint *c1 = [NSLayoutConstraint constraintWithItem:lbl
                             attribute:NSLayoutAttributeCenterX
                             relatedBy:NSLayoutRelationEqual
                             toItem:lbl.superview
                             attribute:NSLayoutAttributeCenterX
                             multiplier:1
                             constant:0];



[_controller.view addConstraint:c1];

}

I have created a constructor that takes as parameter a reference to the AchievementsViewController and assigns it to our internal variable, _controller.

In the first part of the AddTestLabel method I instantiate the UILabel lblTest and set the property translatesAutoresizingMaskIntoConstraints to NO. For more information about this property you can check the official documentation here.

I then define UILabel *lbl = _controller.lblTest. This is because in the next statement I have to define the visual format for the NSLayoutConstraint: "V:|-100-[lbl]". This means that I will set the label 100 spaces from the top of the superview. The superview is marked by the "|" character.

In the next constraint (c1) I set the label at the center of the superview, on the X axis only.

No comments:

Post a Comment