Lessons Building a Simple iOS + Backbone.js + Ruby on Rails App

03.10.2015

Recently, I spent some time learning how to tie together a Rails back-end, an iOS client, and a Backbone.js web interface. For future reference, I am writing this post of my notes during the development process.

Authentication

The first challenge was building an authentication system that would work for both a web and mobile client. Traditional Rails apps use a session based authentication system where users have their encrypted session id and user id passed along with every request. With Devise, you could have this mechanism all set up for you within minutes. Adding an iOS client requires a bit more thought and work. After some research, I ended up going with a JSON authentication solution by using the simple_token_authentication gem in conjunction with Devise. Every user that logs in gets an “authentication_token”, which is saved as a field on the User model. When a user logs in with correct credentials, they will receive the authentication token, which can be saved in memory on the iOS client. You can pass this token along with every request to authenticate the user.

Gemfile

gem 'simple_token_authentication'

user.rb

class User < ActiveRecord::Base
  acts_as_token_authenticatable
end

sessions_controller.rb

module Api
  module V1
    class SessionsController < Devise::SessionsController
      skip_before_action :verify_authenticity_token
      def create
        self.resource = warden.authenticate!(auth_options)
        sign_in(resource_name, resource)
        current_user.update authentication_token: nil
        respond_to do |format|
          format.json {
            render :json => {
              :user => current_user,
              :status => :ok,
              :authentication_token => current_user.authentication_token
            }
          }
        end
      end
    end
  end
end

LoginViewController.m

- (IBAction)signIn:(id)sender {
    NSString *requestString = @"http://localhost:3000/api/v1/sessions/create.json";
    NSURL *url = [NSURL URLWithString:requestString];
    NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
    [req setHTTPMethod:@"POST"];
    //NSDictionary *userDict = @{@"user": @{@"email": @"test@example.com", @"password": @"password"}};
    NSDictionary *userDict = @{@"user": @{@"email": self.username.text, @"password": self.password.text}};
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:userDict options:NSJSONWritingPrettyPrinted error:nil];
    [req setHTTPBody: jsonData];
    [req addValue:@"application/json" forHTTPHeaderField:@"Accept"];
    [req addValue:@"application/json" forHTTPHeaderField:@"Content-type"];
    NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (!error) {
            NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
            NSString *auth_token = [jsonObject objectForKey:@"authentication_token"];
            NSString *user_email = [[jsonObject objectForKey:@"user"] objectForKey:@"email"];
            NSDictionary *authInfo = @{@"email": user_email, @"authentication_token": auth_token};
            dispatch_async(dispatch_get_main_queue(), ^{
                AppDelegate *app = [UIApplication sharedApplication].delegate;
                app.authInfo = authInfo;
                app.session = self.session;
                [app setRoots];
            });
        } else {
            UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Error" message:@"There was an error." preferredStyle:UIAlertControllerStyleAlert];
            UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
            }];
            [alert addAction:defaultAction];
            [self presentViewController:alert animated:YES completion:nil];
        }
    }];
    [dataTask resume];
}

Backbone.js pushState

How do you handle anchor tags in a Backbone.js app? One way to deal with it is to use a “catch all” listener for any clicks on anchor tags. We override the default behavior and instead use Backbone’s routing system.

index.html.erb

$(function() {
  window.router = new PhotoCritic.Routers.PhotosRouter();
  Backbone.history.start({pushState: true});
    $(document).on('click', 'a:not([data-bypass])', function (evt) {
        var href = $(this).attr('href');
        var protocol = this.protocol + '//';
        if (href.slice(protocol.length) !== protocol) {
          evt.preventDefault();
          window.router.navigate(href, true);
        }
      });
});

nav.hbs

<div id="photo-critic-nav">
  <ul class="nav nav-tabs">
    <li><a href="/" id="home-link">Home</a></li>
    <li><a href="/photos/new" id="new-link">New Photo</a></li>
    <li><a href="/photos" id="photos-link">My Photos</a></li>
  </ul>
</div>

iOS Frame and Coordinate System

Understanding iOS’s frames and bounds was another hurdle that mostly came about as I was trying to position an Activity Indicator in the middle of the screen. A frame is made up of a CGRect struct, which has an x and y origin and width and height. Every view has a frame. The x and y origin is the top left point of of the view relative to the superview’s top left origin (0, 0). Center is the center of the view relative to the superview’s coordinate system.

iOS Protocols and Delegates

A protocol is essentially a set of “rules” that a class must follow. A class must implement certain methods in order to “conform” to a protocol. For instance the UIImagePickerControllerDelegate protocol must implement the - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info method to handle what happens when a user picks an image. The protocol must be declared in the interface of the controller.

NewPhotoViewController.m

@interface NewPhotoViewController () <UIImagePickerControllerDelegate>
@end

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    UIImage *image = info[UIImagePickerControllerOriginalImage];
    self.imageView.image = image;
    self.submitButton.hidden = NO;
    [self dismissViewControllerAnimated:YES completion:nil];
}

iOS ViewDidLoad vs. ViewDidLayoutSubviews

It is important to know that auto-layout gets applied after ViewDidLoad. If you are trying to edit the layout in code, you have to use ViewDidLayoutSubviews, otherwise the auto-layout from the interface builder will override your changes and you’ll be left wondering why your code layout changes aren’t working.

The App Delegate

The app delegate can be accessed anywhere from the application using AppDelegate *app = [UIApplication sharedApplication].delegate;.
This is useful when you need to change something stored at the root level in the view hierarchy or call a method that is defined in the app delegate implementation. In this app I use it to set the root view controller after the user logs in.

dispatch_async

If you try to call some methods on the main thread within an asynchronous process callback, you’ll likely get some unexpected results. You might need to call the dispatch_async method with the code you want to execute passed in as a block. For example, this is used to set the session information and new root view controller after a log in request and response is made.

LoginViewController.m

NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (!error) {
            NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
            NSString *auth_token = [jsonObject objectForKey:@"authentication_token"];
            NSString *user_email = [[jsonObject objectForKey:@"user"] objectForKey:@"email"];
            NSDictionary *authInfo = @{@"email": user_email, @"authentication_token": auth_token};
            dispatch_async(dispatch_get_main_queue(), ^{
                AppDelegate *app = [UIApplication sharedApplication].delegate;
                app.authInfo = authInfo;
                app.session = self.session;
                [app setRoots];
            });
        } else {
            UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Error" message:@"There was an error." preferredStyle:UIAlertControllerStyleAlert];
            UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { 
            }];
            [alert addAction:defaultAction];
            [self presentViewController:alert animated:YES completion:nil];
        }
    }];

Backbone PubSub

Publish Subscribe (PubSub) is a useful design pattern for sending notifications to different parts of the application. I needed this to implement the infinite scroll with Backbone.

class Backbone.PubSub extends Backbone.Events
Backbone.PubSub.on('loadMore', @loadMore)
Backbone.PubSub.trigger('loadMore')
Backbone.PubSub.off('loadMore')

Ajax File Uploads

To upload files with Ajax, you have to use the FormData object.

formData = new FormData()
formData.append('photo[pic]', input[0].files[0])
formData.append('photo[title]', title)
@model.data = formData
@model.unset("errors")
@model.validate()
$.ajax({
  url: '/api/v1/photos',
  data: formData,
  cache: false,
  contentType: false,
  processData: false,
  type: 'POST',
  success: (data) =>
    Backbone.history.navigate("/photos/#{data.photo.id}", {trigger: true})
  error: (model, xhr, options) ->
    alert('Error')
})

iOS Pointers

Certain variable declarations marked with an asterisk represents a pointer to an object. Those without asterisks are not pointers, but represent a C structure. Things like CGRect, Int, etc. It’s important to know how pointers work in Objective-C to understand memory management and Automatic Reference Counting (ARC), and to debug strong reference cycles should they happen to occur.

GitHub

https://github.com/travisluong/photo-critic
https://github.com/travisluong/photo-critic-client

Sources

http://jessewolgamott.com/blog/2012/01/19/the-one-with-a-json-api-login-using-devise/

http://provoost.tumblr.com/post/80873086965/json-api-authentication-using-devise-tokens

https://gist.github.com/josevalim/fb706b1e933ef01e4fb6

http://stackoverflow.com/questions/5082738/ios-calling-app-delegate-method-from-viewcontroller

http://stackoverflow.com/questions/1071112/uiviews-frame-bounds-center-origin-when-to-use-what

http://stackoverflow.com/questions/5361369/uiview-frame-bounds-and-center

http://stackoverflow.com/questions/8564833/ios-upload-image-and-text-using-http-post

http://stackoverflow.com/questions/18226267/changing-root-view-controller-after-ios-app-has-loaded

http://stackoverflow.com/questions/9984859/backbone-js-can-one-view-trigger-updates-in-other-views

http://stackoverflow.com/questions/5392344/sending-multipart-formdata-with-jquery-ajax

http://www.codeschool.com

http://www.bignerdranch.com/we-write/ios-programming/

iOS Gray Out View and Add an Activity Indicator in the Center

02.24.2015

Recently, I needed to figure out a way to gray out the screen with an activity indicator in the center in a scrollable table view.

This was the simplest way I’ve found to do that:

In the implementation file, create a class property to store the Y scroll offset.

@interface PhotosTableViewController () <UIPopoverControllerDelegate>
@property (nonatomic) CGFloat scrollY;
@end

Initialize the scrollY offset in initWithNibName.

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    
    if (self) {
        self.scrollY = 0.0;
    }
    return self;
}

Then implement the scrollViewDidScroll method that is part of the UIScrollViewDelegate protocol. We will capture the offset anytime the user scrolls.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
     self.scrollY = scrollView.contentOffset.y;
}

Then create the container view and indicator view. We set the Y origin of the container to the current scroll position.

CGRect maskFrame = CGRectMake(self.view.frame.origin.x, self.scrollY, self.view.frame.size.width, self.view.frame.size.height);
    
UIView *mask = [[UIView alloc] initWithFrame:maskFrame];
    
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
    
indicator.frame = self.view.frame;

[indicator startAnimating];
    
[mask addSubview:indicator];
    
[mask setBackgroundColor:[UIColor colorWithWhite:0.0 alpha:0.78]];
    
[self.view addSubview:mask];

And the code to remove the view:

 [mask removeFromSuperview];

Sources

http://stackoverflow.com/questions/1431021/gray-out-view-in-iphone-how

Undoing Published Commits with Git

02.24.2015

So let’s say I’ve done some work. I’ve made several commits and I’ve pushed them to GitHub. The next day, I decide that those commits are no good and I want to go back to the way things were at commit “0766c053″. How do I “get rid” of them?

This is something that happens quite often and I have to look up the solution each time. There are many different ways to handle this, but the simplest and safest way that I’ve found is to do this:

git revert --no-commit 0766c053..HEAD
git commit

That will bring the current state of the repository back the commit specified without overwriting history.

Sources

http://stackoverflow.com/questions/4114095/revert-to-a-previous-git-commit

Project Euler Problem 4 – Largest palindrome product

02.23.2015

The Problem

A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.

Find the largest palindrome made from the product of two 3-digit numbers.

The Test Case

class Problem4Test < Minitest::Unit::TestCase
  def test_largest_palindrome_product2
    solver = Problem4.new 2
    ans = solver.solve
    assert_equal 9009, ans
  end
end

The Logic

First, find the highest possible product by multiplying the highest two digit factors together. 99 x 99 = 9801.

With highest product, we can iterate backwards and test if it is a palindrome.

If it is a palindrome, we then find its factors that are 2 digits.

Then we check each one to see if the other factor is also 2 digits.

If so, we’ve found our answer.

The Code

class Problem4
  def initialize num_digits
    @num_digits = num_digits
  end

  def solve
    max_factor = 10**@num_digits - 1
    product = max_factor * max_factor

    # iterate from max product down to 1
    product.downto(1) do |i|

      # if it is a palindrome
      if is_palindrome i

        # get all factors
        factors = divisors_of i
        # iterate through each factor and divide i by factor
        factors.each do |f|
          x =  i / f

          # if x length is equal to num digit, we found our answer
          if x.to_s.length == @num_digits
            return i
          end
        end
      end
    end
    return nil
  end

  def is_palindrome int
    str = int.to_s
    str == str.reverse
  end

  # return all factors that are of length num_digit
  def divisors_of num
    (1..num).select { |n| num % n == 0 && n.to_s.length == @num_digits }
  end
end

https://github.com/travisluong/projecteuler

ReCaptcha Gem Custom Theme

02.16.2015

Recently, I needed to figure out how to customize the look of the ReCaptcha form generated by the recaptcha gem for Rails.

After you’ve installed the gem and got it working according to the installation instructions, you’ll have to change a few things.

First, replace the <%= recaptcha_tags %> code with <%= render 'recaptcha' %>.

Next, create a new view _recaptcha.html.erb and paste in the code found in the Customizing the Look and Feel of reCAPTCHA documentation.

<script type="text/javascript">
 var RecaptchaOptions = {
    theme : 'custom',
    custom_theme_widget: 'recaptcha_widget'
 };
</script>

<div id="recaptcha_widget" style="display:none">

   <div id="recaptcha_image"></div>
   <div class="recaptcha_only_if_incorrect_sol" style="color:red">Incorrect please try again</div>

   <span class="recaptcha_only_if_image">Enter the words above:</span>
   <span class="recaptcha_only_if_audio">Enter the numbers you hear:</span>

   <input type="text" id="recaptcha_response_field" name="recaptcha_response_field" />

   <div><a href="javascript:Recaptcha.reload()">Get another CAPTCHA</a></div>
   <div class="recaptcha_only_if_image"><a href="javascript:Recaptcha.switch_type('audio')">Get an audio CAPTCHA</a></div>
   <div class="recaptcha_only_if_audio"><a href="javascript:Recaptcha.switch_type('image')">Get an image CAPTCHA</a></div>

   <div><a href="javascript:Recaptcha.showhelp()">Help</a></div>

 </div>

 <script type="text/javascript"
    src="http://www.google.com/recaptcha/api/challenge?k=your_public_key">
 </script>
 <noscript>
   <iframe src="http://www.google.com/recaptcha/api/noscript?k=your_public_key"
        height="300" width="500" frameborder="0"></iframe><br>
   <textarea name="recaptcha_challenge_field" rows="3" cols="40">
   </textarea>
   <input type="hidden" name="recaptcha_response_field"
        value="manual_challenge">
 </noscript>

Next, you will want to replace your_public_key with <%= ENV['RECAPTCHA_PUBLIC_KEY'] %>.

You can now move stuff around and apply custom CSS styling.

Bootstrap has some good glyphicons for this. You can change the colors as well:

<div class="recaptcha_buttons">
  <div><a href="javascript:Recaptcha.reload()"><span style="color:#333;" class="glyphicon glyphicon-refresh"></span></a></div>
  <div class="recaptcha_only_if_image"><a href="javascript:Recaptcha.switch_type('audio')"><span style="color:#333;" class="glyphicon glyphicon-headphones"></span></a></div>
  <div class="recaptcha_only_if_audio"><a href="javascript:Recaptcha.switch_type('image')"><span style="color:#333;" class="glyphicon glyphicon-refresh"></span></a></div>
  <div><a href="javascript:Recaptcha.showhelp()"><span style="color:#333;" class="glyphicon glyphicon-question-sign"></span></a></div>
</div>

Project Euler Problem 3 – Largest prime factor

02.09.2015

The Problem

The prime factors of 13195 are 5, 7, 13 and 29.

What is the largest prime factor of the number 600851475143 ?

The First Solution

My first instinct when I saw this problem was to see if there was a “Prime” library for Ruby. Indeed, there was. With just a couple lines of code, you can get the answer for this.

require "prime"
Prime.prime_division(600851475143)

But I kind of felt that was cheating, so I went and googled how to do prime factorization.

The Test Case

The steps to solve is to keep dividing the number by the lowest prime factor until you reach the largest prime factor. For example, if we were to solve for 75.

  1. 75 / 3 = 25
  2. 25 / 5 = 5
  3. 5 / 5 = 1
class Problem3Test < Minitest::Unit::TestCase
  def test_largest_prime_factor1
    ans = 10.largest_prime_factor
    assert_equal 5, ans
  end

  def test_largest_prime_factor2
    ans = 13195.largest_prime_factor
    assert_equal 29, ans
  end

  def test_largest_prime_factor3
    ans = 600851475143.largest_prime_factor
    assert_equal 6857, ans
  end
end

The Solution

The largest prime factor for 75 is 5. In the code, we just increase the factor by 1 in each iteration until we’ve tested every possible factor up to the number. For each factor, we keep dividing by the factor until it is no longer divisible. (In the example, we divide by 5 twice).

class Fixnum
  def largest_prime_factor
    n = self
    factor = 2
    lastFactor = 1
    while n > 1
      if n % factor == 0
        lastFactor = factor
        n = n / factor
        while n % factor == 0
          n = n / factor
        end
      end
      factor = factor + 1
    end
    return lastFactor
  end
end

Notes

In the example above, I used an interesting feature of Ruby where I “open” the Fixnum class and add a new method to it. Now all Fixnum instances will have the largest_prime_factor method.

https://github.com/travisluong/projecteuler

Project Euler Problem 2 – Even Fibonacci Numbers

02.04.2015

Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, …

By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.

To solve this problem, I first started by writing a simple test case to test that this would work with numbers under 10. We know that our answer would be 10 since 2 and 8 are the only even numbers in the Fibonacci sequence. The test instantiates a Problem2 solver object with 10 as the parameter. We solve and should expect 10 as the answer.

class Problem2Test < Minitest::Unit::TestCase
  def test_even_fibonacci_numbers
    solver = Problem2.new :under => 10
    answer = solver.solve
    assert_equal 10, answer
  end
end

The test should be failing since we haven’t implemented the class yet. The next step is to implement the class.

class Problem2
  def initialize options
    @under = options[:under]
  end

  def solve
    previous = 0
    current = 1
    sum = 0
    loop do
      temp = current
      current += previous
      previous = temp
      break if current >= @under
      sum += current if current % 2 == 0
    end
    sum
  end
end

In the solve method, we start by declaring 3 variables, previous, current, and sum. In the loop, we store the current as temp, which we will use to set the previous later on. We add the previous to the current and then set the previous to the temp. We stop the loop if the current is equal to or greater than the under instance variable we initialized earlier. We add current to the sum if it is even. We return the sum.

Then we solve for the answer:

puts Problem2.new(:under => 4000000).solve

https://github.com/travisluong/projecteuler

Project Euler Problem 1 – Sum of Multiples of 3 and 5

02.03.2015

This is my first in a series of posts where I’ll be working through Project Euler Problems in Ruby. My goal is to write the code in an “object oriented” way along with unit tests.

There are a few reasons why I am doing this.

  1. To practice object oriented design and apply lessons from Practical Object Oriented Design in Ruby
  2. To practice unit testing and experiment with minitest
  3. To practice problem solving with algorithms

And last, but not least I’m doing it because I think it’s fun.

I will post the code on GitHub.

Here is the first Project Euler problem. I remember getting a problem very similar to this one at a job interview at one of my first coding jobs.

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.

Find the sum of all the multiples of 3 or 5 below 1000.

Here was my solution before refactoring:

require 'minitest/autorun'

class Problem1
  def self.sum_of_multiples_of_3_and_5 num
    sum = 0
    (1..num-1).each do |i|
      if i%5 == 0 || i%3 == 0
        sum += i
      end
    end
    sum
  end
end

class Problem1Test < MiniTest::Unit::TestCase
  def test_sum_of_multiples_of_3_and_5
    result = Problem1.sum_of_multiples_of_3_and_5 10
    assert_equal 23, result
  end
end

I built a simple test case based on the example in the question. Then I wrote the class along with the class method to run the calculation. We iterate through each number from 1 up to one below the number passed in to the method. We add it to the sum if it is a multiple of 5 or 3. We can test that with the modulus operator. Then we return the sum.

At this point, we're able to get the right answer using this class. While the code works, it is limited to only multiples of 3 and 5. Let's refactor the test so we can pass in any two numbers into an Problem Solver instance.

Here is my solution after refactoring:

require 'minitest/autorun'

class Problem1

  attr_accessor :first, :second

  def initialize first, second
    @first = first
    @second = second
  end

  def solve num
    sum = 0
    (1..num-1).each do |i|
      if i % @first == 0 || i % @second == 0
        sum += i
      end
    end
    sum
  end
end

class Problem1Test < MiniTest::Unit::TestCase
  def test_sum_of_multiples_of_3_and_5
    solver = Problem1.new 3, 5
    answer = solver.solve 10
    assert_equal 23, answer
  end

  def test_sum_of_multiples_of_2_and_4
    solver = Problem1.new 2, 4
    answer = solver.solve 10
    assert_equal 20, answer
  end
end

Now we can instantiate a Problem1 object with two parameters. There is a way to pass in any number of parameters using the ruby splat * or simply passing in an array, but I'll leave that up as an exercise for the reader.

Thanks for reading.

iOS Equal Width Auto Layout Tutorial

02.02.2015

Recently, I needed to figure out a way to get two views to equal width spanning the entire width of the screen. I’ve created this tutorial to show you how to create symmetrical views.

Step 1: Create a new Single View Application

Once you’ve created a new application, click on the root in the project navigator. In General, uncheck everything except Landscape Left. This part is optional.

Screen Shot 2015-01-19 at 3.47.44 PM

Step 2: Create Views

Drag a view onto storyboard.

Resize the the view.

Ctrl + D to duplicate view.

Go to the attributes inspector in the upper right to change the background color. (optional)Screen Shot 2015-01-19 at 3.25.51 PM

Step 3: Add Constraints

Click on the left view and use the pin menu to add constraints to the superview for the top, left, and bottom and set to 0. Click on Add 3 Constraints.

Screen Shot 2015-01-19 at 3.40.49 PM

Click on the right view and use the pin menu to add add constraints to the superview for the top, right, and bottom and set to 0. Click on Add 3 Constraints.

Screen Shot 2015-01-19 at 3.41.29 PM

Control drag from the left view to the right view to set a constraint. Select Horizontal Spacing. Hover your mouse over the constraint line until it is highlighted and click. In the attributes inspector, set the Constant to 0.

Screen Shot 2015-01-19 at 3.46.06 PM

If you run the application, you’ll get something that looks like this.

iOS Simulator Screen Shot Jan 19, 2015, 3.46.53 PM

The ratio is off.

Step 4: Add Equal Width Constraint

To add equal width constraint, you will need to select both views by command clicking on both of them. Then click on the pin menu and the previously grayed out Equal Width checkbox is now available. Click on that and click Add 1 Constraint.

Screen Shot 2015-01-19 at 3.51.01 PM

As you can see there are still some white space on the sides. To get rid of the white space, click on the leading constraint, and uncheck Relative To Margin for Second Item. For the trailing constraint, uncheck Relative To Margin for the First Item.

If you run the application, now you will have two equal full width views.

iOS Simulator Screen Shot Jan 19, 2015, 4.04.22 PM

GitHub

https://github.com/travisluong/auto-layout-equal-width-demo

Sources

http://www.raywenderlich.com/50319/beginning-auto-layout-tutorial-in-ios-7-part-2

Incompatible integer to pointer conversion assigning to ‘int *’ from ‘int’

02.01.2015

I got this warning message today while working on my iOS app:

Incompatible integer to pointer conversion assigning to ‘int *’ from ‘int’

Looked it up on Stack Overflow, and apparently primitive types don’t need the asterisk which indicates that it is a pointer to an object.

Sources

http://stackoverflow.com/questions/5293406/another-warning-question-incompatible-integer-to-pointer-conversion-assigning