     }
   }
 
-  /// Gets multiple attributes of the element at once.
-  ///
-  /// - parameter attributes: An array of attribute names. Nonexistent attributes are ignored.
-  ///
-  /// - returns: A dictionary mapping provided parameter names to their values. Parameters which
-  ///            don't exist or have no value will be absent.
-  ///
-  /// - throws: If there are any errors other than .NoValue or .AttributeUnsupported, it will throw
-  ///           the first one it encounters.
-  ///
-  /// - note: Presumably you would use this API for performance, though it's not explicitly
-  ///         documented by Apple that there is actually a difference.
-  public func getMultipleAttributes(names: Attribute...) throws -> [Attribute: Any] {
-    return try getMultipleAttributes(names)
-  }
-
-  public func getMultipleAttributes(attributes: [Attribute]) throws -> [Attribute: Any] {
-    let values = try fetchMultiAttrValues(attributes.map({ $0.rawValue }))
-    return try packMultiAttrValues(attributes, values: values)
-  }
-
-  public func getMultipleAttributes(attributes: [String]) throws -> [String: Any] {
-    let values = try fetchMultiAttrValues(attributes)
-    return try packMultiAttrValues(attributes, values: values)
-  }
-
-  // Helper: Gets list of values
-  private func fetchMultiAttrValues(attributes: [String]) throws -> [AnyObject] {
-    var valuesCF: CFArray?
-    let error = AXUIElementCopyMultipleAttributeValues(
-      element,
-      attributes,
-      AXCopyMultipleAttributeOptions(rawValue: 0),  // keep going on errors (particularly NoValue)
-      &valuesCF)
-
-    guard error == .Success else {
-      throw error
-    }
-
-    return valuesCF! as [AnyObject]
-  }
-
-  // Helper: Packs names, values into dictionary
-  private func packMultiAttrValues<Attr>(attributes: [Attr], values: [AnyObject]) throws -> [Attr: Any] {
-    var result = [Attr: Any]()
-    for (index, attribute) in attributes.enumerate() {
-      if try checkMultiAttrValue(values[index]) {
-        result[attribute] = unpackAXValue(values[index])
-      }
-    }
-    return result
-  }
-
-  // Helper: Checks if value is present and not an error (throws on nontrivial errors).
-  private func checkMultiAttrValue(value: AnyObject) throws -> Bool {
-    // Check for null
-    if value is NSNull {
-      return false
-    }
-
-    // Check for error
-    if CFGetTypeID(value) == AXValueGetTypeID() &&
-       AXValueGetType(value as! AXValue).rawValue == kAXValueAXErrorType {
-      var error: AXError = AXError.Success;
-      AXValueGetValue(value as! AXValue, AXValueType(rawValue: kAXValueAXErrorType)!, &error)
-
-      assert(error != .Success)
-      if error == .NoValue || error == .AttributeUnsupported {
-        return false
-      } else {
-        throw error
-      }
-    }
-
-    return true
-  }
-
-  // MARK: Array attributes
-
-  /// Returns a subset of values from an array attribute.
-  ///
-  /// - parameter attribute: The name of the array attribute.
-  /// - parameter startAtIndex: The index of the array to start taking values from.
-  /// - parameter maxValues: The maximum number of values you want.
-  ///
-  /// - returns: An array of up to `maxValues` values starting at `startAtIndex`.
-  ///   - The array is empty if `startAtIndex` is out of range.
-  ///   - `nil` if the attribute doesn't exist or has no value.
-  ///
-  /// - throws: `Error.IllegalArgument` if the attribute isn't an array.
-  public func valuesForAttribute<T: AnyObject>
-      (attribute: Attribute, startAtIndex index: Int, maxValues: Int) throws -> [T]? {
-    return try valuesForAttribute(attribute.rawValue, startAtIndex: index, maxValues: maxValues)
-  }
-
-  public func valuesForAttribute<T: AnyObject>
-      (attribute: String, startAtIndex index: Int, maxValues: Int) throws -> [T]? {
-    var values: CFArray?
-    let error = AXUIElementCopyAttributeValues(element, attribute, index, maxValues, &values)
-
-    if error == .NoValue || error == .AttributeUnsupported {
-      return nil
-    }
-
-    guard error == .Success else {
-      throw error
-    }
-
-    return (values! as [AnyObject] as! [T])
-  }
-
-  /// Returns the number of values an array attribute has.
-  /// - returns: The number of values, or `nil` if `attribute` isn't an array (or doesn't exist).
-  public func valueCountForAttribute(attribute: Attribute) throws -> Int? {
-    return try valueCountForAttribute(attribute.rawValue)
-  }
-
-  public func valueCountForAttribute(attribute: String) throws -> Int? {
-    var count: Int = 0
-    let error = AXUIElementGetAttributeValueCount(element, attribute, &count)
-
-    if error == .AttributeUnsupported || error == .IllegalArgument {
-      return nil
-    }
-
-    guard error == .Success else {
-      throw error
-    }
-
-    return count
-  }
-
-  // MARK: Parameterized attributes
-
-  /// Returns a list of all parameterized attributes of the element.
-  ///
-  /// Parameterized attributes are attributes that require parameters to retrieve. For example,
-  /// the cell contents of a spreadsheet might require the row and column of the cell you want.
-  public func parameterizedAttributes() throws -> [Attribute] {
-    return try parameterizedAttributesAsStrings().flatMap({ Attribute(rawValue: $0) })
-  }
-
-  public func parameterizedAttributesAsStrings() throws -> [String] {
-    var names: CFArray?
-    let error = AXUIElementCopyParameterizedAttributeNames(element, &names)
-
-    if error == .NoValue || error == .AttributeUnsupported {
-      return []
-    }
-
-    guard error == .Success else {
-      throw error
-    }
-
-    // We must first convert the CFArray to a native array, then downcast to an array of strings.
-    return names! as [AnyObject] as! [String]
-  }
-
-  /// Returns the value of the parameterized attribute `attribute` with parameter `param`.
-  ///
-  /// The expected type of `param` depends on the attribute. See the
-  /// [NSAccessibility Informal Protocol Reference](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Protocols/NSAccessibility_Protocol/)
-  /// for more info.
-  public func parameterizedAttribute<T, U>(attribute: Attribute, param: U) throws -> T? {
-    return try parameterizedAttribute(attribute.rawValue, param: param)
-  }
-
-  public func parameterizedAttribute<T, U>(attribute: String, param: U) throws -> T? {
-    var value: AnyObject?
-    let error = AXUIElementCopyParameterizedAttributeValue(element, attribute, param as! AnyObject, &value)
-
-    if error == .NoValue || error == .AttributeUnsupported {
-      return nil
-    }
-
-    guard error == .Success else {
-      throw error
-    }
-
-    return (value as! T)
-  }
-
   // MARK: - Actions
 
   /// Returns a list of actions that can be performed on the element.

    }
  }

  /// Sets the value of `attribute` to `value`.
  ///
  /// - warning: Unlike read-only methods, this method throws if the attribute doesn't exist.
  ///
  /// - throws:
  ///   - `Error.AttributeUnsupported`: `attribute` isn't supported.
  ///   - `Error.IllegalArgument`: `value` is an illegal value.
  ///   - `Error.Failure`: A temporary failure occurred.
  public func setAttribute(attribute: Attribute, value: Any) throws {
    try self.setAttribute(attribute.rawValue, value: value)
  }

  public func setAttribute(attribute: String, value: Any) throws {
    let error = AXUIElementSetAttributeValue(element, attribute, packAXValue(value))

    guard error == .Success else {
      throw error
    }
  }

  // Checks if the value is one supported by AXValue and if so, wraps it.
  // If the value is a UIElement, unwraps it to an AXUIElement.
  private func packAXValue(value: Any) -> AnyObject {

    return try self.attribute(attribute.rawValue)
  }

  public func attribute<T>(attribute: String) throws -> T? {
    var value: AnyObject?
    let error = AXUIElementCopyAttributeValue(element, attribute, &value)
