Hide chapters

Catalyst by Tutorials

9. The Mouse
Written by Andy Pereira

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

Just like a keyboard, the mouse is a toolset that you may not have encountered if you’ve focused solely on iOS development. Catalyst makes working with the mouse easy since it provides a familiar pattern, and it gives you a great amount of control in the process.

In this chapter, you’ll learn how to implement PointerStyleProvider and UIHoverGestureRecognizer. You’ll take a look at the differences between iOS/iPadOS and touch targets in macOS.

Getting started

Open the starter project for this chapter. Build and run for iPadOS. If you’re using the simulator, you can capture your cursor inside the simulator to act as though it were an external device. Do this by selecting Capture Pointer in the simulator toolbar:

Add a few entries and then move your mouse around the app. Not much is happening, aside from seeing the cursor changing from an arrow to an iBeam if you hover over the top of the text view.

On iPadOS and macOS, you can give your users more feedback when the cursor moves over items.

Pointer style providers

On iPadOS, your cursor is going to behave a bit different from that of macOS. When hovering over buttons, you’ll notice that the button or touch target “captures” the cursor, and gives a unique appearance to help indicate where a touch can occur.

if let button = reusableView.viewWithTag(1) as? UIButton {
  button.pointerStyleProvider = { button, effect, _ in
    var rect = button.bounds
    rect = button.convert(rect, to:
    return UIPointerStyle(effect: effect, shape: .roundedRect(rect))

Adding effects with hover gesture recognizer

Next, you’ll use UIHoverGestureRecognizer to add some more effects for iPadOS, as well as macOS.

private func addHoverGesture() {
  let hoverGesture
    = UIHoverGestureRecognizer(target: self,
                               action: #selector(hovering(_:)))
@objc private func hovering(_ recognizer: UIHoverGestureRecognizer) {
  // 1
  guard !isSelected else { return }
  // 2
  switch recognizer.state {
  // 3
  case .began, .changed:
    backgroundColor = .secondarySystemBackground
  // 4
  case .ended:
    backgroundColor = .none

let hoverGesture
  = UIHoverGestureRecognizer(target: self,
      action: #selector(self.hovering(_:)))
@objc private func hovering(_ recognizer: UIHoverGestureRecognizer) {
  #if targetEnvironment(macCatalyst)
  switch recognizer.state {
  case .began, .changed:
  case .ended:

A few notes on elements and haptics

Keep in mind that the interface guidelines for iOS state that you should keep touch targets for interactive elements to a minimum of 44pt × 44pt. The cursor gives you a lot more flexibility when your app is running on macOS. If you’re creating macOS-specific UI elements, you can use smaller elements if it makes sense for your app.

Bridging the gap

In a previous edition of this book, some frameworks or tools that were available in macOS were not available in Mac Catalyst, like NSCursor. While NSCursor has been added now, if you find yourself needing to utilize some other components, you can create an AppKit bundle. Creating a bundle and accessing its contents is out of the scope of this book, but here are some pointers:

Key points

  • You can use PointerStyleProvider to respond to cursor events on iPadOS.
  • Add hovering to views by adding a hover gesture recognizer to give your user more visual feedback.
  • Hover gesture recognizers work similarly to other gesture recognizers.
  • You can access NSCursor on macOS with Catalyst.
  • Bundles may provide a solution to missing functionality.

Where to go from here?

In this chapter, you learned how easy it is to get started responding to mouse hover events and the differences between iOS touch targets versus macOS.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2023 Kodeco Inc.

You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.

Unlock now