 	
 	func renderLabels(projection project: (Vertex) -> CGPoint) {
 		for label in poiLabels {
-			guard let marker = poiPrimitives.values.first(where: { $0.ownerHash == label.tag }) else { // $ hotspot
+			guard let marker = poiPrimitives.values.first(where: { $0.ownerHash == label.ownerHash }) else { // $ hotspot
 				continue
 			}
 			
 			// Layout labels (region labels hang under the center, POI labels hang from their top-left)
 			let screenPos = project(marker.worldPos)
 			switch marker.kind {
-			case .Region: label.center = screenPos
-			default: label.frame.origin = screenPos
+			case .Region: label.view.center = screenPos
+			default: label.view.frame.origin = screenPos
 			}
 		}
 	}
 	
-	func bindLabel(_ label: UILabel, to marker: LabelMarker) {
-		label.tag = marker.ownerHash
-		label.isHidden = false
+	func bindLabel(_ label: Label, to marker: LabelMarker) {
+		label.ownerHash = marker.ownerHash
+		label.view.isHidden = false
 		
 		let alignment: NSTextAlignment
 		let textColor: UIColor

	}
}

class LabelView: UIView {
	static let s_maxLabels = 20
	var poiPrimitives: [Int: LabelMarker] = [:]
	var poiLabels: [UILabel] = []
	
	override func awakeFromNib() {
		for _ in 0 ..< LabelView.s_maxLabels {
			let newLabel = UILabel()
			newLabel.tag = 0
			newLabel.isHidden = true
			newLabel.frame = CGRect(x: 0.0, y: 0.0, width: 200.0, height: 30.0)
			newLabel.preferredMaxLayoutWidth = 200.0
			newLabel.lineBreakMode = .byWordWrapping
			newLabel.numberOfLines = 2
			newLabel.adjustsFontSizeToFitWidth = true
			
			poiLabels.append(newLabel)
			addSubview(newLabel)
		}
	}
	

		let markersToShow = prioritizedMarkers.prefix(LabelView.s_maxLabels)
		let hashesToShow = markersToShow.map { $0.ownerHash }
		
		// First free up any labels that no longer have active markers
		_ = poiLabels
			.filter({ $0.ownerHash != 0 && !hashesToShow.contains($0.ownerHash) })
			.map(unbindLabel)
		
		// Bind new markers into free labels
		for marker in markersToShow {
			guard poiLabels.first(where: { $0.ownerHash == marker.ownerHash }) == nil else {
				continue
			}
			guard let freeLabel = poiLabels.first(where: { $0.ownerHash == 0 }) else {
				print("Marker \(marker.ownerHash) could not be bound to a free label")
				continue
			}
