 	var readerWindow: NSWindow?
 	var viewController: ViewController?
 	
+	var managerObservation: NSKeyValueObservation?
+	var slotObservation: NSKeyValueObservation?
+	
 	func applicationDidFinishLaunching(_ aNotification: Notification) {
 		let windowController = createCardWindow()
 		windowController.showWindow(self)
 		readerWindow = windowController.window
 		viewController = (readerWindow?.contentViewController as! ViewController)
 		
-		addObserver(self, forKeyPath: #keyPath(slotManager.slotNames), options: [.new, .initial], context: nil)
-	}
-	
+		managerObservation = slotManager?.observe(\.slotNames, options: .initial, changeHandler: updateCardSlots)
+	}
+
 	@IBAction open func saveDocument(_ sender: Any?) {
 		createDocumentFromCurrentCard().runModalSavePanel(for: .saveOperation, delegate: self, didSave: #selector(discardDocumentUnless), contextInfo: nil)
 	}
-	
+
 	func application(_ sender: NSApplication, openFile filename: String) -> Bool {
 		let url = URL(fileURLWithPath: filename)
 		Swift.print("is file:", url.isFileURL, url)

		}
		slotManager?.getSlot(withName: slot) {
			self.currentSlot = $0
			self.addObserver(self, forKeyPath: #keyPath(currentSlot.state), options: [.new, .initial], context: nil)
		}
	}

	func applicationWillTerminate(_ aNotification: Notification) {
		removeObserver(self, forKeyPath: #keyPath(slotManager.slotNames), context: nil)
	}

	func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
		return true
	}
}

extension Data {
	func hexEncodedString() -> String {
		return map { String(format: "%02hhx", $0) }.joined()
	}
}

		}
	}
	
	func updateCardSlots(manager: TKSmartCardSlotManager, change: NSKeyValueObservedChange<[String]>) {
		if let firstSlot = manager.slotNames.first {
			observe(slot: firstSlot)
		} else {
			clearCard()
			DispatchQueue.main.async {
				self.readerWindow?.title = "No card reader detected"
			}
		}
	}
	
	func observe(slot: String) {
		DispatchQueue.main.async {
			self.readerWindow?.title = slot
