Stuart Breckenridge

Yahoo Confirms 2013 Data Breach Affected All Accounts

It turns out Yahoo’s 2013 data breach affected all accounts in existence at the time of the breach:

Subsequent to Yahoo’s acquisition by Verizon, and during integration, the company recently obtained new intelligence and now believes, following an investigation with the assistance of outside forensic experts, that all Yahoo user accounts were affected by the August 2013 theft.

This seemed to be inevitable.

Previously: Yahoo’s 2013 Data Breach Expanded to 2015 and 2016, Yahoo Confirms Security Breach of 1 Billion Accounts

Match Data in GameKit

Over the last few days I’ve started working with the GameKit API for the first time in a few years. It’s as bad as I remember.

The most egregious problem I have come across is this particular API:

GKTurnBasedMatch.loadMatches { (matches, error) in 
    if matches != nil {
	    // Do something with the matches

This is the API description:

Loads the turn-based matches involving the local player and creates a match object for each match.

And this is the description of the matches parameter:

An array of GKTurnBased Match objects containing the match objects for matches that the local player is playing in, or nil if there are no matches to load.

This is hardly the full story. The loadMatches API will indeed download matches from Game Center, but what this description lacks is any reference (at all) to the fact that the downloaded matches will very likely include stale or non-existent matchData.1

As I encode the match score within matchData, I ran into issues when Game Center was downloading out-of-date matchData. This necessitated in a second call to either of the following functions before displaying data to the user:

GKTurnBasedMatch.load(withID: match.matchID!, withCompletionHandler: { (match, error) in 
    // Logic


match.loadMatchData(completionHandler: { (data, error) in 
    // Logic

In my opinion, the loadMatches API should return the current matches the user is participating in with the latest matchData.

  1. I’ve created rdar://34782360 in the hope that Apple will clear up this description in a future update. ↩︎

Trump Waives Jones Act for Puerto Rico, Easing Hurricane Aid Shipments

Niraj Chokshi, for The New York Times:

The Trump administration said on Thursday that it would temporarily waive a century-old shipping law for Puerto Rico that officials there said was hindering disaster relief efforts after Hurricane Maria.

The law, known as the Jones Act, was limiting access to food, medicine, clothing and needed supplies, officials said. Sarah Huckabee Sanders, the White House press secretary, announced the waiver on Twitter, saying that President Trump had authorized it after a request from Gov. Ricardo A. Rosselló of Puerto Rico.

This comes after Trump sided with industry as a reason for not waiving the law:

President Trump says he’s reluctant to lift shipping restrictions to get more aid to hurricane-ravaged Puerto Rico — because mariners don’t want him to.

“We’re thinking about that,” Trump said Wednesday when asked about lifting the Jones Act, which prohibits foreign ships from moving goods between US ports.

“But we have a lot of shippers and a lot of people that work in the shipping industry that don’t want the Jones Act lifted, and we have a lot of ships out there right now.”

Industry. Shameful.

Implementing Drag and Drop with an NSManagedObject

Back in July I started adding the drag and drop API to The FFI List. At the time, I wrote:

What I want to do — and what I haven’t worked out yet — is dragging from the search table view on to the saved tab in order to save FFIs. It’ll take a bit more work, but I’m sure it’s doable.

It turns out this was easier than I thought: all I had to do was assign the NSManagedObject to the UIDragItem’s localObject variable (1), add a UIDropInteraction to the appropriate UITabBar subview (2), and make the UITabBarController conform to the UIDropInteractionDelegate protocol (3).

1 — Assign an NSManagedObject to the UIDragItem’s localObject variable:

let dragItem = UIDragItem(itemProvider: itemProvider)
dragItem.localObject = <#NSManagedObject#>

2 — Add a UIDropInteraction to the tab bar in viewDidLoad():

let dropInteraction = UIDropInteraction(delegate: self)

3 — Make the UITabBarController conform to the UIDropInteractionDelegate protocol:

func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool {
    return session.hasItemsConforming(toTypeIdentifiers: [kUTTypePlainText as String])
func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal {
    return UIDropProposal(operation: UIDropOperation.move)
func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) {
    let ffi = session.items[0].localObject as! <#NSManagedObject#>
    // Necessary logic to parse the NSManagedObject

You can see it working over on YouTube.

Ferrari's First Ever First-Lap Double Retirement

Jamie Strickland, via the BBC:

It’s taken 67 years, nearly 1,000 grands prix and 108 drivers, the likes of Ascari, Fangio, Hawthorn, Surtees, Lauda, Andretti, Villenueve, Prost, Mansell and Schumacher have come and gone, but Ferrari have finally suffered the ignominy of their drivers taking each other out on the opening lap of a race.

Now that has been a long time coming.

I was there, at turn 5, when it happened!

Going the wrong way, Seb.

Astonishment at the statistics aside, this is the first F1 incident that I’ve seen in person and I am glad that the drivers involved have not been hurt.