mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-09-14 16:08:51 +00:00
Merge pull request #1624 from maicki/FixDelegateProxyCrash
[Accessibility / iOS 8] Fix 8.0 and 8.1-only, VoiceOver crash when clearing delegate / dataSource for Table or Collection
This commit is contained in:
commit
d88e170163
@ -343,10 +343,10 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
{
|
||||
// Note: It's common to check if the value hasn't changed and short-circuit but we aren't doing that here to handle
|
||||
// the (common) case of nilling the asyncDataSource in the ViewController's dealloc. In this case our _asyncDataSource
|
||||
// will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to nil out
|
||||
// super.dataSource in this case because calls to ASCollectionViewProxy will start failing and cause crashes.
|
||||
|
||||
super.dataSource = nil;
|
||||
// will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to hold a strong
|
||||
// reference to the old dataSource in this case because calls to ASCollectionViewProxy will start failing and cause crashes.
|
||||
NS_VALID_UNTIL_END_OF_SCOPE id oldDataSource = super.dataSource;
|
||||
|
||||
if (asyncDataSource == nil) {
|
||||
_asyncDataSource = nil;
|
||||
_proxyDataSource = _isDeallocating ? nil : [[ASCollectionViewProxy alloc] initWithTarget:nil interceptor:self];
|
||||
@ -375,13 +375,9 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
{
|
||||
// Note: It's common to check if the value hasn't changed and short-circuit but we aren't doing that here to handle
|
||||
// the (common) case of nilling the asyncDelegate in the ViewController's dealloc. In this case our _asyncDelegate
|
||||
// will return as nil (ARC magic) even though the _proxyDelegate still exists. It's really important to nil out
|
||||
// super.delegate in this case because calls to ASCollectionViewProxy will start failing and cause crashes.
|
||||
|
||||
// Order is important here, the asyncDelegate must be callable while nilling super.delegate to avoid random crashes
|
||||
// in UIScrollViewAccessibility.
|
||||
|
||||
super.delegate = nil;
|
||||
// will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to hold a strong
|
||||
// reference to the old delegate in this case because calls to ASCollectionViewProxy will start failing and cause crashes.
|
||||
NS_VALID_UNTIL_END_OF_SCOPE id oldDelegate = super.delegate;
|
||||
|
||||
if (asyncDelegate == nil) {
|
||||
_asyncDelegate = nil;
|
||||
|
@ -268,10 +268,9 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
{
|
||||
// Note: It's common to check if the value hasn't changed and short-circuit but we aren't doing that here to handle
|
||||
// the (common) case of nilling the asyncDataSource in the ViewController's dealloc. In this case our _asyncDataSource
|
||||
// will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to nil out
|
||||
// super.dataSource in this case because calls to ASTableViewProxy will start failing and cause crashes.
|
||||
|
||||
super.dataSource = nil;
|
||||
// will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to hold a strong
|
||||
// reference to the old dataSource in this case because calls to ASTableViewProxy will start failing and cause crashes.
|
||||
NS_VALID_UNTIL_END_OF_SCOPE id oldDataSource = self.dataSource;
|
||||
|
||||
if (asyncDataSource == nil) {
|
||||
_asyncDataSource = nil;
|
||||
@ -299,13 +298,9 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
{
|
||||
// Note: It's common to check if the value hasn't changed and short-circuit but we aren't doing that here to handle
|
||||
// the (common) case of nilling the asyncDelegate in the ViewController's dealloc. In this case our _asyncDelegate
|
||||
// will return as nil (ARC magic) even though the _proxyDelegate still exists. It's really important to nil out
|
||||
// super.delegate in this case because calls to ASTableViewProxy will start failing and cause crashes.
|
||||
|
||||
// Order is important here, the asyncDelegate must be callable while nilling super.delegate to avoid random crashes
|
||||
// in UIScrollViewAccessibility.
|
||||
|
||||
super.delegate = nil;
|
||||
// will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to hold a strong
|
||||
// reference to the old delegate in this case because calls to ASTableViewProxy will start failing and cause crashes.
|
||||
NS_VALID_UNTIL_END_OF_SCOPE id oldDelegate = super.delegate;
|
||||
|
||||
if (asyncDelegate == nil) {
|
||||
_asyncDelegate = nil;
|
||||
|
@ -125,7 +125,15 @@
|
||||
if (_target) {
|
||||
return [_target respondsToSelector:aSelector] ? _target : nil;
|
||||
} else {
|
||||
[_interceptor proxyTargetHasDeallocated:self];
|
||||
// The _interceptor needs to be nilled out in this scenario. For that a strong reference needs to be created
|
||||
// to be able to nil out the _interceptor but still let it know that the proxy target has deallocated
|
||||
// We have to hold a strong reference to the interceptor as we have to nil it out and call the proxyTargetHasDeallocated
|
||||
// The reason that the interceptor needs to be nilled out is that there maybe a change of a infinite loop, for example
|
||||
// if a method will be called in the proxyTargetHasDeallocated: that again would trigger a whole new forwarding cycle
|
||||
id <ASDelegateProxyInterceptor> interceptor = _interceptor;
|
||||
_interceptor = nil;
|
||||
[interceptor proxyTargetHasDeallocated:self];
|
||||
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user