In Evergreen I’m using
WKWebView instead of
WebView, because it’s the new and improved WebKit view. NSHipster writes:
Sounds great! I’m on board.
One of the best parts about it — easily enough to sell me — is that a crash in
WKWebView won’t crash my app.
(Back when I was doing NetNewsWire, crashes in the old
WebView — the predecessor to
WKWebView — were the most common crash. But, to be fair, many if not most of those were actually Flash crashes.)
I’ve also heard, though I’m not sure how to verify, that
WKWebView is better for accessibility, too. So it’s a win all around.
But it’s not a win all around
WebView — good ’ol trusty friend — has a bunch of things that
WKWebView is missing.
The new web view has no built-in support for finding text, for instance. I’m not sure what I’m going to do about this, since the ability to hit cmd-F and look for some text is a pretty fundamental thing, and I can’t skip it.
It also has no delegate method for when you mouse over a link. Seems like another fundamental thing, right? Any browser offers you a status bar or some way to see the URL of the link your mouse is over.
renderedHTML() method.) Then I added handlers in DetailViewController: see
viewDidLoad and the
This worked fine: now my status bar shows the URL of the link your mouse is over. Cool.
Then the issue of scrolling came up
Evergreen’s design includes a key feature: you can go through all of your news just by hitting the space bar repeatedly.
If there’s more to scroll in the web view (the article), it scrolls. If not, then it goes to the next unread article.
This is a coffee-in-hand feature, which is critical for a news reader.
WKWebView provides no access to its scroll view. (It does on iOS, yes, but not on Macs.)
The logic goes like this:
if canScrollDown() scrollDown() else goToNextUnread()
There are two parts to this, and both (I thought) required access to the scroll view.
I did this an DetailViewController, in the
(Unfortunately, this is asynchronous. I expect it to be super-fast, but I won’t know if this is a problem without a bunch of testing. Let’s set that issue aside.)
fetchScrollInfo method creates a
ScrollInfo struct (at the bottom of
DetailViewController) that has
So that’s how I know if the web view can scroll. Part one of two solved.
(I write Mac apps. “Noticeably different” is the kiss of death.)
So I did some nerd-sniping, on Twitter and Slack, to see if anybody had a suggestion that would work.
People had ideas. Nothing worked.
So I’m frustrated, and I’m just about to switch back to my old friendly friend
WebView, because I know it will do what I want.
The voice of another old friend — the guy who mentored me in my early days as a programmer — came into my head, as it often does in these situations.
“What is the real problem you’re trying to solve?” asks Dave Winer, in my head.
The real problem is not arbitrary animated scrolling. The real problem is that I want to do a page-down exactly the same way it would work if the
WKWebView had focus and you hit the space bar. Exactly the same animation and scroll distance.
But not arbitrary scrolling: just a page-down.
So I think maybe I can spy on the event stream; maybe I can figure it out by seeing what happens when I click in the web view and hit the space bar. Maybe I can post an event that will do the job.
To do so I make an
NSApplication subclass, which I do (in Swift, of course), and break on
But of course this doesn’t work. The app crashes immediately saying it can’t find the
EvergreenApplication class. (Which is right there! Dude!)
Okay, maybe it’s back to
WebView after all. Forget
Then I do a search in Xcode on
pagedown, just out of a last gasp of trying — and, forgotten long ago by me, but look: there is a
scrollPageDown method in
NSResponder — and
WKWebView is an
NSView subclass which is an
NSResponder subclass — so, could it be? maybe? it might work?
I tried it: sure enough! It works! With animation and everything. It’s perfect.
* * *
So, in the end, the action method is in MainWindowController — see
(It’s a little weird due to the async thing I mentioned earlier. But it does the job.)
And now — after three years of working on this app — I was finally able to go through all my news just by hitting the space bar. Big day for me.