UIWindow implicitly declares delegate property with standard accessors instead of private ones.

Originator:anthony
Number:rdar://27267968 Date Originated:07/10/2016
Status:Open Resolved:
Product:iOS Product Version:9.3.2
Classification:Bug Reproducible:Always
 
Summary:
So if a UIWindow subclass redefines a delegate property and use it then, that leads to unexpected behavior and weird side effects (like interface rotations get disabled) which are difficult to debug.

Private delegates in UIKit must be declared with custom accessors, e.g.:

@property (getter=_delegate, setter=_setDelegate:, nonatomic <UIWindowInternalDelegate> *delegate;

Steps to Reproduce:
Compile and run the following code, which demonstrates harmful side effects:

// UIWindow with redefined delegate.
@interface Window : UIWindow
@property (nonatomic, weak) id<NSObject> delegate;
@end

@implementation Window
@end

// View controller which can change UIWindow delegate.
@interface ViewController : UIViewController
@end

@implementation ViewController

- (instancetype)initWithWindow:(Window *)window {
  self = [super init];
  if (self) {
    window.delegate = self;
  }
  return self;
}

- (void)viewWillTransitionToSize:(CGSize)size
       withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
  [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];

  // Never called because we've overridden UIWindow delegate and set it before setRootViewController.
  assert(NO);
}

@end

// Standard application delegate.
@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (nonatomic) Window *window;

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  self.window = [[Window alloc] initWithFrame:[UIScreen mainScreen].bounds];
  self.window.rootViewController = [[ViewController alloc] initWithWindow:self.window];
  [self.window makeKeyAndVisible];

  return YES;
}

@end


Expected Results:
Private UIKit properties do not cause collisions with public ones declared in subclasses.
The code above should invoke viewWillTransitionToSize:withTransitionCoordinator: on device rotation.

Actual Results:
Private UIWindow delegate property causes collisions with public one declared in subclasses.
The code above does not invoke viewWillTransitionToSize:withTransitionCoordinator: on device rotation.

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!