More Than Devs: Providing Support as an iOS Developer

Today I gave a presentation on providing support for your iOS app as an iOS Developer. It’s a near-inevitability if you release an app for public consumption.

Many developers probably don’t even consider support as a potential issue while developing their applications – and are then flooded with requests, suggestions and feedback when their applications take off!

Here are some things to consider re: supporting your iOS app – even before you release it!


Support Considerations

  • If you’re a single developer – not working on a team – you should identify the basics of how you will support your application: how much time you’ll put into support, how many requests you’ll limit yourself to, whether or not you’ll provide self-service help to your customers, etc.
  • If you’re on a team of developers, awesome – think about setting someone (perhaps on a rotating schedule) to handle support requests for your app. It splits up the work and lets you plan your development work.
  • Consider setting limits for yourself: “I’ll only fix critical, app-crashing bugs”, or “I will focus mainly on performance and GUI issues; feature work can wait”
  • Give yourself the tools to succeed: decide what channels you’ll be using for your support (Email, Ticketing System, Twitter, Facebook, etc) and stick to them

Providing Support

  • Remember: your users are your customers. They may frustrate you, but remember to understand their side of the story too. If they have a frustration, it’s likely affecting other users too!
  • This is your application, and thus you have the final say on feature development/implementation. You won’t satisfy everyone!
  • Provide channels for feedback and support, separated or at least sortable if possible. It will help you sort both types in the long run.

Suggested Tools

  • Get yourself some analytics tools: AWS/Google Analytics can give you insight into how users are actually using your app, while platforms like Crashlytics will help you fix and identify bugs/crashes more quickly
  • Don’t overload yourself with channels: pick one or two at most. Twitter gives you a public-facing reply ability and a private one; but managing those requests can be nuts. Consider a ticketing system that will let you easily automate/manage/view your requests.
  • Give your customers self-service tools. As often as it gets skipped over, documentation can be an absolute life-saver!
  • Bonus: Provide some in-app tools! A good example: provide the ability to submit an email or ticket right from your app. There are lots of great SDKs out there that will give you this (and much more) functionality.

Note that these bullets just scratch the surface. There are many, many more tools and considerations you will need to make for your application. Ultimately, decide what works best for you – and modify your workflow(s) to best fit your support philosophy.

Best of luck to you, fellow app devs!

Best of luck to you, fellow developer!

Using an Objective C Framework with a Swift Project – Bridging Header (Xcode)

I was recently working on a personal project and checking out an Objective C framework. However, as I learned from doing a Google search, it’s not as easy as just throwing the ObjC framework into your project and then crossing your fingers.

I found a good tutorial on Randexdev, but I thought I would add my own here – one part of my setup, in particular, had to be changed for Xcode to compile.

Thus, here’s a short tutorial on pulling this off.

Step 1 – Copy the Framework into your Project

  • Drag and drop the framework into your Xcode project
  • Make sure you select/check “Copy Items as Needed
  • You should now have a .framework file in your project (some come with other files which may need to be imported as well), such as Bird.framework

* Make sure you do the second bullet – otherwise the project may have issues finding the files in the future; best to copy them for your own purposes).
Step 2Tell Xcode where to find the headers

  • Select your Project in the Project Navigator
  • Select your Target (if you only have a base app, it should be selected by default) in the list of Targets
  • Go to Build Settings in the upper part of the Target’s window
  • Search for “Header Search Paths” using the search bar
  • Add a new line but clicking the “Plus” ( + ) button
  • Add the path to your framework’s headers; this will vary depending on where you’ve placed your framework file.
  • In this example, I’ve used a placeholder for the project directory – “$(PROJECT_DIR)” – and then, since my Framework was in the default directory of my app, I referred to it by name – “Bird.framework” – and finally, added the path for the headers file with “/Headers”.

$(PROJECT_DIR)/Bird.framework/Headers

Step 3 – Adding a Bridging Header

There are several ways to add/create a bridging header; I find it’s easiest to make my own using the below method

  • Select your project file in the file viewer in Xcode (left hand side)
  • Hit ⌘N and choose to create a new iOS -> Source -> Header File
  • Save it with a name using the following syntax:

ProjectName-Bridging-Header.h

  • For example, if you had a project called “BirdIsTheWord” you would name the file BirdIsTheWord-Bridging-Header.h

Step 4 – Import your headers from your framework

  • Navigate to your new Bridging Header file
  • Now you’ll import the headers from your framework – many frameworks have one main framework which will import everything for you (and is a lot better than importing every single little header) – for example, you may just need to add something like this:

#import “BirdMain.h”

or

#import <Bird/BirdMain.h>

I’ve seen it work both ways – it may depend on the framework you’re using.

Step 5 Proclaim your undying love Bridging Header to Xcode

  • Navigate back to your Project -> Target -> Build Settings where you previously worked in Step 2
  • Search for “Objective-C Bridging Header”, and double-click on it’s value, then add the location of your Bridging Header file

This part messed me up a bit. Some tutorials say using a path similar to what we used above in Step 2, but that did not work for me.

$(PROJECT_DIR)/BirdIsTheWord-Bridging-Header.h

Instead, this is what worked out for me:

./PROJECT_NAME/PROJECT_NAME-Bridging-Header.h

So in my example above, I used:

./BirdIsTheWord/BirdIsTheWord-Bridging-Header.h

  • Hit Enter -> Build (⌘B) -> DONE! 😀

You should now be able to use the framework without any issues in your Swift files. It’s pretty handy – Xcode actually goes in and translates the syntax of your Framework’s language into Swift, making it incredibly easy to code using Swift and take advantage of an entire framework!

Hope this helps someone (other than me) some day. I leave you with Peter Griffin.

Indeed Peter, indeed.

Indeed Peter, indeed.

WatchKit and Apple Watch Resources

In preparation for a presentation I’m going to be giving on March 3rd, I wanted to list some of the (frankly amazing) materials I’ve come across dealing with WatchKit and  Watch. First things first: Apple’s own website has an extensive section on all things  Watch related 🙂

A huge shout-out to Ben Morrow of Realm.io, who has an extensive list of WatchKit resources he’s put online and has done some excellent tech talks on the subject. You can find him on Twitter: @benmorrow.

I highly recommend his WatchKit talk on Realm.io. He provides a great overview of WatchKit and goes through some simple but in-depth examples. Also came across his happywatch blog – highly recommended for some redirects to great existing Watch materials. Finally, one particularly useful document on happywatch is the WatchKit cheatsheet for developers. It’s mainly info on what WatchKit is, and what is does (and does not) do!

Of course, you can’t research many things iOS-development related without Ray Wenderlich. So BOOM: WatchKit Impressions.

Finally, there’s Apple’s Developer Documentation on WatchKit. It doesn’t get much more detailed than that 🙂

Live long and prosper.

RIP

Follow My Touch, Little Spaceship (Pt 4)

I am really going to need some of this shortly.


So after a bit of struggling with the Trig to figure out exactly what I’m going to need, I decided that I’m pretty bad at Trig and should probably take that course all over again (this Wikipedia article on Orientation in Geometry made my mind melt a little bit). Just happy I’m not an architect.

I got some help from a colleague on this one (thanks Zina!) – her recommendation was the following:

  • Calculate the change in position X (horizontal movement) using the touched location’s X coordinate & the current location of the sprite’s X coordinate
  • Do the same, but for the Y coordinate (vertical movement)
  • Calculate the radians using change in X/change in Y

… totally doable. I think. The change in X would be the differential (subtracted value) of the location’s X coordinate from the sprite’s X coordinate. Same with Y. So:

Change in X = locationX – spriteX

Change in Y = locationY – spriteY

As pseudo-functions (haven’t translated to Swift yet):

changeX = location(x) – sprite.location(x)

changeY = location(y) – sprite.location(y)

Now, back to Xcode, and let’s translate these into Swift functions. It turns out that a sprite doesn’t have a “location”, but a “position”:

var changeInX = location.x – sprite.position.x
var changeInY = location.y – sprite.position.y

Awesome. More progress. Now to calculate the angle in radians. This is where Ray’s function comes into play.

atan2f(_playerSpeedY, _playerSpeedX)

As a Swift function using our new values (after checking Ray’s function, we aren’t using float values, so you can drop the “f” in atan2f and use the atan2(Y,X) function instead):

var radians = atan2(changeInY, changeInX)

Finally, let’s make that rotateToAngle useful:

let rotateMove = SKAction.rotateToAngle(radians, duration: 1)

So the touchesBegan() function now looks something like this:

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */

for touch: AnyObject in touches {

// Specify the location where the sprite should move

let location = touch.locationInNode(self)

// Calculate change in X/Y position
var changeInX = location.x – sprite.position.x
var changeInY = location.y – sprite.position.y

// Calculate the angle in radians

var radians = atan2(changeInY, changeInX)

// Denote the actions for rotating and moving the sprite
let rotateMove = SKAction.rotateToAngle(radians, duration: 1)
let actionMove = SKAction.moveTo(location, duration: 1)

//Perform the rotate & move actions
sprite.runAction(rotateMove)
sprite.runAction(actionMove)

}
}

Are we there yet? Never know. Let’s give this a shot.

Whoa! Something isn’t quite right here.

Okay. So we’re definitely not done yet. First, it doesn’t seem like our ship is orienting properly – so our calculation for radians is probably off. The other thing is, we’re also telling it to do two actions… that could be messing things up too.

I remember reading something from Apple’s docs about SKActions in a sequence. That part isn’t too difficult, simply make a sequence object using SKAction.sequence and an array of the actions in the order you want the ship to take them. Then, add the newly formed sequence object in as your argument in the runAction() function:

// Denote the actions for rotating and moving the sprite
let rotateMove = SKAction.rotateToAngle(radians, duration: 0.5)
let actionMove = SKAction.moveTo(location, duration: 1)

//Perform the rotate & move actions
var spriteMoveSequence = SKAction.sequence([rotateMove, actionMove])
sprite.runAction(spriteMoveSequence)

This negates any problems we might have with the action sequence being wrong. Next, we need to fix our calculation. Our calculated angle clearly isn’t correct…

var radians = atan2(changeInY, changeInX)

The value is off by a certain amount… but which amount? Ray gives us yet another win here: “The atan2f() function returns a value in radians but the direction we are pointing is off by 90 degrees.” We’re using atan2, but it should be similar, right?

Well, if π is 180 degrees, and we’re off by only 90, let’s try subtracting (π/2) – or 90 degrees – and see what happens. Swift has the constant “M_PI_2” to denote the value of π/2:

var radians = atan2(changeInY, changeInX) – CGFloat(M_PI_2)

What is the result? BOOM, that’s the result!

Huzzah!

We did it! The spaceship now appropriately orients itself and moves toward the specific location that you touch (or click, in the case of the Simulator).

That wraps up this tutorial! Congratulations 🙂

Follow My Touch, Little Spaceship (Pt 3)

More spaceship progress!

If you recall, we have one last major step to finish, with two distinct components:

  • The spaceship needs to move
    • First, it needs to turn/orient toward the point that was touched
    • Second, it needs to move to and then stop at the designated/touched location

After some Google Searching, I found an article about creating a “Space Shooter” on Stefans Dev Playground. This should help us with the last few coding components we need.

This time, we’ll need to use the touchesBegan function, because we’re going to be looking for a touch/event to cause the spaceship to move.

Stefan gives us the code we’ll need to move our Sprite, though he actually creates a second, invisible sprite to denote the path the Sprite should take. I don’t know yet if this is necessary, but this piece of code looks particularly promising:

// Create an action to move the hero sprite to the touch location

let actionMove = SKAction.moveTo(location, duration: 1)
heroSprite.runAction(actionMove)

After checking out Apple’s class reference on SKAction, this looks like exactly what we’ll need to move our Sprite!

First, let’s set our location – it looks like this is pretty easy to do, using this line of code:

var location = touch.locationInNode(self)

So we have a location to feed to our SKAction.moveTo() function. Duration can be whatever we want it to be.

Let’s try adding these basics to our touchesBegan() function:

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */

for touch: AnyObject in touches {

let location = touch.locationInNode(self)

// Create an action to move the hero sprite to the touch location
let actionMove = SKAction.moveTo(location, duration: 1)
sprite.runAction(actionMove)

}
}

And voila! Our spaceship now moves to the location we touch! Check it out:

Awesome! Okay, so now our ship moves. But we want it to orient itself toward the location we specify with our touch.


After some Google Searching, checking Apple’s reference class for SKAction and a tip from a colleague, I found out that “orient” isn’t the right word: we want rotation for our spaceship.

This rotateToAngle:duration: function looks very promising. We can specify an absolute angle toward our touched location, and then tell the spaceship to move to that location.

I’ve never calculated an angle like this before… so… to the internet!


AHA! Ray Wenderlich strikes again! I haven’t done Trig since early in college, so this article was a lifesaver. After reading a lot about angles, radians and something about a pie (it has seriously been awhile), I came to the conclusion that this would be a handy function:

float angle = atan2f(_playerSpeedY, _playerSpeedX);

And that I needed to calculate an X, Y, and an angle. Why the X/Y? Because Wenderlich said so, that’s why.

So… let’s write this out first (and comment it into Xcode):

  • Calculate the ship’s change in X and change in Y coordinates
  • Calculate the angle based on the X/Y changes
  • Rotate the ship based on the angle you calculated
  • Move the ship to the specified point

I think I’ll tackle that in a new post. Oddly enough, if you recall, back at the top of this post I noted we have two steps to complete: rotating & moving the sprite. It turns out we actually successfully completed the second part (moving the sprite) before rotating. Oh well – progress nonetheless.

Follow My Touch, Little Spaceship (Pt 2)

Now, it’s time we got that Sprite back.

We already have the necessary code for creating a Sprite:

let sprite = SKSpriteNode(imageNamed:”Spaceship”)

We also have some code for specifying the position & scale of the sprite:

let location = touch.locationInNode(self)

let sprite = SKSpriteNode(imageNamed:”Spaceship”)

sprite.xScale = 0.5
sprite.yScale = 0.5
sprite.position = location

However, the Sprite needs to appear prior to a touch on the screen. So, using Ray’s tutorial above, we can see that we need to:

  • Create the Sprite (and make it accessible to any/all of our functions)
  • Provide the Sprite a position & size
  • Add the sprite as a child to our view/scene – but not upon touch; we want it immediately

First, let’s create the sprite, and make it accessible to our functions by putting it at the top of our GameScene class:

class GameScene: SKScene {

    let sprite = SKSpriteNode(imageNamed:”Spaceship”)

override func didMoveToView(view: SKView) {

/* Setup your scene here */

}

Next, let’s give the Sprite a position and size in our didMoveToView function. We’ll use a position, designated as a CGPoint, similar to Ray’s:

player.position = CGPoint(x: size.width * 0.5, y: size.height * 0.5

And a size, which we can take from our touchesBegan function using xScale and yScale.

sprite.xScale = 0.25
sprite.yScale = 0.25

Finally, we need to add our Sprite to the scene/view as a child object. So we’ll add a piece of code to our didMoveToView function:

self.addChild(sprite)

The result looks something like this:

class GameScene: SKScene {

let sprite = SKSpriteNode(imageNamed:”Spaceship”)

override func didMoveToView(view: SKView) {

/* Setup your scene here */

sprite.position = CGPoint(x: size.width * 0.5, y: size.height * 0.5)
sprite.xScale = 0.25
sprite.yScale = 0.25

self.addChild(sprite)
}

Now, when you preview the app in the simulator, you’ll see your new sprite!

A wild spaceship sprite appears!

A wild spaceship sprite appears!


Last, but not least, we need to code up the final pieces of the puzzle:

  • The spaceship needs to perform two actions upon a touch
    • First, it needs to turn toward the point that was touched
    • Second, it needs to move to and then stop at the designated/touched location

We’ll tackle that in the next post.

Follow My Touch, Little Spaceship (Pt 1)

If you haven’t seen The Lego Movie, you really should.

So you wanna guide a spaceship with a finger tap in Swift.

Let’s do this. Start with a blank SpriteKit project.

First things first: let’s look at GameScene.swift:

class GameScene: SKScene {
override func didMoveToView(view: SKView) {
/* Setup your scene here */
let myLabel = SKLabelNode(fontNamed:”Chalkduster”)
myLabel.text = “Hello, World!”;
myLabel.fontSize = 65;
myLabel.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame));

self.addChild(myLabel)
}

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */

for touch: AnyObject in touches {
let location = touch.locationInNode(self)

let sprite = SKSpriteNode(imageNamed:”Spaceship”)

sprite.xScale = 0.5
sprite.yScale = 0.5
sprite.position = location

let action = SKAction.rotateByAngle(CGFloat(M_PI), duration:1)

sprite.runAction(SKAction.repeatActionForever(action))

self.addChild(sprite)
}
}

override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}

There’s a lot of unneeded code here. Let’s get rid of the Label first. That leaves you with:

class GameScene: SKScene {
override func didMoveToView(view: SKView) {

/* Setup your scene here */

}

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */

for touch: AnyObject in touches {
let location = touch.locationInNode(self)

let sprite = SKSpriteNode(imageNamed:”Spaceship”)

sprite.xScale = 0.5
sprite.yScale = 0.5
sprite.position = location

let action = SKAction.rotateByAngle(CGFloat(M_PI), duration:1)

sprite.runAction(SKAction.repeatActionForever(action))

self.addChild(sprite)
}
}

override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}

A few other things come to mind:

  • We only need one Sprite
  • We don’t need it to spin forever; only when we make a touch, and only toward where we make that touch
  • We need to make the Sprite move

Let’s tackle the first one. We only need a single Sprite. Right now, any time we touch the screen, a new “child” Sprite is added. That won’t work – we need a single Sprite to appear at a specified location. Let’s get rid of the add child part in the touchesBegan function – and, while we’re at it, let’s drop the rotation part… however, we might need that function later to rotate the spaceship (haven’t figured that part out yet). So let’s comment it out.

We really only have one function that’s doing anything: touchesBegan.

class GameScene: SKScene {
override func didMoveToView(view: SKView) {

/* Setup your scene here */

}

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */

for touch: AnyObject in touches {
let location = touch.locationInNode(self)

let sprite = SKSpriteNode(imageNamed:”Spaceship”)

sprite.xScale = 0.5
sprite.yScale = 0.5
sprite.position = location

/*let action = SKAction.rotateByAngle(CGFloat(M_PI), duration:1)

sprite.runAction(SKAction.repeatActionForever(action))*/
}
}

override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}

And actually, the program does nothing right now, because the touch doesn’t add the Sprite as a “child” to your scene at all:

followMyTouchPt1

Nothing here… yet.

In my next post, I’ll tackle how to get the sprite to appear (once), and then we’ll start working on getting our spaceship to move.

SPACESHIP BLAST OFFFFFF