Month: July 2015

Listen to the Log

An illustration of a log with the caption Listen to the Log
And watch out for the owls.

Looking forward to season 3 of Twin Peaks.

Useful CGFloat Extensions

I’ve been working a lot with CALayers over the past few days, specifically layers with circular shapes, and so these two little extensions have been really useful.

extension CGFloat {  
    func degreesToRads() -> CGFloat {  
        let rads = self * CGFloat(M_PI / 180 )  
        return rads  
    }
    func positionOnCircleInRect(rect : CGRect) -> CGPoint {  
        let rads =  self.degreesToRads() - CGFloat( M_PI / 2)

        // Assume square  
        let x = rect.size.width / 2 * CGFloat(cos(rads))  
        let y = rect.size.height / 2 * CGFloat(sin(rads))  
        return CGPointMake(x + (rect.size.height / 2) + rect.origin.x, y + (rect.size.height / 2) + rect.origin.x)  
    }
}   

The first is your standard degrees to radians conversion function that every programmer that’s worked with UI has probably written at some point.

The second is a bit more interesting, though, as it finds a point on a circle within a frame of a given size (it also assumes that 0 is the top of the circle, not the right edge as in Core Animation):

let rectForCircle = CGRect(x: 0, y: 0, width: 50, height: 50 )  
let point = CGFloat(90).positionOnCircleInRect(rectForCircle) 

// Returns x 50, y 25—or the point at 90º on a circle

Distribution Provisioning Profile Woes

Managing App IDs and provisioning profiles has come on a lot from when I first started iOS development almost three years ago. Xcode now does a fair amount of the heavy lifting for you, creating App IDs and development provisioning profiles automatically as and when they’re needed. This is great, removing some of the administrative burden and getting new projects running on devices as quickly as possible.

It has become so easy, in fact, that I thought I could just start submitting apps to the App store for testing based on simply setting the Team setting in the General tab of the target in Xcode. There was nothing really telling me that I couldn’t do this—this process will work just fine until you want some advanced entitlements (like iCloud), at which point trying to upload it to iTunes will result in no matching provisioning profiles found for application errors.

When I looked carefully at the error, I noticed that it was trying to use the wildcard provisioning profile which isn’t allowed when it comes to certain entitlements.

After much deleting of the automatically generated App IDs and provisioning profiles, I realised that you still needed to manually create a distribution profile with your distribution certificate even though the Code Signing Entities in the Build Settings tab now always just say iOS Developer now and the Provisioning Profile says automatic. There are few clues that multiple provisioning profiles were even necessary any more.

Anyway, it’s my fault for making the assumption that differentiated provisioning profiles were a thing of the past—I thought I had reached the point of never needing to reach for the Certificates, Identifiers & Profiles section of the Developer Portal again—but maybe this will help someone else come to the realisation sooner that, when it comes to distribution profiles, you always need to make sure you have one set up and you have to do this manually.

Core Data and NSAttributedString

I’m currently creating an app that uses some weird formatting and inline images that can be handled nicely by NSAttributedString.

The app is bundled with a pre-populated database and I was considering populating the database with the already formatted strings and images.

Core Data supports NSAttributedStrings—just set the attribute to be Transformable and you can create and store attributed strings along with most attributes.

The interesting thing is that it can also store images within the strings if you add it using NSTextAttachment:

let attributedString = NSMutableAttributedString(string: "Hello images!")
var attributes: [String : AnyObject]?

if let font = UIFont(name: "AvenirNextCondensed-Medium", size: 30) {
    attributes = [ NSFontAttributeName : font ]
}

let range = NSRange(location: 0, length: attributedString.length)
attributedString.setAttributes(attributes, range:range )

// You can safely pass nil to both parameters if using an image
let textAttachment = NSTextAttachment(data: nil, ofType: nil) 
textAttachment.image = UIImage(named: "TestImage")        
let imageString = NSAttributedString(attachment: textAttachment)
attributedString.appendAttributedString(imageString)

coreDataEntity.transformableAttribute = attributedString

There’s a few issues with this:

  1. Your database will get big fast. Unlike the Binary attribute, there’s no way to tell Core Data to use external storage.
  2. You’re passing in the scale of image of the device that created the image. For example, if you’re running the app on an iPhone 6, then UIImage(named:) will return an @2x image and this and only this scale is what will be stored in the database

This will be fine if it’s going to be accessed on the same device that it’s created on, but if you use any sort of syncing or you want to deliver a pre-populated database in your app bundle, then you’re going to be passing around an image that might be the wrong scale for the device.

Also, storing attributed strings this way breaks any connection with dynamic text styles, so there’s no resizing of the string after it comes out of the database if the user changes the text size in Accessibility. This makes sense as the font is hardcoded into the attributed string so there’s no way of the system knowing that it should resize it, but it does make storing attributed strings in the database less useful if you want to provide dynamic text resizing (which you should).

Because of these limitations, I think I’m going to stick with formatting the strings and adding the image on the fly for the moment, but it’s good to know what’s possible with Core Data.