Whenever the only remote attached to the Apple TV is an iOS Apple TV Remote app, the GCController object is connected and disconnected each time the tvOS app didResignActive:. This seems to be fine, the problem comes in the object passed with the GCControllerDidConnectNotification and GCControllerDidDisconnectNotification notifications.
When first starting the app, I receive:
Connected: <GCController 0x1c80a6b40 vendorName='Remote' deviceHash=0x113f884c0>
[GCController controllers]: (
"<GCController 0x1c80a6b40 vendorName='Remote' deviceHash=0x113f884c0>"
)
And then, if I long press the Home button to bring up the sleep dialog, I see:
Disconnected: <GCController 0x1c80a8a60 vendorName='Remote' deviceHash=0x113f884c0>
[GCController controllers]: (
"<GCController 0x1c80a6b40 vendorName='Remote' deviceHash=0x113f884c0>"
)
Notice at this point that the GCController that was disconnected (0x1c80a8a60) is a different object than the one that was connected (0x1c80a6b40).
I then dismiss the sleep dialog (either hit menu or cacel) and then I see:
Connected: <GCController 0x1c80a8a60 vendorName='Remote' deviceHash=0x113f88d10>
[GCController controllers]: (
"<GCController 0x1c80a8a60 vendorName='Remote' deviceHash=0x113f88d10>"
)
Notice that this is yet another new GCController object (0x1c80a8a60). So at this point in time, if I debug the memory graph. I can indeed see that their are three GCController objects pertaining to each of the ones listed above (0x1c80a6b40,0x1c80a8a60, and0x1c80a8a60) being retained by the same _GCControllerManager.
This by itself isn't a very big issue for me, the bigger issue is that if you continue to background (resign active) the app, valueChangedHandlers on the
GCControllerDirectionPad eventually stops being called. I set the valueChangedHandler on the dpad every single time a controller is connected (as shown below), but eventually it just stops getting called.
Is this a known issue?
Here is the code I used to demo this behavior.
#import "ViewController.h"
#import <GameKit/GameKit.h>
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSNotificationCenter* notifications = NSNotificationCenter.defaultCenter;
[notifications addObserver:self
selector:@selector(controllerConnected:)
name:GCControllerDidConnectNotification
object:nil];
[notifications addObserver:self
selector:@selector(controllerDisconnected:)
name:GCControllerDidDisconnectNotification
object:nil];
}
- (void)controllerConnected:(NSNotification*)notification {
GCController* controller = (GCController*)notification.object;
NSLog(@"Connected GCController %p", controller);
NSLog(@"GCControllers: %@", [GCController controllers]);
controller.microGamepad.dpad.valueChangedHandler = ^(GCControllerDirectionPad *dpad, float xValue, float yValue) {
NSLog(@"dpad.valueChangedHandler called");
};
}
- (void)controllerDisconnected:(NSNotification*)notification {
GCController* controller = (GCController*)notification.object;
NSLog(@"Disconnected GCController %p", controller);
NSLog(@"GCControllers: %@", [GCController controllers]);
}
@end