I need to trigger accessory connected notification for testing purposes, for which I need to create an instance of EAAccessory class and send a fake accessory. How do I do that? I get this exception `EAAccessoryInitException`. *** Terminating app due to uncaught exception ‘EAAccessoryInitException’, reason: ‘-init not supported. EAAccessoryManager is responsible for creating all objects.’ Is there any other way to test this behavior?
How to create EAAccessory instance?
That’s not going to work, alas. When dealing with complex system types like
EAAccessory
you can’t just conjure them out of thin air.
One way to deal with this is to create a custom protocol that encapsulates all the services that this part of your app needs and then:
Conform
to that protocol for use within your appEAAccessory
Create a dummy type that conforms to that protocol for use within your tests
For example, imagine that your notification code maintains a mapping from the connection ID to the accessory. That might be declared like this:
var accessoriesByID: [Int:EAAccessory] = [:]
Instead, you can declare it like this:
protocol MyAccessory : AnyObject {
var connectionID: Int { get }
}
var accessoriesByID: [Int:MyAccessory] = [:]
You can now conform
EAAccessory
to
MyAccessory
for use in your real app.
extension EAAccessory : MyAccessory {
}
You don’t need to write any code here because
EAAccessory
already satisfies the protocol requirements.
And for testing you can create a dummy accessory that conforms to the protocol:
class DummyAccessory : MyAccessory {
var connectionID: Int = 0
}
Note that while this example is in Swift you can do a similar thing in Objective-C (and it may turn out to be easier because Objective-C is a little more flexible when it comes to protocol requirements).
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"
How can you then inject that into a property that must return only EAAccessory objects, such as EAAccesoryManager.shared().connectedAccessories ?
I would abstract my access to that property as well.
Alternatively, you could build a high-level abstraction layer that represents an accessory and then implement that twice, one on top of EA framework and against using dummy accessories for testing. You’ll have to test that abstraction layer with real accessories, but you can test the rest of your app against dummies.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"
I coded objective c version but I got
-[DummyAccessory _protocolIDForProtocolString:]: unrecognized selector sent to instance error
It’s hard to say what’s going on here without looking at your code in more detail. I encourage you to start a new thread with those details. Feel free to reference this thread for context. Oh, and tag it with ExternalAccessory, Testing and Objective-C so that I see it.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"