Commit #7: Useful practices for leading an Agile team

2016 has passed, and people had different opinion on it. The internet seemed to think that 2016 is a complete disaster, though. Political turmoils, wars, death of famous figures, and our personal miseries propagated through social medias and memes. This meme depicts the thought pretty well:

I got my share of miseries for 2016, but the old hymn reminded me to count my blessings. I realised that through the whole year, I learned important lessons from my workplace.  One of the most valuable lesson I had was more chances to lead iOS team in projects.

Moving from a single contributor to a team leader wasn’t easy. I need to deliver stories while facilitate my teammates to deliver theirs. Along with other leadership principles that commonly known, I found out that these practices helped me on leading my team, which were establish shared grounds, foster ownership, and schedule technical retrospectives.

Read More

Commit #6: Unwrapping Swift optionals

Update 12 Oct ’16: I’ve updated the code in this post and the Xcode Playground blog post version to Swift 3! Thank you for the wait 😁

As an iOS developer, handling empty value cases in Objective-C is never easy. Let’s suppose we’re making a function that return NSString instance out of a NSDictionary:

Everything seems fine, isn’t it? The method’s logic is pretty clear – it returns the value in user_token key of the JSON. If the key exists, it will return the string. If not, it will return a nil value… dead simple, right?

No.

I left out a sanity check there, but  let’s continue our example for now.

Suppose that the returned string will be encrypted and stored by C++ library. And for that, we need to cast our NSString to C string:

Where’s the problem, Do? Everything looks fine…

Right. The method above looks good – it stopped the process early if passed userToken is nil. Both of them will work correctly, until somebody from the server side single-handedly pass null value in response JSON’s user_token key, instead of omitting it.

Let’s run through the code once again. If the passed JSON is made from NSJSONSerialization process, the user_token key will store a NSNull  instance. Thus, the result from userTokenFromJSON: will be a NSNull instead of a nil or NSString – which will allow it to pass through storeUserToken:‘s early sanity check code (since it’s not a nil), and break the whole app, since NSNull doesn’t have UTF8String method.

Let’s hope this case will never happen in production servers. And yes – I’m looking at you, cowboys.

Due to this issue, nil-checking alone in Objective-C isn’t sufficient. We also need to ensure whether an instance is the right class using isKindOfClass: method. It doesn’t always work well either – for example, if the server on the example above returns a number for user_token value, there’s a chance that it’ll read as _NSCFString (Apple’s private API) instead of a NSNumber.

That’s why after a few month working with Swift,  I grew appreciating the Swift Team’s decision to include Optionals. I believe they made this as an answer to Objective-C’s tedious sanity check. The documentation clearly says that:

You use optionals in situations where a value may be absent. An optional says:

  • There is a value, and it equals x

or

  • There isn’t a value at all.

If I declare a variable to be a String? (read: String Optional), it would either be a String value or a nil. Not a NSNull, not other class type, and not another Apple’s private API. So, userTokenFromJSON: above could be rewritten in Swift into this:

And yes, this method will an Optional – either  String or a nil. 🙂 But the process isn’t ended here – we need to take the available String value out of the Optional. The term is usually called as unwrapping in Swift development – and there are several ways to do it!

Wait, it seems I had enough rant above… this post started to feel edgy. Let’s change the mood, shall we?

In this post, I’ll list the ways for unwrapping Swift’s Optionals that I have found so far. For the sake of the post, let’s assume we got a new function that needs a String input and an Optional variable:

Now, we need to unwrap the name (since it’s a String optional) to pass it to the createGreetings(sailorName:). There are several ways to do this:

Read More

Commit #2 : Export your *.xcarchive to *.ipa via terminal!

December last year, several Ice House clients asked for Christmas update on their app. There’s a strange case that occurred when our team tried to send old projects to the iTunesConnect using Xcode 6’s Organizer, just like this image :

Screen Shot 2015-01-09 at 17.12.22

Our supervisor, Didiet, said this issue might be caused by the project file. The project was built on Xcode 5.1 and we’re trying  to publish it from Xcode 6. Since we don’t have much time left, we ended up using xcodebuild‘s exportArchive command from terminal to export the *.xcarchive from Organizer to *.ipa :

Read More

Commit #1 : Bash up your workspace!

It’s all started when I was assigned to develop a Rails web app with Haris as a team. He worked on the Rails side, while I’m on the HTML / CSS. It was my first time using Rails, and I barely have any experience on web development. Haris told me that there are several commands that should be executed to enable developing the web locally :

  • mysql.server start
  • rvm gemset use iceberg,
  • bundle install,
  • bundle exec rails s, and
  • bundle exec foreman start for running Redis server (on other terminal instance)

At that time, I typed all of those commands on my terminal each time I start working on the app, until I’ve made an embarrassing mistake – twice. Read More