Seichy's Missing Bit

Using MapKit with Swift

I've been using Swift a lot lately. I wanted to start making iOS apps a while ago but Objective-C is frankly, not worth the trouble. Swift on the other hand is actually fun to use and I love experiencing how the language evolves.

This weekend I started working on a small app I've wanted for a while but got stuck when it came to implementing a map with MapKit. I couldn't find documentation or code samples on how to do it anywhere. Turns out that it's not hard at all! It took very little fiddling around before I figured it out. Here's how I did it:

First, create a new project

I started with a Single View Application.

Then added a MKMapView to the view controller. After that, imported MapKit into the view controller's code. Finally, I added a new reference outlet to the map called map.

Setup your desired location

Now our map is ready to display a location. You'll need a couple of things to set it to the right place. First, you need a location in the form of a latitude and longitude and a CLLocationCoordinate2D.

var location = CLLocationCoordinate2D(
    latitude: 16.40, 
    longitude: -86.34
)

Now, we need to tell the map what the area spanned by the region is. For this we use MKCoordinateSpanMake. Which, as you probably guessed, creates a MKCoordinateSpan.

var span = MKCoordinateSpanMake(1, 1)

After that we just need to define the region using these two things:

var region = MKCoordinateRegion(center: location, span: span)

And finally, we set this region to the map:

map.setRegion(region, animated: true)

Bonus: Adding an annotation

Adding an annotation is actually quite easy. We start by creating a new MKPointAnnotation instance. It'll display the default red pin which, might not be as pretty but it'll get the job done.

var annotation = MKPointAnnotation()

Afterwards, we can set it's coordinates, title and subtitle to place it wherever we want and to add the text it's callout will display when tapped.

annotation.setCoordinate(location)
annotation.title = "Roatan"
annotation.subtitle = "Honduras"

Finally, we add it to the map like this:

map.addAnnotation(annotation)

Here's my final code:

import UIKit
import MapKit

class ViewController: UIViewController {

    @IBOutlet weak var map: MKMapView!
    override func viewDidLoad() {
        super.viewDidLoad()

        var location = CLLocationCoordinate2D(
            latitude: 16.40, 
            longitude: -86.34
        )

        var span = MKCoordinateSpanMake(0.5, 0.5)
        var region = MKCoordinateRegion(center: location, span: span)

        map.setRegion(region, animated: true)

        var annotation = MKPointAnnotation()
        annotation.setCoordinate(location)
        annotation.title = "Roatan"
        annotation.subtitle = "Honduras"

        map.addAnnotation(annotation)
    }
}

And here's what my app looks like:

Additional Resources

Location and Maps Programming Guide

Using mailgun to receive emails with Phabricator

Phabricator is awesome. We recently started trying it out for 2build.it (more like, this morning) and we all (Jorge and I) agreed it's awesome.

The setup is pretty straight-forward and only took like 20 minutes. The one thing I got stuck on though, was the emailing. It took me forever to realise that you're supposed to restart the emailing daemons for the configuration to stick. It is my fault but, this wasn't mentioned anywhere in the documentation. Btw, here's how you do it:

./bin/phd restart

Right from the Phabricator folder.

Moving on.

Now that sending was settled there was one huge thing that wasn't working. Inbound emails. I tried working with postfix but, it was too painful and after a couple of hours I didn't get anywhere. The documentation talks about using sendgrid to achieve it but, I already have a mailgun account and according to the configuration Phabricator should be able to use mailgun as well. So, I had to do some research.

It turns out you can use mailgun to do this but, there's zero documentation about it. Luckily, I found the commit where this functionality was added and figured it out on my own. Here's the three step guide to getting it done.

Step 1

You have to configure you domain's MX records to point to mailgun. You can find more information here.

Step 2

Go to your setup your mailgun configuration by going to the mailgun config (http://example.com/config/group/mailgun/) and adding your API key and your domain.

Step 3

We're almost done. Now, all we have to do is tell mailgun to send received emails your way. To do this all you have to do is create a new route (go here: https://mailgun.com/cp/routes). Give it a priority and a filter that'll work for you (I used 0 as a priority and catch_all() for a filter). For the action, forward it to your Phabricator installation with the endpoint '/mail/mailgun'. Like this: forward("http://example.com/mail/mailgun/").

That is all. Your emails should now allow you to interact with Phabricator.

Sketch Presets for Desktop Screens

I've been using Sketch to create mock ups for clients lately. So far so good. Today, I wanted to create art board presets for common desktop screen sizes. It took me a little while to find out how to organize them into folders. Luckily for me, Jan Drewniak has a blog post detailing how to do just this.

Sketch actually keeps these artboard presets in an artboards.sketchpreset file located somewhere on your mac. If you're using the App Store version of Sketch, then the file is located here:

~/Library/Containers/com.bohemiancoding.sketch/Data/Library/Application  Support/sketch/

Here's my presets:

<dict>
    <key>name</key>
    <string>Desktop</string>
    <key>presets</key>
    <array>
        <string>Retina Displays</string>
        <dict>
            <key>width</key>
            <integer>2880</integer>
            <key>name</key>
            <string>15-inch</string>
            <key>height</key>
            <integer>1800</integer>
        </dict>
        <dict>
            <key>width</key>
            <integer>2560</integer>
            <key>name</key>
            <string>13-inch</string>
            <key>height</key>
            <integer>1600</integer>
        </dict>
        <string>4:3</string>
        <dict>
            <key>width</key>
            <integer>1600</integer>
            <key>name</key>
            <string>Large 4:3</string>
            <key>height</key>
            <integer>1200</integer>
        </dict>
        <dict>
            <key>width</key>
            <integer>1280</integer>
            <key>name</key>
            <string>Medium 4:3</string>
            <key>height</key>
            <integer>1024</integer>
        </dict>
        <string>16:9</string>
        <dict>
            <key>width</key>
            <integer>1920</integer>
            <key>name</key>
            <string>Large 16:9</string>
            <key>height</key>
            <integer>1080</integer>
        </dict>
        <dict>
            <key>width</key>
            <integer>1600</integer>
            <key>name</key>
            <string>Medium 16:9</string>
            <key>height</key>
            <integer>900</integer>
        </dict>
        <dict>
            <key>width</key>
            <integer>1366</integer>
            <key>name</key>
            <string>Small 16:9</string>
            <key>height</key>
            <integer>768</integer>
        </dict>
    </array>
</dict>

I have categories for: Retina, 16:9 and 5:4 displays. Only listing the ones I've used recently and might re-use in the future.

Scroll Spying for Fun and Profit

I recently redesigned by blog. One of the new features is a menu that highlights the current post you are on.

To achieve this, I used Zepto and a small amount of math. (The great thing about Zepto is that it's fully compatible with jQuery, so this should work with jQuery out of the box as well).

Let's jump right in, here's how I do it:


$(window).on('scroll', function() {
    var scrollTop = $(window).scrollTop();
    var article_offsets = $('article').map(function(i) { 
        if (i === 0) {
            return 0;
        }

        return $(this).offset().top 
    });

    for (var i = 0; i < article_offsets.length; i++) {
        if (article_offsets[i] - 40 <= scrollTop) {
            $('.sidebar li').removeClass('active')
                .eq(i).addClass('active');
        }
    };
});

The first line of interest:

var article_offsets = $('article').map(function(i) { 
    if (i === 0) {
        return 0;
    }

    return $(this).offset().top 
});

Grabs all the vertical positions (from now on, offsets) of the elements I want to match and makes an array out of them. In this case, I am targeting the articles since, those represent my blog posts. I make sure to mark the first one as 0, so it works when the page first loads at scroll position 0.

After doing this, we iterate over all our scroll positions, if we find ourselves scrolled after one of the offsets we run this:

$('.sidebar li').removeClass('active').eq(i).addClass('active');

This looks for the Ith element on the sidebar's list and we add a class of 'active' to it, highlighting it and doing whatever we want with it.

There's a couple of other (bigger, more complex and probably more robust) solutions to this problem out there. Here's a couple I came through:

I am pretty sure they are plenty of others but, for my evil purposes, my tiny script fulfills my needs.

2014

I know I am a little late doing the whole goal setting and year review thing but, this year I wanted to try something different. I wanted to see how January turned out before setting goals.

This year will be pretty exciting. I'll continue working as a consultant as I have for the past couple of years. Invivo Link is doing some pretty cool things and I am happy to help them continue building their product. Over at 2build.it, we're working with some pretty cool clients, building a variety of pretty cool things, hopefully the company will grow a whole lot this year.

I tend to decide what I'd like to learn more during the year. This year's language is going to be Rust. I've fallen in love with it on the past couple of months and I'd like to start building more things with it as the language becomes more stable. Apart from Rust, this year I'll be working with Objective-C a whole lot more. I don't fully like the language yet but, I feel like it can be a valuable tool in my toolset. I'll also continue working on bundle.js as it has become essential to a client's project which, turns out to be a great way to further develop it.

I'd also like to write more, I didn't get to do it as much as I wanted to last year so I've adjusted my goal, I want to write at least, 12 posts during the year. I think this is a reasonable quantity and I hope I'll be able to reach it. I'd also like to read more, my goal for that is at least 52 books. I am up to speed so far so I am pretty sure I can reach that.

Finally, I'd like a travel more this year, I am getting a little tired and burned out and I feel that it would help me to travel and see things.

I achieved most of the important goals from last year so, I am looking forward to a great year.