Stuart Breckenridge

iCloud Voicemail

“Employees at Apple are reportedly putting a new service through its paces, one that would allow Siri to not only answer a missed call instead of a pre-set voicemail message, but give her the ability to record and transcribe those message for users to read as text later (via Business Insider).”

Mitchel Broussard


I think the idea of iCloud Voicemail is excellent. The adoption of Visual Voicemail – itself an outstanding feature – has been poor1 and that’s the fault of the carriers. They have, once again, presented Apple with a problem to solve and in the process cut off one their revenue streams.

  1. Only 10 carriers in Asia Pacific and Australasia support Visual Voicemail.

    </li> </ol></div>


— Supported by —


App Transport Security, Cloudfront, and S3

App Transport Security is a new feature in iOS 9 and OS X 10.11 and it’s enabled by default. This means that you can’t use standard HTTP for requests without making changes to application’s Info.plist.

Take the following simple request:

let request = NSMutableURLRequest(URL: NSURL(string: "http://something.cloudfront.net/some.file")!)
request.HTTPMethod = "HEAD"
let queue = NSOperationQueue()
let session = NSURLSession(configuration: sessionConfiguration, delegate: nil, delegateQueue: queue)
let downloadTask = session.downloadTaskWithRequest(request) { (url, response, error) -> Void in
            print(response)
        }

This request fails in iOS 9 with the following error and a nil response:

App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. 

Temporary exceptions can be configured via your app's Info.plist file.

As Cloudfront supports HTTPS the request URL can be changed:

let request = NSMutableURLRequest(URL: NSURL(string: "https://something.cloudfront.net/some.file")!)

However, when running the request a different error appears:

NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)

For my specific configuration – Cloudfront CDN with data hosted in Amazon S3 – Forward Secrecy is not enabled (or, at the very least, it’s causing issues). You don’t have to tear down ATS entirely to get things working, you just need to disable the requirement for Forward Secrecy in your Info.plist:

<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSExceptionDomains</key>
		<dict>
			<key>something.cloudfront.net</key>
			<dict>
				<key>NSExceptionRequiresForwardSecrecy</key>
				<false/>
			</dict>
		</dict>
	</dict>

This resolved my issue, hopefully it helps someone else to.


2XU Compression Run 2015

The postponed 2XU Compression Run is happening on August 2nd. While the route has yet to be announced, a few extra bits of information have trickled out:

“Flag-Off Time: 4.30am (21.1KM), 7.30am (10KM) and 8.30am (5KM)
Venue: Marina East Drive (Open field beside 201 Marina East Drive, Singapore 029997)


Due to the changes in the date and venue of the run, please also note that there will be changes in terms of the layout and race route. While the route may not be as ideal as we would like it to be, the replacement route has been derived with the best of our abilities, given the sudden change in circumstances and because many venues were booked a year in advance. The updated race route will be announced this week due to restrictions by stakeholders.

2XU


The start point is hard to get to, so have a look at the getting there guide.


Code Review

When I first got interested in programming – around 2009 – the first app I made was a little utility to help you pick your lottery numbers. It was called Lucky Dip and it sold exclusively in the UK App Store and it very quickly went from being £0.69 to being free.1

In the spirit of continual improvement I’m reviewing my younger self’s code, and boy is it a painful experience.

The problem statement: generate a set of six unique numbers between 1 and 49.


Younger Self

I’m sure I attacked the problem in the following way:

  • find out how to generate numbers within a specific range;
  • generate six of them; then,
  • compare them all against each other individually to make sure they are unique.

This is what my code looked like:

- (NSArray *)generateLottoNumbers
{
        // Generate Numbers
    int n1 = arc4random() % 49 + 1;
    int n2 = arc4random() % 49 + 1;
    int n3 = arc4random() % 49 + 1;
    int n4 = arc4random() % 49 + 1;
    int n5 = arc4random() % 49 + 1;
    int n6 = arc4random() % 49 + 1;
    
        // Check uniqueness
    if (n1 == n2 || n1 == n3 || n1 == n4 || n1 == n5 || n1 == n6 ||
        n2 == n3 || n2 == n4 || n2 == n5 || n2 == n6 ||
        n3 == n4 || n3 == n5 || n3 == n6 ||
        n4 == n5 || n4 == n6 ||
        n5 == n6)
        {
            return [self generateLottoNumbers]; // Duplicates detected.
        }
    
    	// Return a sorted array.
    else
        {
        NSMutableArray *numbers = [NSMutableArray arrayWithObjects:@(n1), @(n2), @(n3), @(n4), @(n5), @(n6),  nil];
        NSArray *array = [numbers sortedArrayUsingSelector:@selector(compare:)]; 
        return array;
        }
}

The code was then called with:

	NSArray *numbers = [self generateLottoNumbers];

This existed in each view controller in a different incarnation, suitable to each lottery game (typed out every time).2 Talk about not having reusable code and massive view controllers.

Current Self

What I’d do now is create reusable code so each view controller for each lottery game called the same function. I’d start with a protocol:

protocol LottoNumbers
{
    func generateLottoNumbers(count:Int,maxRange:UInt32) -> [Int]
}

I’d then extend UIViewController to conform to the LottoNumbers protocol3. The function makes use of a Set to ensure that there are the correct amount of unique numbers:

extension UIViewController:LottoNumbers
{
    func generateLottoNumbers(count:Int,maxRange:UInt32) -> [Int]
    {
        var i = 0
        let uniqueSet = NSMutableSet(capacity: count)
        var numberArray = [Int]()
        
        repeat {
            let genNumber = (Int(arc4random() % maxRange + 1))
            uniqueSet.addObject(genNumber)
            numberArray.append(genNumber)
            ++i
        } while i < count
        
        if uniqueSet.count != count
        {
            return self.generateLottoNumbers(count, maxRange: maxRange)
        }
        
        numberArray.sortInPlace({$0<$1})
        
        return numberArray
    }
}

This code can be reused depending on the rules of the game and it also prevents having a massive view controller:

let numbers = generateLottoNumbers(6, maxRange: 49) // Lotto.
let numbers = generateLottoNumbers(5, maxRange: 50) // Euromillions.
// etc...

There are always better ways of doing things. However, the original version worked and that’s all that mattered at the time.

  1. I had lofty ambitions of World domination that didn’t last. ↩︎

  2. There were three others: Hotpicks, Thunderball, and Euromillions. ↩︎

  3. This could also be achieved with an Objective-C tags. ↩︎


New Horizons Reaches Pluto

“Nasa’s New Horizons spacecraft has made the first visit to Pluto, speeding past at 14km per second. Earlier, the space agency released the most detailed picture yet as it hurtled towards the dwarf planet on Tuesday. The probe was set to grab more pictures and other science data on the object, as it passed 12,500km from the surface. Controllers got a last health status report, before the robotic craft turned its antenna away from the Earth to concentrate on its target. Only when New Horizons has its trove of images safely in its onboard memory will it call home again. This is not expected to happen until just after midnight (GMT) into Wednesday. It means there will be a long, anxious wait for everyone connected with the mission, as they hold out for a signal that will be coming from almost five billion km away.”

Jonathan Amos


It’s incredible to think that we have a satellite orbiting a dwarf planet, sending back data, from a distance of five billion kilometres. Star Trek distances.

Update: just look at this tweet