UIKit accesses dead objects in certain view configurations
| Originator: | mike.ferenduros | ||
| Number: | rdar://22812548 | Date Originated: | 23-Sep-2015 03:51 AM |
| Status: | Duplicate of 22473314 (Open) | Resolved: | Closed |
| Product: | OS X SDK | Product Version: | |
| Classification: | Reproducible: | Always |
Summary:
When a scrollview and it's delegate are deallocated in a particular order, UIKit attempts to access the scrollview after it's been deallocated, causing a crash in many situations.
Specifically I observed it in the following situation:
- A custom UIView 'V' subclass contains a reference to a UIScrollView SV
- V is SV's delegate
- V holds the last reference to SV when it's dealloced
The error appears to be because ordinarily, deallocing SV would remove the UIAXDelegateClearer from it's delegate, but for some reason fails to here, perhaps because the delegate is in the process of being dealloced. Then when V continues to dealloc it has a stale delegate-clearer left pointing at the dead SV.
Steps to Reproduce:
Open the attached project in XCode
Edit your debugging scheme and check 'Enable'Zombie Objects'
Select the 'iPad Air' simulator
Build and run it
Click the 'TAP ME' button, then go back again
Expected Results:
I would expect the project to run without error.
Actual Results:
The debugger traps an error warning that "-[UIScrollView performSelector:withObject:]: message sent to deallocated instance ---"
Version:
Version 7.0 (7A220)
10.11.1
Notes:
Associated dev forum post: https://forums.developer.apple.com/message/59615
Configuration:
I've observed it on 64bit targets only.
Attachments:
'crashy2.zip' was successfully uploaded.
---
IMPORTANT!!!
Apologies, I forgot to add something very important: This appears to be related to accessibility. It was reported by several users with unremarkable setups, but I was only able to reproduce the crash in the simulator by first enabling the accessibility inspector in the simulator's settings app.
---
A more concise example:
@interface Crasher: NSObject <UIScrollViewDelegate>
@property (nonatomic,retain) UIScrollView *sv;
@end
@implementation Crasher
- (instancetype)init {
if( self = [super init] ) {
self.sv = [UIScrollView new];
self.sv.delegate = self;
}
return self;
}
@end
void test() {
[Crasher new];
}
---
This looks like it's a result of UIScrollView.delegate becoming a weak reference - the delegate is zeroed at the start of it's delegate's dealloc, which bypasses [UIScrollViewAccessibility setDelegate], breaking an assumption in how it manages UIAXDelegateClearer.
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!