CoreHID, Would someone unwind this for me?

This code block is from the CoreHID documentation.I want to use CoreHID to communicate to a USB device. I cannot make sense of this call. There's a for, try and 2 awaits. I think I understand what it's supposed to do, I can't understand the syntax. Where is the "catch"? should the enclosing function throw? Thanks for any help.

// The criteria combines multiple sets in a single array.
for try await notification in await manager.monitorNotifications(matchingCriteria: [matchingCriteria]) {
switch notification {
case .deviceMatched(let deviceReference):
print("A device was found.")

    case .deviceRemoved(let deviceReference):
        print("A device was removed.")


    default:
        continue
}

}

The for here is an iteration over an AsyncThrowingStream, so the try is needed in that position to acknowledge that each iteration may throw. Because there's no catch in the code fragment, the implication is that the catch would happen in additional code (omitted from the example for clarity) in whatever function contains this fragment, or the containing function would itself be a throwing function, so that the caller of that function would have to deal with thrown errors.

The rest of the syntax is for await … in await …. There are 2 awaits because there are two sources of suspension points (and hence asynchronicity) in the loop.

The first is the returned value of monitorNotifications(matchingCriteria: ). That function asynchronously returns a value, so it needs to be awaited.

The returned value is actually an async stream (specifically: AsyncThrowingStream), so each result of each iteration, in the notification variable has to be awaited too.

The two sources of asynchronicity in this aren't necessarily related. You could have an async stream that's determined synchronously (for await … in …) or you could iterate synchronously over a collection that's determined asynchronously (for … in await …).

1 Like

Thank you. I have a lot to get my head around. You broke it down clearly, showing me the parts I need to understand and how they should fit. I've found a couple resources explaining an async stream and throwing async streams.

I am wondering why that piece of code wasn't written like this.

// The criteria combines multiple sets in a single array.
let notifications = try await manager.monitorNotifications (matchingCriteria: [matchingCriteria])

for try await notification in notifications {
      switch notification {
      case .deviceMatched(let deviceReference):
          print("A device was found.")
      case .deviceRemoved(let deviceReference):
          print("A device was removed.")
      default:
          continue
      }
}

I have it working. Thanks for the help and a thank you to the SwiftLee blog. Still a lot to absorb, but I'm making good headway.