Swift By Sundell – Model Controllers

This is a great post about Model controllers. Upon reading it I realize that I’ve done this for many years, to try and keep things encapsulated.¬†


I’ve been slowly rewriting my Birthdays app in Swift, for no real reason except to see how little code I could write now to reproduce when I wrote 9 years ago in Objective C.

I had been putting a lot of logic in the “Person” class I made. Looking at my old code I had a Person class, and a PeopleController. Not sure why I made that distinction. ūüôā


Birthdays: View on App Store

Apple Acquires Shazam

I still remember being at a WWDC Stump The Experts session where one of the first questions was what were the names of the songs playing before things kicked off, and a developer from Shazam stood up, and rattled all of them off.

There was a roar from the crowd, and he said he was from Shazam. And presumably all of us went and downloaded the app then and there.


Apple’s December 2 Springboard Crash Bug

It’s been interesting to watch this pop up tonight. It looks like a pretty serious bug in iOS 11:


I can imagine what’s happen at Apple right now for the past few hours, engineers in there working and finding and solving the problem. Other folks discussing how to push it out to customers.

I wonder if they are also discussing tonight about pushing the button and releasing 11.2 tonight. I don’t think that’s in the cards if only for the size of that download, vs a super small patch for this one.

Today at work I spent most of the day doing a small firefight around how Touch ID / Face ID works in an app. I’ve come to the conclusion that’s a combination of a subtle bug, and customers expectations regarding how the feature is supposed to work. It felt like a small firefight to me Рit was exciting and a little hairy at the same time.

But nothing on the scale of what’s happening at Apple tonight. Good luck Apple folk!

Intuit vs eBay Settlement

Today I received a $150 check from the settlement of this class action lawsuit: http://www.agtechemploymentsettlement.com/frequently-asked-questions.aspx.

As much as I am not a fan of class action lawsuits, two companies that colluded to not poach each others employees seems wrong, it doesn’t allow for people to move freely between companies based upon their skills and future challenges. 

This FAQ link is interesting: http://www.agtechemploymentsettlement.com/frequently-asked-questions.aspx#a6. Рtalking about the different settlements amounts, and the numbers of people in them. 

Halt And Catch Fire

I’ve really enjoyed¬†Halt And Catch Fire¬†over the past three years. Being part of the tech industry now for over 20 years, I’ve found myself really empathizing with these characters, and growing to love them.

The final season was great and heart wrenching at the same time. But the writers and actors did a fantastic job in my opinion. I shed more than one tear over the last 4 episodes.

If you haven’t seen the show, I highly recommend it. It’s a bit techie, but the show is really about relationships and people.

XOXO to Halt and Catch Fire.

Test Drove a Chevy Bolt EV today

A few days ago I got an email from Chevy regarding a new program they started in the past few weeks where one can sign up for a Chevy Bolt EV test drive. (It’s currently offered in San Francisco/San Jose, San Diego and Los Angeles)

But unlike a normal test drive, they drive the Bolt EV to the location you choose and you drive from there for about 30 minutes.

So I signed up for April 1 at 11am. I got an email confirmation, and when the driver was on his way I got a text with a link to a page that had a map showing the Bolt’s current location.


Sam arrived with the blue Bolt, and we hopped in, he showed me around a bit, and then I ended up driving to work and driving to my local grocery store, on the roads that I travel every day.

Sam wasn’t from a particular dealership in the area, but works for Chevrolet doing this only, what he calls a product specialist. So no hard sells, just a nice test drive on roads I drive every day.

Thoughts on the car

I was very impressed. The Bolt has some really good pickup, that great linear acceleration that people have talked about with electric cars. The technology was impressive too, two nice large screens, one for your speedo, etc, and one in the radio/nav area of the car.

Will I get one? I don’t know. I’m a little sad that it doesn’t have adaptive cruise control (my current Mazda has it). And it’s a good $14,000 more than my current car. But I would probably end up leasing it, as I have to think in 3 years the cost/technology in electric cars will have advanced quite a bit.

A few last pictures




Long after WKWebView Hello World – Part 1 – Cookie Handling

First of all, I want to thank my friend and colleague Lucien Dupont for inviting  me to contribute.

Recently our project transitioned web views written in UIWebView to WKWebView and Lucien suggested that I share some of my experiences with the larger community.  The intent here is not a tutorial on how to write web views using WKWebView, (there are tons of great, and free material out there) but suggest solutions on problems that we struggled with and hopefully help those with similar issues.

Before I begin, I am greatly indebted to the ton of postings in Stack Overflow and other web sites.  In particular please bookmark the following links whose authors really took the time to document the many tips they collected over the years:



Finally my discussions assumes iOS 9 and above, Xcode 8.2.1, Swift 3, basic WKWebView API

Cookie Handling

Adding Cookies

Quick take: Cookies are added using Javascript and only after the document is loaded

Adding cookies to a WKWebView from the app is different from UIWebView.  For UIWebView, one can take advantage of the APIs in HTTPCookieStorage as follow:

let cookieStorage = HTTPCookieStorage.shared
let cookieProperties: [AnyHashable: Any] =
[HTTPCookiePropertyKey.domain: "mydomain",
HTTPCookiePropertyKey.path: "/",
HTTPCookiePropertyKey.name: "mycookie",
HTTPCookiePropertyKey.value: ",abc"]
let cookie = HTTPCookie(properties: cookieProperties as! [HTTPCookiePropertyKey : Any])


Add a cookie to the HTTPCookieStorage and viola, the cookie is added.

WKWebView, cannot take advantage of HTTPCookieStorage APIs to add the cookie.  Instead one has to use javascript evaluation to add the same cookie

let webConfiguration = WKWebViewConfiguration() 
myWKWebView = WKWebView(frame: .zero, configuration: webConfiguration)

let addCookieScript = "document.cookie = \'mycookie=abc;domain=mydomain;path=/\';"


// Call this only after document is loaded
myWKWebView.evaluateJavaScript(addCookieScript,completionHandler: { (result, error) in
            if completionHandler != nil {
               completionHandler(result, error)

Additionally, the above javascript evaluation will not be successful until a document is loaded!

Sharing Cookies

Quick Take: Use the same WKProcessPool to share cookies with other WKWebView

Since WKWebView is not able to take advantage of HTTPCookieStorage, you would need to create a common WKProcessPool to be used by WKWebViews that need to share cookies

let commonProcessPool : WKProcessPool = WKProcessPool()

let configuration1 = WKWebViewConfiguration()
configuration1.processPool = commonProcessPool
let webView1 :WKWebView = WKWebView(frame: CGRectZero, configuration: configuration1)

let configuration2 = WKWebViewConfiguration()
configuration2.processPool = commonProcessPool
let webView2 :WKWebView = WKWebView(frame: CGRectZero, configuration: configuration2)

Instruct WKWebView to add cookies once document is loaded

Quick Take: A javascript to add cookie can be set when the WKWebView is first initialized and can be instructed to run when the document is loaded

WKWebView can be instructed to add cookies once the document load and before any other scripts and logic are processed within the document.  This is especially helpful when some of the scripts are looking for certain cookies.  We can do this using the WKUserScript class and specify the injectionTime to .atDocumentStart (and if for some reason you need the script to be run at the end, then use .atDocumentEnd)

let addCookieScript="var cookieNames = document.cookie.split(\'; \').map(function(cookie) { return cookie.split(\'=\')[0] } );\nif (cookieNames.indexOf(\'mycookie\') == -1) { document.cookie=\'mycookie=abc;domain=mydomain;path=/\'; };\n"

let script = WKUserScript(source: addCookieScript, injectionTime: .atDocumentStart, forMainFrameOnly: false)

let config = WKWebViewConfiguration()
config.processPool = processPool


webView = WKWebView(frame: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(50), height: CGFloat(50)), configuration: wkconf)

What about time sensitive cookie?

Quick Take:  Use a message handler to add time sensitive cookie

The above example works well if the value of your cookie stays the same.  Eg if the same web view is used to load another document which also needs the same cookies, then your work is done.  However, what if the value of the cookies changes eg if they are time sensitive, then using the above example could result in stale data.  Fortunately we can modify the example to callback to use a message handler to set the cookie with the latest value when the document loads

class MyWKWebViewController: NSObject, WKNavigationDelegate,  WKScriptMessageHandler {

override init() {
  // this script callback when the document load
  let script = WKUserScript(source: "window.webkit.messageHandlers.MyListener.postMessage(\"setCookiesForInitialLoad\");", injectionTime: .atDocumentStart, forMainFrameOnly: false)

  let config = WKWebViewConfiguration()
  config.processPool = processPool

// Note make sure the name of the message handler, in this case 'MyListener' is the same the one specified in the script
  config.userContentController.addUserScript(script)      conf.userContentController.add(self, name: "MyListener")

  webView = WKWebView(frame: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(50), height: CGFloat(50)), configuration: config)


// MARK: Message Handler methods
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {

  let messageValue = message.body as! String;
  switch (messageValue) {
     case "setCookiesForInitialLoad":
          self.webView.evaluateJavaScript(self.addTimeSensitiveCookieScript, completionHandler: nil)

func addTimeSensitiveCookieScript() -> String! {
   let newValue : String = self.getSomeTimeSensitiveValue()
   let addCookieScript="var cookieNames = document.cookie.split(\'; \').map(function(cookie) { return cookie.split(\'=\')[0] } );\nif (cookieNames.indexOf(\'mycookie\') == -1) { document.cookie=\'mycookie=\(newValue);domain=mydomain;path=/\'; };\n"

    return addCookieScript

Deleting Cookies

Cookies are not automatically deleted when the WKWebView is deleted, have to manually delete them

As with UIWebView, cookies are not deleted when they are deleted, in the case of WKWebView, once again, you are not able to delete cookies using HTTPCookieStorage APIs.  You can use the following (which will not only delete cookies but any cache data as well.  Note some cookies are needed for signing out etc, so do not delete cookies until they are used for the necessary clean up.

func deleteWebViewData(completion: @escaping () -> Void) {
  let dateFrom = NSDate(timeIntervalSince1970: 0)
  let websiteDataTypes = WKWebsiteDataStore.allWebsiteDataTypes()

  WKWebsiteDataStore.default().removeData(ofTypes: websiteDataTypes, modifiedSince: dateFrom as Date, completionHandler: {() -> Void in

That’s all for now, hopefully its enough to chew for the time being.

I would like to leave you with a link to a slide show that Mobify put together about their experience with WKWebView:

Test Driven Development in iOS with Swift

At Intuit we work in 2 week sprints. Last sprint I decided to take a story about a crash happening in an image downloader class. After looking at it for a bit, I decided it would be a great candidate to rewrite using dispatch groups, and also in Swift. (It’s an internal goal to rewrite when we can in Swift).

At first it was rough going and slow. The write a test, run it, and fail felt far slower than just writing the class from scratch, and then debugging it inside the app.

But – I really wanted to give it a try, so I changed my layout in Xcode. Instead of having the source in my left source panel in Xcode, I decided to put the unit test file there. And then on the right side I split that into two panels: the new Swift downloader source, and the old Objective C source.

That changed my focus from writing the source, to writing the tests, and then making the tests pass. I know it sounds like a small thing, but for me it really worked.

I also decided to embrace the “slowness” of TDD. It gave me more time to think about what I was writing and how to make sure it covered all the cases.

In short, something I feel I¬†could have finished in a few days¬†(with no tests) took me 5 days (along with meetings, production support, etc). But I got into it and really enjoyed it. I’d recommend you give it a try!