Category Archives: Development

Reading JSON from a file (in the Documents folder) into an NSDictionary in iOS

So you have a JSON file stored in the user’s Documents directory in your iOS app, and now you want to read it. First, you get the URL to the file by getting the user’s NSDocumentDirectory, then you can append your filename to it. To get the data out, you can read with NSString and use NSJSONSerialization JSONObjectWithData:options:error:. Note that in the Gist NSJSONReadingMutableContainers is used to ensure the dictionary is an NSMutableDictionary instead of NSDictionary. (You can choose other options to make the dictionary immutable, or partially mutable.)

PhoneGap: automated app building with Grunt, Node, Watch, Sass

After much fiddling around, this is the solution I’ve ended up with that uses Grunt, Node, Watch, and Sass:

  • Install Node: http://nodejs.org
  • Create a package.json: NOTE: I froze versions of my dependencies. You may want to use ~ instead.
  • Install/update node packages: npm install
  • Create a Sass directory in your www: mkdir www/sass
  • Add an SCSS file in your www/sass
  • Add a Grunt config script:
  • Run Grunt (and it will keep rebuilding any time a change to app.scss or your www/* files happens): grunt
  • Open the Xcode project: open platforms/ios/YourAppProjectName.xcodeproj/
  • Run the iOS simulator

PhoneGap: why there is no platform.js

There is no platform.js in your PhoneGap project anywhere because it’s autogenerated. However, if you are getting errors that platform.js never gets generated, perhaps you’re not running the right build command. There is a difference! cordova build ios is not correct with PhoneGap. Rather use:

# *Not* cordova!
phonegap build ios

PhoneGap: removing the iOS 7 status bar

A quick guide removing the iOS 7 status bar:

  • Visit https://github.com/phonegap-build/StatusBarPlugin
  • Add the plugin: cordova add plugin https://github.com/phonegap-build/StatusBarPlugin.git
  • Add this to your config.xml:
    <gap:plugin name="com.phonegap.plugin.statusbar" />
    <gap:config-file platform="ios" parent="UIStatusBarHidden">
        <true/>
    </gap:config-file>
    <gap:config-file platform="ios" parent="UIViewControllerBasedStatusBarAppearance">
        <false/>
    </gap:config-file>
    <preference name="StatusBarOverlaysWebView" value="true" />
  • Rebuild: phonegap build ios

PhoneGap: changing the iOS app name

A quick guide on changing the iOS app name:

  • Remove the iOS platform first: cordova platform remove ios
  • Edit www/config.xml:
  • Change the <widget> id, name, description, and author entries to your liking
  • Add the iOS platform back: cordova platform add ios

sBASSdrum: Upcoming development

You have spoken. I am listening.

As sBASSdrum has largely been a side project, many features did not get implemented in the first release, nor the second. But know that your feedback on the iTunes App Store has not gone unnoticed! I’ll respond to a few of them:

  • Metronome / Pre-Record Count-In: Probably the #1 most requested feature, and I absolutely agree. I have been doing live recorded music for quite a while and even my tempo is not consistent! This is definitely slated for inclusion in an upcoming release. In fact, I have a number of ideas on a better metronome that isn’t just a “click” sound.
  • Saving Loops: There is no current way to save your loops and sometimes when you launch the app your current loop disappears. This is definitely a known issue.
  • Recording X/Y Pad: I hope to introduce X/Y pad automation recording! Actually, any “effect” ought to be automatable.
  • Importing Sounds: Absolutely. You are currently only able to use the built-in sounds but at some point your own sound fonts will be importable. After all, it’s backed by a PCM sampler!
  • Sound Exporting: There is no way to render out your sounds or loops unless you capture the audio with Audiobus. A planned feature is the “Flight Recorder” that will enable recording of a session. Possibly uploading direct to SoundCloud, out to iMovie, or other apps.
  • User-Definable Patches: Absolutely. Currently you are locked into the chord progressions that I’ve created
  • MIDI Support: All in good time.
  • iPhone Version: All in good time.

Things that were added in response to user requests:

  • Big buttons: Buttons are big and tap targets are actually generous!
  • Audiobus: Enjoy audio sharing!
  • Looper: The first version of the looper made it into the shipping version.

Developer Tip: 30×30 (60×60) is still a good custom UITabBarItem size

icon_30x30

Working with UITabBarControllers is fun. Once you get the hang of making UIViewControllers in your storyboard, Ctrl+drag linking them to your UITabBar is quick and easy. But chances are you will want custom tab bar icons. Here are some tips:

1. Icons should be 100% white with a transparent background

Even the updated iOS HIG says this. Use a PNG.

2. Make the high resolution version fit in a 60×60 rectangle

The docs will tell you that you have a 96×64 max size, but this not only doesn’t look great but it is just too large for most cases. Begin creating your art to fit in a 60×60 rectangle. Then, top-align and horizontally-center the content in a 100×100 canvas:

icon_centering

The resulting icon will be neatly centered with room at the bottom for the bar item title.

3. Save the high resolution first as “filename@2x.png”

As discussed in other tutorials, Interface Builder will do some magic for you. Save your high res version first with “@2x.png” at the end of the filename. Next, scale the image down to 50×50 and save again as just “.png”.

Note: if you are using Adobe Photoshop CC you can use the awesome Adobe Generator syntax to automatically render out both versions of the assets as you update the graphics automatically.

Developer tip: Taming UIPageViewController to do paging

I am coming off of several days of head-scratching as I have been trying to understand how UIPageViewController works. There is a lot of documentation to read and even with a good tutorial I still had questions. Hopefully this helps you:

1. Forget Interface Builder

Seriously. IB has given me more headaches. Yes, there’s a component you can drag and drop but it never worked great for me. Just make a plain view as the container that will hold your UIPageViewController. Even if you use Xcode’s new project Page-Based Application template you’ll end up with the same thing.

2. You want to implement the <UIPageViewControllerDataSource> protocol on your UIViewController

Keep things easy to begin with: whatever UIViewController that is serving up your UIView, make it the data source too. You will have two methods to implement where they will get the current UIViewController and be expected to return new UIViewControllers for the page before or after.

Note that the gist also has a factory method to return the UIViewController for the page number. In this case, all pages are just instances of SomePageViewController. You can imagine that each page might be a different view controller.

3. Don’t worry about navigation dots unless you want to.

If you want those dots on the bottom of the screen that show the user which page they are looking at, you’ll need to implement something like this:

3b. If you do implement the dots, presentationIndexForPageViewController: may only be called once

I had thought that every time you navigate this method would get called. Not necessarily true: it and the count method get called during some setup phase and don’t need to be called again. If you want to keep updating the number of dots or do some cute navigation trick where the current dot doesn’t map exactly to a specific page, good luck.

4. Alloc/init the child UIPageViewController

In your viewDidLoad: of the UIViewController mentioned in Step 1, do something like this:

5. There is no manual previous or next page … but you can reset the view controllers array and fake it with animation

UIPageViewController seems like it is overly simplistic. There is apparently no easy way to navigate prev/next. But what you can do is reset that view controllers array and indicate you want it to animate. So, let’s say you want to go to the previous page, this is a possibility:

That’s not great but it works. For instance, let’s say you wanted to go to the first page, if you followed a similar technique then:

To the user it would look like the page coming in immediately to the left is the first page. They would not see a flurry of pages fly by as it seeked to the first page.