If I try to change the value of the speed parameter of a GKAgent2D (or its parent class GKAgent) in iOS9 I get this unrecognised selector error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[GKAgent2D setSpeed:]: unrecognized selector sent to instance
However in iOS10 this error does not occur and the speed of the agent is changed correctly.
I can reproduce the error in a very simple example (single view iOS application, change the view controller code to the following, note that the error occurs with either GKAgent2D or GKAgent):
import UIKit
import GameplayKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var agent = GKAgent()
agent.speed = 10
print(agent.speed)
}
}
The above always crashes with this unrecognised selector error on the line that sets the agent's speed on the simulator running iOS9.3, but not iOS10.3 (all this under Xcode 8.3.2).
The speed property of GKAgent is documented as being read and write and being supported under iOS9 - see Apple's Documentation for GKAgent, speed Property.
I had a similar problem with GKAgentDelegate, which would crash on iOS9 only with an unrecognised selector to agentWillUpdate. I worked around this by putting a dummy method in my code:
func agentWillUpdate(_ agent: GKAgent) {
}
I have tried a similar solution to the new error, by overriding the speed property in my GKAgent2D sub class and providing an explicit setter and getter, and even backing the speed parameter by a private Float as suggested by Kdawg, but the same error still occurs when the super's speed parameter is set:
class Agent:GKAgent2D {
override var speed:Float {
get {return localSpeed}
set {localSpeed = newValue}
}
private var localSpeed:Float {
get {return super.speed}
set {super.speed = newValue}
}
}
Any thoughts?
Specifically: are there any known issues with GKAgent in iOS9 regarding selectors?
Alternatively, any thoughts on an alternative work around?
I would like to support iOS9 if I can. It looks to me like a bug in GameplayKit - but I expect Apple's response to a report would be that it is fixed in iOS10.
Edited
What I meant was to have your subclass's property setter/getter just override the base class's and not try to access the parent class's setter at all, like this:
class Agent:GKAgent2D {
private var _speed: Float = 0.0
override var speed:Float {
get {return _speed}
set {_speed = newValue}
}
}
At that point, assuming that the GKAgent
and GKAgent2d
accesses speed
through its property getter, it will get the value of _speed
from the overridden getter in your subclass. This is why I suggested in the comments to try this after making that subclass:
var agent: GKAgent
agent = GKAgent2dSubType()
agent.speed = 10
I would then expect that if you then tried to read out the property of your GKAgent
agent, it would be 10. And so the expected behavior of your agent might work properly with your speed in there.
Original This is just a total guess (I'm not really familiar with the technologies here), but have you tried changing your
override var speed:Float {
get {return super.speed}
set {self.speed = newValue}
}
to not reference super.speed
or self.speed
(incidentally, shouldn't setting self.speed
from your speed
setter result in an infinite recursive call to that setter?) but rather to reference a private backing floating point value? Then maybe you'll be able to instantiate an object of type GKAgent2dSubClass
(however you've named that subclass) and have it work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With