Archive for November, 2015

Apple TV Store update: Commerce watch

So, after about 6 sales total, I made my app free. 3 sales days later of 6 total sales days, and I have sold a total of 41 units. Total proceeds to date: US$8.14.

Screen Shot 2015-11-16 at 2.11.38 PM

I averaged about 2 sales a day (paid) before going free and about 10 sales a day after.

So how does this massive sales surge affect my chart standings?

Still not in TR:

Screen Shot 2015-11-16 at 2.16.59 PM

But HEY! I made it into TRI! Woo.

Screen Shot 2015-11-16 at 2.16.49 PM

And with TRIV, I’m basically SMOKIN’. Look at me there in position (2,2).

Screen Shot 2015-11-16 at 2.16.36 PM

So this is apparently what 10 sales a day gets you on the Apple TV app store.

I didn’t see “Triviata” in the Top Free Apps on Apple TV itself, but according to Slide To Play, I’m #77 on games:

Screen Shot 2015-11-16 at 2.21.33 PM

Speeding up Swift playgrounds with closure initialization #swiftlang

Swift playgrounds can be ridiculously slow, especially when you’re working with items sourced from SpriteKit and SceneKit. Moving any and all code you can into an external Sources file enables optimized compilation and far better runtime speed.

The big problem with this approach is that you lose the linear flow that you have in playgrounds. Module compilation does not support top level directives that modify variables. So, for example, if you have code that looks like this:

 public let lightNode = SCNNode()
 lightNode.light = SCNLight()
 lightNode.light!.type = SCNLightTypeOmni
 lightNode.position = SCNVector3(x: 0, y: 10, z: 10)

(I apologize for the forced unwrap. This was taken from Apple sample code.) 

You cannot move these lines directly to a module file because you’re using top-level calls, which will not compile in an external swift file. As a workaround, you might throw most of that into a function, like this:

internal func setupLightNode() -> SCNNode {
 let theLight = SCNNode()
 theLight.light = SCNLight()
 theLight.light!.type = SCNLightTypeOmni
 theLight.position = SCNVector3(x: 0, y: 10, z: 10)
 return theLight

And then call it from your declaration:

let lightNode = setupLightNode()

That’s ugly. It creates an unnecessary extra function and it forces you to place the code that processes a new instance before the instance itself is declared.

Closures offer a (slightly) more appealing solution, as you see in the following example. Here, the initialization lines are wrapped together into a single group, and executed, returning the fully initialized instance at the end.

// create and add a light to the scene
public let lightNode: SCNNode = {
  let theLight = SCNNode()
  theLight.light = SCNLight()
  theLight.light!.type = SCNLightTypeOmni
  theLight.position = SCNVector3(x: 0, y: 10, z: 10)
  return theLight

This approach enables you to build and initialize an item using a single statement, retain the flow and readability of your playground declarations, but run things quite a bit faster.

Here’s a video of this lightNode code in action, running along with various other setup tasks. After hitting the playground “run” button, it now only takes about 3-4 seconds to get going instead of minutes. This kind of speed-up means it becomes far more practical to prototype SpriteKit and SceneKit elements in playgrounds before deploying them to real apps.

Update: Here’s another approach for setting up class instances:

infix operator •-> {}

// prepare class instance
func •-> <T>(object: T, f: (T) -> Void) -> T {
  return object

class MyClass {var (x, y, z) = ("x", "y", "z")}
let myInstance = MyClass() •-> {
 $0.x = "NewX"
 $0.y = "NewY"

What do you think?

tvOS dev: Removing “transparency” for top shelf image

Have you gotten an odd complaint message about image transparency for your decidedly non-transparent top-shelf image? Do this:

  1. Open the file in Preview.
  2. Choose File > Export
  3. Select PNG
  4. Uncheck Alpha
  5. Save

Screen Shot 2015-11-15 at 2.50.30 PM

This creates an RGB  version vs the original RGBA version. Use Finder’s Get Info to view the difference.

Screen Shot 2015-11-15 at 2.55.30 PM

Replace your old image with the new one and Xcode stops complaining.

Weekend Posts

Playground alerts for #swiftlang

These alerts are not ideal. You can’t block because then you can’t interact with the alerts which run in the main thread. So they are what they are. (sigh.) I’m figuring you can use one per playground page if you really have to.

Of course, what playgrounds really need are embedded controls, reset buttons (revert to distribution set point, allowing exploratory tweaks to undo), and audio and video narration. Among many other things on my list.

Today, I put together a SpriteKit tutorial proof of concept. My primary tester had to spend nearly an hour just getting the thing running (you need the right iPhone Simulator installed with the right OS / I suspect it’s one of the 6’s) just to spend about 10 minutes looking at my “see what Playgrounds could do in terms of SpriteKit training” stuff. He liked the SpriteKit bits but the playground parts are putting me way way off this concept.

Anyway, here’s some code. Do with it as you will.

New github repository, Triviata price update, and more about app discoverability

After a couple of days of “sales”, Triviata has not proved to be a huge success on the tvOS App Store. I’m shocked, I tell you, shocked.

Screen Shot 2015-11-13 at 7.35.30 AM

Even worse, Triviata has dropped several places on the “TRIV” store search due to new competing products.

Well to hell with that.

I’ve decided to take the classic route of dropping the price to free for a while to see if it can gain store position. (Good thing this isn’t a serious business investment and is more a way to explore the store because…golly.)

Please grab a free copy and let’s see if I can push this baby up the charts. For science! And kittens! And feels!

After updating my pricing details on iTunes Connect, I spent significant time checking whether the listing had updated. That of course was a major pain. The Apple TV app store is not, how shall we say, “friendly”.

So I used my “link opener” opener, which I described in this post to jump directly to the app listing. Because why not jump with a single “Go” button rather than laboriously typing T, then R, then I, then…you get the picture.

Since I’m probably not the only person who will ever be doing this, I’ve put the link opener utility on github. And then I got inspired. What if I could just put a search term in instead and see the search results without the whole scrooooooooollll click scrolllllllllllllclick search routine.

I tried (and I mean really tried) to hack together a solution for searching the store from an app but could not come up with anything. While URLs based on MZSearch.woa are legal and recognized by UIApplication, they lead nowhere meaningful. You get an App Store icon, a spinning wheel, and then nothing.

In similar matters, I have yet been unable to find a way to scrape Apple TV top charts and search results yet. And no, you can’t just sync a Bluetooth Keyboard to your ATV, a decision that completely mystifies me.

Oh well.

In any case, let me know if you find the repo useful and please do download a free copy of the app. I want to run more experiments and I can’t do that when my app isn’t even visible. Thanks!

Ancient tutorials in the age of Swift

So I was talking in irc tonight with someone working his way through some 1.1 tutorials and it took me a bit aback. Many of the language features he described have long since changed or been abandoned, causing him much confusion in the modern toolsets.

What kind of advice can you give someone like that other than “embrace the fact that your language no longer exists and you are learning a dead language”? There are so many fundamental best practices that have shifted, what can a 1.x tutorial give to potential devs living in a 2.x world?

What advice would you give him? Mine is “stick with Apple’s book to learn the basics and keep reading release notes”. What’s yours?

SpriteKit, Pages, Videos, Epub, and Production Toolchains

I was back in SpriteKit world early this week for AppleTV world, and I do really love SpriteKit flaws and all. So I started conceptualizing what an SK Book might look like, specifically tons of “here’s a clever way to accomplish something” (which is kind of a thing with me) with a lot of simple code and embedded videos showing those things in action.

I tried doing video and GIF embeds in my normal workflow and got nowhere (especially with GIFs, which are a dead end) until I turned to Pages. Turns out Pages has no problems embedding and it can produce “universal” epubs (that is, iPhone, iPad, Mac) that can be read and watched in iBooks.

Unfortunately, it also wants a very very specific type of H.264 video, and while Pages can convert the media in-app, it takes approximately forever to tweak each one.

So if I do go this route, I’m going to have to edit in MS Word (sorry, but Pages just doesn’t do style shortcuts as well, producing about a 50% overhead in styling time for paras, examples, notes, headers, etc that I’m not willing to invest). Then transfer to Pages (easy, simple import). Add all the my videos and convert them. And then do the incredibly annoying indexing and cover work that Calibre normally handles.

Not sure I’m willing to spend that much overhead for a project like this.

Of course, having code, description, and videos in an ebook is kind of killer. And I love the video being on the same page and not via a YouTube link. iBooks Author can do some of this but it produces books that are not universal and can never be exported outside the Appleosphere.

If you have any tips for better tools / chains for productions please let me know.

Updates from a post-laptop world: Nulaxy keyboard adapter review

Ever since my daughter stole my laptop, I’ve been trying to make do with my iPad when on the go.

I own an Apple bluetooth keyboard but I hate the chicklets. So I bought this Nulaxy keyboard adapter from Amazon. For $25, I thought it would be a great “bring your own keyboard” alternative. Attach a keyboard, and it converts it to bluetooth for use with tablets.

It arrived yesterday, and this morning I finally got a chance to kick the tires so to speak. Unfortunately, I don’t have good news to report.

The lid of the battery compartment doesn’t stay on and won’t click into place. Any minor vibration on the table with it in use causes the lid and one or two of the batteries to pop out. Not good.

Even taped shut, it’s a disappointment. Unlike most people, I actually have drawers of keyboards around to test. So I grabbed four of them, ranging from low end to high, low-power to mid-power, plugged them into the Nulaxy, and attempted to sync.

I was unable to get a single keyboard to connect to my iPad.

I guess it’s time to process a return at Amazon.