Search Archive Tags About RSS
  • August 16, 2023
    Presidential Hopefuls: 2024 Edition
    Tl;dr: I built a thing. Download it.

    Presidential Hopefuls logo

    Tl;dr: I built a thing. Download it.

    Next week is the first debate in this season of presidential hopefuls. The frontrunner has been indicted under dozens of counts in multiple jurisdictions. We could see multiple trials and maybe even multiple convictions between now and November 2024. We certainly will see many primaries, debates, gaffes, and scandals.

    Which seems like the perfect time to launch the reboot of the successful 2020 era Presidential Hopefuls screensaver (for Mac!)!

    It is a hopeless task to keep up with all the news of this race. It is even more hopeless to try to keep track of the various polls: who’s in the lead? Who’s moving up or down the ladder in the psyches of potential American voters? What wild combination of candidates will polling firms pose to us next?

    Presidential Hopefuls solves all these problems and more. By using data sourced from our friends over at FiveThirtyEight, we are able to provide a unique visualization of how these men (and women!) are doing against each other. We cycle through each set of polling data, and then we size and rank each candidate according to how they did in that poll. We utilize polling quality data from FiveThirtyEight to inform how long a poll will be up on your screen.

    We display each candidate as a disembodied head to remind you of the farce and absurdity of it all. The classic DVD logo screensaver of yore inspires our candidates to bounce around the screen, for what could be better than one bouncing head than several? Larger heads can plow through the smaller ones, just like they will inevitably also do on the debate stage and in the press. Occasionally, there is a bout of frenetic energy as heads try to escape other heads. This beautiful feature allows you to visualize what it might be like to run your own race to be President of the United States of America.

    We the people of the USA come together every four years to elect our President. (Well, I guess we elect electors who elect our President, but that’s for another day.) I hope this screensaver may provide you some levity during the brutal process we are all to endure over the next 15 months or so.

    For screensavers matter now, more than ever.

    Tysm.

    Please to download.

    • Robert Tolar Haining
  • August 29, 2020
    2010: The days before the iPad
    On professional accomplishments and personal loss

    January 27, 2010 Steve Jobs announced to the world a new product: the iPad. I had been the lead developer for a burgeoning motley crew of software developers learning on the job how to create iPhone apps at the storied magazine powerhouse Condé Nast. Our biggest success by far had been Epicurious, which allowed folks to find recipes on the go, build shopping lists, and then cook those recipes at home (RIP printers). We had also published GQ Magazine on the iPhone, the first of its kind, with both a digital native interface to make reading easier on a small phone, but also the full-fledged PDF rendering of the glossy print version. This was a far cry from my previous work at Condé: building Facebook and MySpace apps (lol, remember those?) for a small team that didn’t survive the 2008 round of layoffs at the company. I had learned a new language (Objective-C, the original programming language for iPhone apps) and had emerged from working on a new type of product as the sole engineer to leading development on a few apps with a bigger team.

    Steve Jobs with the Apple iPad Steve Jobs launching the iPad, 📷 Jacqui Cheng

    With the announcement of the iPad, we immediately shifted focus and thought about what Condé Nast might mean on this new tablet device. Was it a large iPhone? A small laptop? Something else entirely? Our initial inclination was that it would be perfect for magazines. Readers would love getting GQ on their iPad. Right?! For me, it was both a creative opportunity to help rethink these apps and deliver them to a larger audience, but also professionally I would help lead a team of several engineers working with designers, product managers, editorial, and publishing, all working within one of the shortest deadlines we had seen.

    January 30, 2010 (three days after the iPad announcement) Early on a Saturday morning, I received a phone call from my good friend Jay. It was maybe 8am, I ignored the call and went back to sleep. But I somehow already knew what had happened. Jay lived in Seattle at the time, so it was close to 5am there. I woke up a bit later and returned his call. That was when I found out that one of my best friends Trey had died in a car accident in the wee hours of the morning. Jolted from my anticipated lazy Saturday after a rollercoaster ride of a work week, I curled up into a little ball on my couch and barely moved until I had to go to work the following Monday morning. I watched countless hours of Doctor Who (one of Trey’s favorite shows, which he had introduced me to), drank a fair amount of whiskey, and cried and cried and cried.

    Trey and me Trey and me

    I flew down to Atlanta to meet up with some friends to drive to Little Rock for the funeral, while the team at Condé Nast continued work on the iPad apps. I had been nervous to tell my boss I would need to leave town, but she was immediately understanding and helped cover me while I was out. Back in Atlanta, I met up at my friend’s house to have breakfast and caravan to Little Rock, but one friend did not have time to eat, so we made her a bacon, egg, & cheese sandwich. We put it in the car with the rest of everyone’s stuff, but the sandwich was never to be seen again. My friends and I are all still convinced that the ghost of Trey made off with that bacon, egg, & cheese sandwich. He would have loved it.

    Later that day, we had been driving for a bit down I-20 towards Little Rock, and we were traveling through Alabama, when we realized that we were certainly going to be late for the “viewing” that evening. Suddenly, we all collectively realized that Little Rock is indeed not in the Eastern time zone and is an hour behind Atlanta. We had plenty of time to get checked in, change into our “Sunday best”, and drive over to the funeral home.

    We spent a few days in Little Rock, bonding with his family and his college friends, most of whom we had not met before. With the viewing over, the funeral complete, some late night memorializing at his Aunt’s house, and some even later night dancing out at Little Rock’s finest warehouse clubs, we drove back to Atlanta. I arrived back at my parents’ house in time to see the end of the Super Bowl, before flying back to New York City the next day.

    Back at home, I was a little disoriented in my life, still processing the loss of a good friend. I doubled down and focused 110% on work to help fill my time. I was working with some of the best people around, and personally I was happy to spend late nights and long weeks engrossed in building iPad apps.

    I was happy to have a distraction when our Developer Relations Manager from Apple, let’s call him Ralph, came to pay us a visit. We collaborated with Ralph on how Condé could adapt to this new tablet interface. After telling him our plans to focus on publishing GQ on the iPad, he had one response: “Steve really likes Epicurious.” A few beats of silence passed as it sunk in that the man who only needs one name (in this context at least) had offered us guidance. The man behind the company who had revolutionized mobile phones and who unwittingly had radically pivoted my career to building iPhone apps.

    Based on our history of building dope iPhone apps at Condé, Apple offered to loan us a few iPads before they were released to the public, so we could get a real feel for them and build the best products we could build. Codenamed “K48”, the iPads were locked to a table in a room at the Condé Nast Digital offices (then located a few blocks from the company headquarters at 4 Times Square). The room’s windows were covered up with craft paper, so no one could peer in from any nearby skyscrapers, and the room had a coded lock on the door, to which only a small group of trusted engineers, designers, and product managers could access.

    The caveat was that we had to have the apps ready to go before the iPad’s release date of April 3. We worked hard. Harder than we had ever worked. With the unexpected passing of my dear friend, I was happy to fill up my days and nights and weekends with work that was interesting, novel, and that people would end up appreciating. It also helped the team that we had carte blanche from the president of Condé Nast Digital to order food and take cars home when we were there late (a true rarity on the digital side, regardless of what you may have heard about the extravagance at publications like Vogue or Gourmet).

    We somehow managed to develop and ship iPad apps for both GQ Magazine and Epicurious, both of which were total rethinks of how people would interact with these products on the larger screen. We were there with Apple at launch when the first iPads were released. The first certified magazine on a tablet and one of the best recipe apps.

    Steve Jobs promoting the Epicurious iPad app Steve Jobs promoting the Epicurious iPad app

    I will always remember my friend Trey. How great a friend he was. How he could light up the room and convince everyone to dance. Weird as it may be, the iPad launch helped get me through a rough patch. The iPad has gone on to be a revolutionary product, while the memory of Trey lives on in his friends and family. The two will forever be intertwined for me. I’ll never forget the great pain that time held, nor will I forget the great excitement.

    Thanks to Jacqui Cheng giving me early feedback on this post.

  • April 13, 2020
    Let a million screensavers bloom
    Writing screensavers in Swift for fun and … profit?

    This is nominally a “travel blog”, or something, but I also write code, and sometimes screensavers, so I thought I’d try putting this out there to see how it goes. Let me know what you think! mail@tolar.town or on twitter @tolar.

    Writing screensavers for macs is a little weird. But once you get past a few oddities, it can be lots of fun!

    For purposes of this post, I assume you have some knowledge of and experience with Xcode and Swift. We’ll build a simple screensaver that spins a green square.

    If you want to go ahead and download the complete source, you can find it on GitHub.

    Setup your project

    Let’s start with your Xcode project setup before we dive in to code: File -> New project. In the project template selection screen, select macOS -> Screen Saver.

    Project selection Project selection

    Continue with setup until you have a project. Xcode will generate an Objective-c subclass of ScreenSaverView for you, but that’s no fun. Swift is the new hot thing, right? Go ahead and delete those files (***View.h and ***View.m). Create a new Swift file. Here we call it GreenSquareScreenSaverView, but you can name it as you please. (Note: if you change the name of the class, be sure to also update it in your Info.plist “Principal class” key.) You can use this stub code:

    import Foundation
    import ScreenSaver
    
    class GreenSquareScreenSaverView: ScreenSaverView {
        override init?(frame: CGRect, isPreview: Bool) {
            super.init(frame: frame, isPreview: isPreview)
            self.animationTimeInterval = 1 / 30.0
        }
        
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        override func startAnimation() {
            super.startAnimation()
        }
        
        override func stopAnimation() {
            super.stopAnimation()
        }
        
        override func draw(_ rect: NSRect) {
            super.draw(rect)
        }
        
        override func animateOneFrame() {
        }    
    }
    

    Congrats, you have a functional screensaver! It might not do much apart from showing a blank screen, but it’ll build.

    Install your screensaver

    One major difference between screensavers and apps is that you can’t simply “Run” from Xcode. To install the screensaver:

    1. Build from Xcode.
    2. Find the screensaver file under “Products”.
    3. Right-click on it & select “Open with External Editor.”
    4. This will open System Preferences and install the screensaver. (The first time, you’ll have to select the screensaver here).

    Install the screensaver Install the screensaver

    Add a mac app target to make testing easier

    Troubleshooting screensavers is a pain in the butt. I highly recommend doing the bulk of your development using a mac app target. Then make sure to test it in screensaver mode, as this is treated a bit differently by macOS.

    First, add a new target:

    1. Select your project on the left.
    2. Under “Targets”, at the bottom select the “+” button.
    3. Under “macOS”, select “App”.
    4. Continue with the prompts. I suggest naming it something like “Preview”.

    Setup the Mac target

    Hook up your mac app to the screensaver code you have. We need to expose the screensaver view class (and any other code you have written or will write):

    1. Select the file(s) on the left.
    2. On the right, select the File Inspector icon
    3. Under “Target Membership”, make sure your screensaver & mac app are selected.

    Fix target membership Fix target membership

    You’ll need to fake the animation in the mac app. Here is some stub code for a view controller (this should only have the mac app as a target):

    import AppKit
    
    class PreviewViewController: NSViewController {
        var screensaverView: GreenSquareScreenSaverView? = nil
        
        var timer: Timer? = nil
        
        var isAnimating: Bool = false {
            didSet {
                toggleAnimationTimer()
            }
        }
        
        override func loadView() {
            screensaverView = GreenSquareScreenSaverView(frame: CGRect.zero, isPreview: true)
            self.view = screensaverView ?? NSView()
        }
        
        override func viewDidAppear() {
            super.viewDidAppear()
            
            isAnimating = true
        }
        
        override func viewWillDisappear() {
            super.viewWillDisappear()
            
            isAnimating = false
        }
        
        private func toggleAnimationTimer() {
            if isAnimating {
                if timer == nil {
                    timer = Timer.scheduledTimer(withTimeInterval: 1/30.0, repeats: true) { [weak self] (_) in
                        self?.animate()
                    }
                }
            } else {
                if let timer = timer {
                    timer.invalidate()
                    self.timer = nil
                }
            }
        }
        
        func animate() {
            if isAnimating, let screensaverView = screensaverView {
                screensaverView.animateOneFrame()
            }
        }
    }
    

    Then in your AppDelegate, you can instantiate your PreviewViewController and pass it to the window:

    import Cocoa
    
    @NSApplicationMain
    class AppDelegate: NSObject, NSApplicationDelegate {
    
        var window: NSWindow!
        var previewViewController: PreviewViewController?
    
        func applicationDidFinishLaunching(_ aNotification: Notification) {
            let previewViewController = PreviewViewController()
            self.previewViewController = previewViewController
    
            // Create the window and set the content view. 
            window = NSWindow(
                contentRect: NSRect(x: 0, y: 0, width: 800, height: 600),
                styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
                backing: .buffered, defer: false)
            window.center()
            window.setFrameAutosaveName("Main Window")
            window.contentView = previewViewController.view
            window.makeKeyAndOrderFront(nil)
        }
    }
    

    Now if you build & run the Preview mac app, you’ll have your screensaver running inside the app, and tied to Xcode for debugging, stepping through code, troubleshooting, etc.

    You should see a single window with a black background color.

    Write code!

    If you want to eventually port your code to iOS or tvOS, you may want to stick with something like layers (CALayer) that are easy to use cross-platform. But if you’re focused on screensavers, AppKit is the mac corollary of UIKit, which you might be familiar with if you’ve built iOS apps. NSView and NSViewController are your friends!

    For now, let’s add a little green square and rotate it, so you don’t have to stare at a blank screensaver. Create a new Swift file GreenSquareView:

    class GreenSquareView: NSView {
        init() {
            super.init(frame: .zero)
            wantsLayer = true
            layer?.backgroundColor = NSColor.green.cgColor
        }
        
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }    
    }
    

    Let’s update a few things in your ScreenSaverView subclass. Create a property:

    let greenSquareView = GreenSquareView()
    

    Then, in the init(), add:

    addSubview(greenSquareView)
    

    We’ll resize the frame in draw():

        override func draw(_ rect: NSRect) {
            super.draw(rect)
            
            var squareFrame = NSRect.zero
            squareFrame.size = NSSize(width: 150, height: 150)
            squareFrame.origin.x = (rect.width - squareFrame.width) / 2.0
            squareFrame.origin.y = (rect.height - squareFrame.height) / 2.0
            greenSquareView.frame = squareFrame
        }
    

    And we can animate it in the stub animateOneFrame():

        override func animateOneFrame() {
            greenSquareView.rotate(byDegrees: 1)
        }
    

    So if we put that together, our GreenSquareScreenSaverView now looks like:

    import Foundation
    import ScreenSaver
    
    class GreenSquareScreenSaverView: ScreenSaverView {
        let greenSquareView = GreenSquareView()
        
        override init?(frame: CGRect, isPreview: Bool) {
            super.init(frame: frame, isPreview: isPreview)
            self.animationTimeInterval = 1 / 30.0
            addSubview(greenSquareView)
        }
        
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        override func startAnimation() {
            super.startAnimation()
        }
        
        override func stopAnimation() {
            super.stopAnimation()
        }
        
        override func draw(_ rect: NSRect) {
            super.draw(rect)
            
            var squareFrame = NSRect.zero
            squareFrame.size = NSSize(width: 150, height: 150)
            squareFrame.origin.x = (rect.width - squareFrame.width) / 2.0
            squareFrame.origin.y = (rect.height - squareFrame.height) / 2.0
            greenSquareView.frame = squareFrame
        }
        
        override func animateOneFrame() {
            greenSquareView.rotate(byDegrees: 1)
        }
    }
    

    Animation

    The ScreenSaverView class offers you a straightforward way to animate, if what you want to do involves regular updates, like a rotating green square. But that should not restrict you from doing your own CoreAnimation or NSAnimation.

    Swift classes: beware, beware, be aware

    There’s a fun little bug where sometimes when you create a Swift class, macOS will try to instantiate it as a ScreenSaverView. Your screensaver will quietly crash, but you’ll see a black screen. You can dive into the Console.app, where you might find that it’s trying to call: -[GreenSquare.GreenSquareView initWithFrame:isPreview:]: unrecognized selector sent to instance 0x7fd13af16950

    Fortunately, there’s an easy fix!

    Back in Xcode, select your project on the left, then your screensaver target, then “Build Phases”. Under “Compile Sources”, ensure that your ScreenSaverView subclass is the first Swift file.

    Fix Build Phases Fix Build Phases

    Code!

    The code mentioned here is over on github.com/rhaining/screensaver-demo.

    App preview App preview

    What else?

    What else do you want to learn? Hit me up: mail@tolar.town or on twitter @tolar.

    Other screensavers

    I’ve published a couple of screensavers this year, if you want to check them out.

    • Presidential Hopefuls visualizes polling data in a fun, weird way.
    • Zooooom is a parody of a zoom call that I built with my friend Harper. You can check out the source code at github.com/rhaining/zooooom-screensaver.

    Check them out and let me know what you think!

  • April 13, 2020
    The New York Easter Parade lives on!
    Well, via Zoom at least

    Every Easter Sunday on 5th Avenue in Midtown Manhattan, outside St Patrick’s Cathedral, there is an Easter Parade. It’s bananas. You see everything from traditional Easter bonnets to outlandish performance art projects to political statements.

    This being a pandemic year, they couldn’t have the traditional gathering, so one group put together a Zoom call, complete with multiple rooms, dance parties with various styles of music, and a promenade, where folks could virtually “raise their hand” to show off their outfits. Here are some I took pictures of. Check them out!

    The Zoom Easter parade was also a fundraiser for Stonewall Village NYC. Support them by donating on their site.

    Easter parade promenade

    Easter parade promenade

    Easter parade promenade

    Easter parade promenade

    Easter parade promenade

    Easter parade promenade

    Easter parade promenade

    I took some pictures at the 2017 parade – if you want to see the real deal, check them at at Flickr.

  • April 13, 2020
    Life in New York under PAUSE
    4 weeks of lockdown, and counting…

    It has been 4 weeks since Governor Andrew Cuomo shut down non-essential businesses in New York. He would later expand it to the New York PAUSE, similar to many other governmental policies called lockdown, shelter-in-place, and the like. The new normal has become wearing masks & gloves during the rare times I leave my apartment: to Foodtown, BQE Liquor & Wines, Meathook, or for a walk around the neighborhood, trying my best to avoid the swarms of people in parks or huddled around the newly minted takeout windows at bars & pizzerias.

    I have been cooking and baking a lot! A few items I’ve been especially happy about: roast chicken, ribs, oatmeal creme pies, roast pork, New Mexican style pork (“carne adovada”), dill shrimp orzo salad, brisket, burrito pie, nachos. I also started experimenting with breads: no-knead loaves, white bread, english muffins, flour tortillas.

    I’ve also loved the video calls that have popped up in place of happy hours, brunches, virtual dinners, Easter parades, dance parties.

    I bought a full-sized digital piano with weighted keys, which I’ve been enjoying relearning, and which provides a nice break from the monotony of lockdown. And I started playing Animal Crossing on Switch, which is pretty fun.

    Foodtown Foodtown, the Friday before the lockdown began. It took 45 minutes just to check out. During normal times, there’s at most 1-2 people ahead of me in the checkout line.

    Home At home: the weird final Democratic primary debate, where Bernie & Joe social distanced; me wearing my first mask; and my new piano.

    Food Food! Bread, ribs & green beans, Ritz chicken & brussels, burrito pie, brisket nachos, oatmeal creme pies, white loaf, brisket tacos, english muffins.

    Video calls A lot more video calls these days! Family chat, virtual dinners, remote stretch, tfw dance party, karaoke crew sans any real karaoke.

    Neighborhood store signs Neighborhood store signs: Pharmacy, Allswell, Egg, Brooklinen, Van Leeuwen, Muji, Two Boots, Fellow Barber, Teddy’s, Junk, Egg, Hive.

    Out and about Out and about: city warnings, street art warnings, dance party, cops observing the park attendees, USPS social distancing, street art inspiration, Spring, Ghostbeard, Billy Barnacles, Meathook social distancing, playground closed, park social distancing, and friends’ social distancing.

  • January 27, 2020
    New Orleans: Architecture in the French Quarter
    Gorgeous buildings

    French Quarter: Royal Street French Quarter: Royal Street

    French Quarter: Royal Street French Quarter: Royal Street

    French Quarter: Royal Street French Quarter: Royal Street

    French Quarter: Chartres Street French Quarter: Chartres Street

    French Quarter: Decatur Street French Quarter: Decatur Street

  • January 27, 2020
    New Orleans!
    Lots of fun, food, drinks, and music

    Over MLK weekend, I went to New Orleans with some friends. It was my first visit there, but we jam-packed the weekend with lots of good food, drinks, catching up, walking around, listening to music. Oh yeah, and holding alligators in a swamp boat.

    I split up the pictures across a few posts. Check them out:

    • Architecture in the French Quarter
    • Walking the streets
    • Music
    • Food
    • Bars
    • Swamp tour
    • Shopping
    • A few random things
  • January 27, 2020
    New Orleans: walking the streets
    A few random shots

    Clint & Tolar Clint & Tolar

    Reverend Zombie’s House of Voodoo: Come on in and shop for a spell

    $$ $$

    Mardi Gras bros We encountered many bros

  • January 27, 2020
    New Orleans: the music
    Omg, y'all
  • January 27, 2020
    New Orleans: food
    Antoine's, Country Club, Cafe du Monde, Killer Poboys, Willa Jean

    Y’all, the food.

    Willa Jean: biscuit sandwich Willa Jean: a biscuit with egg, sausage, & pimiento cheese

    Willa Jean: shrimp & grits Willa Jean: shrimp & grits, with etoufee gravy

    Country Club: the crew Country Club: the crew

    Country Club: a drink Country Club: a drink (along with blurry Jacqui & Clint)

    Country Club: wall flowers Country Club: wall flowers

    Country Club: tacos Country Club: tacos

    Killer Poboys: ham & pimiento cheese Killer Poboys: ham & pimiento cheese

    Cafe du Monde: beignets & coffee Cafe du Monde: beignets & coffee

    Cafe du Monde: staff Cafe du Monde: staff

    Antoine’s: place setting Antoine’s: place setting

    Antoine’s: gumbo Antoine’s: gumbo

    Antoine’s: steak Antoine’s: steak with soft-shelled crab and lump crab meat, and asparagus

    Antoine’s: baked alaska Antoine’s: baked alaska

    Antoine’s: baked alaska slice Antoine’s: baked alaska slice

    Antoine’s: two Tolars Antoine’s: Tolar, Peter, Adam, Jacqui, Tolar (📷 Clint)

Older Posts →

© Copyright 2023 Robert Tolar Haining

Powered by Hugo. Theme adapted from nodejh. Hosted by GitHub Pages.