My main development machine used to be a 2010 MacBook Pro with a 512 GB SSD. Expensive, but way fast. Unfortunately the GPU died about a year ago so I've been using a 2011 iMac. Its also fast, if not faster than the MBP for many things but disk operations are not.

A few weeks ago on Dave Verwer's brilliant iOS Dev Weekly I found a blog post explaining how you could speed up Xcode (and AppCode) build times. This is done by moving Xcode's DerivedData folder as well as iOS Simulator Data to a RAM disk.

A RAM disk is taking a chunk of memory and treating it as a if it were a drive. Now SSD's are fast, but memory is still much faster. If you have extra memory lying around I recommend giving this a shot.

I didn't go the Terminal route but instead used iRamDisk from the Mac App Store. I was skeptical, but it definitely works.

Building and running an app I'm currently working on into a clean iOS Simulator used to take 20 seconds. Using iRamDisk it now takes 7. That's huge.

Regular builds are also much faster and very noticeable after doing a Product > Clean.

DerivedData gets a gig

The Simulator gets 512MB

The dropdown menu in the menu bar also lets you know how full each disk is and you can easily flush them via a menu option.

Menu options

Menu options

If you have extra memory lying around I'd give it a shot.

Posted
AuthorPaulo Fierro

Last week we shipped Brainfeed, an iPad app we've been working on for a client that presents educational videos for kids. We also developed a backend system for the curators to use to add and tag videos for the app.

This backend is built in Ruby with Padrino (on top of Sinatra) and runs on Heroku. Due to the nature of the app it only needs a single dyno and pushes content changes over to a bucket on Amazon S3 which is consumed by the iPad app. This means that the app can continue to work independently from the backend and any scaling issues can be handled on the S3 side of things, which has the added bonus of keeping the overall cost down.

Previously the app was consuming a JSON file provided by the backend via an API. When you're serving JSON (or any data) you really want to serve it compressed to save on bandwidth and overall load time.

In Apache you can add a line to your .htaccess file that indicates this like so:

AddOutputFilterByType DEFLATE application/json

This gzips JSON content on the fly automatically. This is normally already set in Padrino/Sinatra apps using Rack::Deflater.

However, when I started pushing the JSON over to S3 I needed a way to tell S3 to serve the content in a compressed fashion. Using the AWS SDK for Ruby you can do this like so:

Before the gzip compression we were serving about 960KB. Now that's down to 240KB which is much more manageable. Due to the nature of the app (watching online videos) we know the users are going to be on wi-fi so its not that big a deal, but every little bit helps.

For some reason this took way too long to figure out, so here it is for next time.

Posted
AuthorPaulo Fierro

This week we had the pleasure of shipping Brainfeed, an iPad app I've been working on the last few months aimed at providing educational videos for kids, 7-years and older.

Brainfeed

Each video is carefully classified by curators and screened for inappropriate content so you get the best content served in a kid-friendly package. The app itself is free, but there to unlock all of the content you have to sign up for a subscription. The videos are great so its well worth it.

We were responsible for developing the iPad app as well as the Sinatra based backend system for adding and tagging videos.

Its something I'm really proud of and its now available on the App Store.

Posted
AuthorPaulo Fierro

This morning I was using Charles to monitor some HTTP requests like I do. I noticed some odd requests were showing up every time I changed tabs in Safari, but also when swapping to and from Safari.

The requests were going to something on localhost that was running on a range of ports and accepted a request at /snap/new. So something is trying to take snapshots of every page I visit in Safari.

This can't be good.

Suspect requests

After looking around I checked the Safari Extensions to see if I had installed a rogue piece of software and there it was. Nothing fishy at all, just Ember. There to do its job which is to take screenshots.

Disabling the extension got rid of the requests and I could get back to what I was doing without poor Charles getting flooded.

Posted
AuthorPaulo Fierro

While I was working this morning I ran into some issues with an app and went to check if the Console (under /Applications/Utilities) was reporting anything.

Unfortunately the log was filled with some USB device timing out with the following error:

AppleUSBEHCI::Found a transaction past the completion deadline on bus 0xfa, timing out! (Addr: 5, EP: 1)

A very noisy log

This timeout was annoyingly happening every few seconds. The error did give me a few clues. It was happening on USB bus 0xfa on a device attached to address 5.

To find the device in question I generated a System Report ( > About this Mac > More Info > System Report) and looked for the USB bus with the same address.

Finding the USB bus number

Finding the USB bus number

Then it was just a question of going through the devices connected to this bus that had the address in question.

The address of the USB device

The address of the USB device

Found you! The device in question was the Garmin ANT+ stick that transmits data wirelessly from my Garmin Forerunner 610 watch.

Unplugging it fixed the problem and the Console stopped being flooded.

fry.jpg
Posted
AuthorPaulo Fierro

I love git and Github but I don't have any git-fu, as in I don't know how to use the command line version of git to save my life.

Don't get me wrong, I'm fine using the Terminal and for some tasks I even prefer it. But for version control, a GUI does it for me and in this case my app of choice is Tower.

And while Tower is great, and the web interface on Github is good too I recently ran into something I couldn't do with either (or I couldn't figure out).

Deleting tags.

I use tags all the time. Bookmarking commits — what's not to like? For simple things like "this is version 1.1" which we can come back to and branch off of if we need ship a bugfix for 1.1, while at the same time developing new features on the main branch. And for things like "this is where I was before that sketchy merge".

For the first example, this is probably a tag we want to keep and add some release notes. But for the latter, we might want to delete it when we're done. Once we've done testing and QA and everything is good we can nuke that sucka.

So in Tower you can right-click a tag and delete it but if I then push and check "Push All Tags" the tag doesn't get deleted. The next time I pull that tag will come back because I didn't delete it from Github.

We can do this on the command line as follows:

  1. Delete the sketchy tag locally: git tag -d sketchy
  2. Delete the tag on Github: git push origin :sketchy
  3. Push the change: git push --tags

If you added any release notes (and you should) they'll now show up under your project's releases as drafts that are no longer tied to a tag (because you deleted it). To remove it, click to edit it and then Delete Draft.

Posted
AuthorPaulo Fierro

Recently Niqui and I have become addicted to paddleboarding. We've started doing paddlefit with the guys from Waterman and renting boards in the weekend to go paddle around Seven Mile Beach. This is especially beautiful at sunset.

A week ago we made the jump and picked up a cheap deal on a second hand board on eCayTrade which we've been sharing.

This resulted in us doing what we call a "paddle run". Start at Governor's Beach and one runs the 2.5km down to Royal Palms while the other paddles. Then we switch and head back. Good fun, but the runner always wins.

Being summer and there not really being much wind I was intrigued when I saw this video on how to SUK:

Tried it out yesterday but it didn't really work out, there simply wasn't enough wind. I also fear the my kite is too small (12m) and/or the SUP is too big (10' x 29" x 4.5") but I intend to giving it another bash. 

Posted
AuthorPaulo Fierro

On my desk sits a 21" iMac which is plugged into a 27" Apple Cinema Display. The iMac is a great machine, but the audio quality is better coming out of the Cinema Display — larger screen, probably better speakers.

My desk on May 17

So when I'm playing music I always select the sound output to come from the Cinema Display. You can Option+click the Volume icon on the menu bar and select either "Display Audio" or "LED Cinema Display", both mean the same thing. If I want to use the iMac speakers I select "Internal Speakers".

But what if I want to use both? Madness right? After looking around I found that you can create a "Multi-Output" device using the Audio MIDI Setup app.

So after doing that I created a multi-output device called "Both Screens" with output going to the built-in iMac speakers as well as the Cinema Display.

The only downside is that you have to control the volume from the app doing the playback, e.g. iTunes. Whatever volume you had the selected display at is what's used so you may want to swap back to it, set the right volume and then swap back.

Dual monitor sound output. Hell yes.

Posted
AuthorPaulo Fierro

CocoaPods

I'm really glad I took the time to learn and use CocoaPods on this latest project. Such a massive time saver for iOS devs. No more adding linker flags, copying bundles and keeping external frameworks up-to-date manually.

I simply write a Podfile (similar to a Gemfile if you come from the Ruby world), and run "pod install." If a library I'm using has been updated I run "pod update". If a library I want to use isn't available, you can easily submit it to their list of specs on Github.

Great stuff.

Spark Inspector

Its like a Web Inspector for iOS apps. Modify your UI's properties and see the changes live in the Simulator or on your iOS device. you can also see your views in a 3D extruded mode to get a better grasp over how your UI is being laid out.

There's also a notification monitor to see notifications and their payloads as they are fired with the added ability to go back and resend them. Not used this much yet but it looks snazzy.

Crashlytics

I like TestFlight for distributing builds though I will be using Hockey on our next internal app because I've heard great things.

However I no longer ship the TestFlight SDK in our apps because I find the crash monitoring in Crashlytics to be far superior. You can group similar crashes and mark them closed once you've fixed the issue. You also get so many more useful details like available disk space, how many users are affected, etc so I would recommend you give it a shot. I'm a fan.

We're in the business of building things that makes our lives easier and these tools make the development easier.

Posted
AuthorPaulo Fierro

Lately Niqui has been having some issues with her iPhone 5's lock button. It works now and then, but you have to press it 6-7 times before it actually locks the screen which is quite annoying.

You can set phone to Auto-Lock after a minute but sometimes you want to lock the screen at a particular point in time.

Enter LockMe.

lockme.png

LockMe is a tiny app that simply locks the screen and quits. It uses an undocumented function called GSEventLockDevice which does just that. Its part of the private GraphicsServices framework so the app can't be submitted to the App Store, but it does the job until she can get her phone fixed.

There's a few ways to use private frameworks but I found the simplest route was to load it dynamically at runtime. The meat of the app is just ten lines of code.

That's pretty cool if you ask me.

So if you or someone you know has the same issue, grab the app from our GitHub repository, build it for them and be a hero :)

Posted
AuthorPaulo Fierro

I'm currently working on an internal iOS app and while I was working on putting together the About screen I ran into an issue where unicode characters in a UILabel were being displayed as emoji by iOS. While this is kind of awesome, its not really what I was going for.

So my code:

label.text = @"Made with ❤ by jadehopper ltd.";

results in:

madewithemoji.png

To disable the emoji character we have to tell iOS to use the variant of this character. In order to do this we change the label text to:

label.text = @"Made with ❤\U0000FE0E by jadehopper ltd.";

which results in:

madewithnoemoji.png
Posted
AuthorPaulo Fierro

When Niqui and I moved over to Grand Cayman last summer we realised that one of the things that we had been completely spoiled with while living in Brighton was the great tech-community and the amazing people that live and work there — some of which we are lucky enough to call friends.

interactiveky

Soon after moving over, Garth Humphreys invited me to a couple Facebook groups which allowed me to (virtually) meet other people in our industry living on our tiny island. Recently we'd been chatting with some friends at BB&P, a local agency, who were also looking to get the local community together and they kindly invited us to use their space.

So earlier this month we had our first get together so we could meet in meatspace. Our first meetup was a great success and everyone that turned up was keen for more of them.

And so we have interactive.ky — a meetup for designers & developers living in the Cayman Islands. Our next one is next Wednesday, April 3 and you're more than welcome to come join us.

Earlier today Ingrid Riley wrote a lovely piece on our group over on Silicon Caribe.

Posted
AuthorPaulo Fierro

This weekend marks the 25th Taste of Cayman — a food and wine festival put on by the Cayman Islands Tourism Association (CITA).

This year you can buy the tickets online on their site built by Netclues. However, the purchase process is entirely insecure. Taking customers' credit card details in this manner is both irresponsible and unprofessional and it also violates the Payment Card Industry's (PCI) Data Security Standard requirements to protect cardholder data (point #4). I'm no lawyer but I believe if the card details were to fall into the wrong hands they would also be financially liable.

I tweeted at CITA and Netclues but they didn't reply.

When we help clients build anything, be it a site or an app it falls on us as the designers and developers to educate and inform them about issues like this. I am appalled that the people in charge of developing this site would roll out a payment solution without something as basic as an SSL certificate in place — trying to visit the tickets page over HTTPS results in a 404 error (page not found).

If a relatively inexpensive SSL certificate is not installed then I do wonder how much care and attention has been put in place behind the scenes to store credit card details in a safe and secure manner. 

Its 2013 — we should know better. We should expect better.

In any case, we are looking forward to attending the event but purchased our tickets the old-fashioned way.

In person.

Posted
AuthorPaulo Fierro

I was using Charles earlier to monitor some HTTP requests and noticed that every few seconds a request would show up trying to ping 127.0.0.1 (localhost) on port 7682. This was odd so I did a quick search and found that I had actually tweeted about this approximately 112 days ago — and had completely forgotten.

So if you see this, simply disable the Adobe Edge Inspect extension in Chrome in the Extensions settings.

Let's see if I remember this time.

Posted
AuthorPaulo Fierro

I am a big fan of Sinatra and have been writing a few apps using this lightweight Ruby framework. Deploying them on Heroku is a breeze and painless but I always seem to forget a step so this is more of a note for future me.

I wrote a template that sets up a very basic Sinatra app that outputs JSON — perfect for when I need to set up a basic API for an iOS app. There's no database, so DataMapper is nowhere to be found and there's no tests either, just extreme simplicity.

Assumptions:

  1. you already have a Heroku account and have the Heroku Toolbelt installed
  2. you are on a Mac, though I'm sure its not too dissimilar for Windows folk
  3. You have the Bundler and Shotgun gems already installed

So with that out of the way,

  1. Download the template, and unzip it into your new apps' folder
  2. Navigate to the folder in Terminal and then run bundle install
  3. Check that everything is working by running shotgun. Then fire up a browser and navigate to http://127.0.0.1:9393
  4. Next we need to create the local git repository: git init
  5. Now we add all of the files: git add .
  6. Then we commit them: `git commit -m 'first commit'

Now we're ready to create the app on Heroku. For this example lets call it "myapp".

  1. In the Terminal create the app (the default stack nowadays is Cedar which is what we want): heroku apps:create myapp
  2. Because the git repository already exists, the Heroku toolbelt should have set up a remote for us, but lets double check: git remote -v
  3. Double check that the remotes look like heroku git@heroku.com:myapp.git for both fetch and push
  4. Deploy! git push heroku master

Now if you navigate to http://myapp.herokuapp.com you should see some successful JSON output.

Now go build your app!

Posted
AuthorPaulo Fierro