onFocus/onBlur events (or becomeFirstResponder/resignFirstResponder) on NSTextField Cocoa Swift

Since having worked with html/javascript it’s inevitable that such question would eventually arise, in that exact format. In Swift, the onFocus/onBlur events are represented by becomeFirstResponder() and resignFirstResponder(), respectively. This sounds rather simple, until you start working with the  NSTextField class on macOS. And what’s interesting about that? Well, turns out the component will trigger a ‘focus’ event and immediately a ‘blur’ event — It seems the actual object that receives the cursor is a NSText object that lives inside the NSTextField.

After a long search with no real progress, I decided to dive in and come up with a solution myself. And turns out it seems rather simple as well, all that is needed is to subclass the NSTextField class, hijack some methods and away we go.

 

How to make Cocoapods for iOS, macOS (OSX), watchOS and tvOS

Since having published the GhostEventCenter lib for iOS on Cocoapods I have started working on a Mac application which would benefit from that lib. But how to make a pod for all platforms from one source code? Online you can find lots of things, from cocoapod 0.2 versions to newer tutorials using Swift (bingo!). I managed to dig up a few sources that explain how to achieve such thing. Those guys go into the details, really worth reading it all thru. Yet, my first attempt didn’t fail to compile or anything, just wouldn’t bring the classes I needed on the macOS side of the project. Luckily, you can find sources and following these, I managed to get the pod built for iOS, tvOS, watchOS and macOS. One pod install and done!

http://basememara.com/creating-cross-platform-swift-frameworks-ios-watchos-tvos-via-carthage-cocoapods/
http://www.enekoalonso.com/articles/creating-swift-frameworks-for-ios-osx-and-tvos

happy days.

Just in case, GhostEventCenter is now version 1.1 and should work on all platforms! Add pod ‘GhostEventCenter’ to your Podfile and away you go.

New TrailerTime update, GhostEventCenter cocoapod framework release, Alamofire, etc

So I finally had time again to get back to my projects. I had previously decided to work on everything Swift from scratch, but eventually I realised that I was recreating the wheel for no reason. With an update to those apps (more need to be updated, though) more than due, I went back on TrailerTime and changed a few important things: a) it now uses Yahoo’s YQL for some things; b) implemented common and popular libraries and replaced my buggy attempts to recreate them myself.

It’s easy to justify creating a lot of code in the name of “learning”, but when I figured that Alamofire is in the heart of like 85% of everything, not be using it is the oddball. So I decided to go with some “standards”, and clean up my mistakes quite a bit. Now, going with YQL is a bit of a gamble. Yahoo has had the rope around the neck for some time, but I can’t find anything along the same lines of YQL, not even a private company/solution. It’s simply too good, and I doubt it would be killed like that.

Meanwhile, I have been working with a custom event center library. It works great, but compiling it really is a bit annoying (I will post more on that later). So again, to get some basic things, I decided to push it via Cocoapods — it’s called GhostEventCenter, hopefully makes someone else’s life easier too.

If the end of all this journey, TrailerTime 1.1 is now on the app store, bug free and ready to get more functionalities added — something I will be doing soon.

Solving a HackerRank challenge with a Runtime Error in Swift

I was playing around with HackerRank, doing one of their past rookie challenges that goes like this:
“Colleen is turning n years old! She has n candles of various heights on her cake, and candle i has height height. Because the taller candles tower over the shorter ones, Colleen can only blow out the tallest candles.

Given the height for each individual candle, find and print the number of candles she can successfully blow out.”
https://www.hackerrank.com/contests/rookierank/challenges/

Input is passed in via 2 lines of text, first line is the number of candles and second line is the heights.

So I came with this solution for the challenge:

Turns out 2 of the tests failed. Why? Runtime Error. Wtf? I wanted a smart-ass solution, but maybe my mistake was to append too much in one single line that it was overloading something? So I started taking things apart, creating new vars, even though that shouldn’t make much difference in my mind. And of course, it didn’t do.

Annoyed with it, I did it again, this time using for loops in a much less elegant or optimal way:

And, guess what? That worked. Nothing to really ‘fix’ the runtime error. So I suppose next time (if ever again) I do one of those for fun, I better remember to not make it fancy.

Creating a date from a string in Swift using NSDateFormatter

I am consuming a feed that uses a date string as “Mon, 29 Aug 2016 5:12 AM GMT”. So in Swift when converting strings to dates, you are effectively just creating a point in time reference, which means a date object for that string would be something like 29/08/16 05:12.

Annoyingly, it seems that NSDateFormatter doesn’t understand what BST is, while some other timezones seem to work ok.

So instead of relying on the formatter, it would be better to break everything apart and rebuild it from ground up:

 

Adding a blank state to a UIViewController in easy steps

When loading an app for the first time, I wanted to display a “nothing here yet” message. This method works when adding a view (the blank state) on top of everything else in the same screen/view.

Step 1: create a .xib with all the design

Screen Shot 2016-08-26 at 02.26.24

Step 2: create a new Swift file/class. For consistency it’s a good idea to keep both files using the same names — I’ve named them NoBookmarksView.xib and NoBookmarksView.swift. Open the swift file and add:

Step 3: Open the .xib file and set the File’s Owner, in the Document Outline, to NoBookmarksView. Now when showing the Assistant Editor it will be possible to create the IBOutlets and IBActions in the Swift file.

Screen Shot 2016-08-26 at 03.03.37

Step 4: Open the storyboard where you want this and add a UIView. Set its class to the custom NoBookmarksView. It should auto update and display the .xib since it was marked as IBDesignable.

Step 5: In the main ViewController, then create an IBOutlet for the custom view. All it needs now is just show/hide via code, as required.

 

TL;DR

If you’re using a UITableViewController, you won’t be able to add a custom view on top of everything in IB. In that case you’ll need to place your custom view in the tableView.backgroundView:

 

How to add a UIRefreshControl to a UITableView?

The now standard “pull-to-refresh” action on iOS can be achieved with the help of a UIRefreshControl in a UITableViewController — yes, that loading thingy on top of a list. Apple clearly stated that the correct behaviour is not expected when using the refresh control with other classes (like a UITableView alone, for instance). I decided to give it a run anyway, just to confirm that it was a waste of time. It does work, but it’s not good enough imho.

Over Stackoverflow people have demonstrated several ways of making that work, being the alleged best one instantiating a new UITableViewController and hot-wiring the UITableView to its tableView property. Code as on stackoverflow:

That works indeed, but I thought it was a bit nasty. But why was I looking into that in first place? Because I wanted to display empty state message (aka blank slate) if there was no data. So my first instinct was to have a simple UIViewController, add a UITableView to it and solder a custom UIView on top. Just needs to toggle table/view and job done, but then, refreshing the table using the standard refresh control became a bit of a drama.

Either way, in the end I figured I don’t need the refresh control anyway, but I implemented an empty state on a UITableViewController in a totally different way, which I found a lot easier and more flexible — that’s for next post.

Btw, there are a lot of open source UIRefreshControl projects meant to be used on UITableViews on GitHub! :)

Stop, restart.

I won’t even bother saying “I’m still here”. Nothing changed, still no time to do all I want. Only difference is that I will/am focusing on iOS Swift development until the tide changes again. I feel I’ve done a bit of everything frontend related — games, websites, mobile — and I really want to try something new. This was never meant to be a tech blog and there are lots of better people doing exactly the same. I will just randomly try to keep things alive, at least more than I have ever done.

Privacy policy

Finally, after a long while, I’m trying to do some house cleaning over here. It’s not everyday that I decide to work with html, but it’s a necessary part to keep things going forward. Working toward completing my first iOS app, turns out to be necessary to have a privacy policy (turns out to be on Google Analytics’s TOS too) visible to inform how you deal with data. Interestingly, that is something I have been thinking of, to improve usability and general tweaks, so why not stop the engines now and do some parallel job? It’s time for spring cleaning anyway! :)
Soon, website privacy policy in place, plus custom app page.