產生場景
通過繼承UITextField自定了一個textfield,在iOS11以下可以正常使用,在iOS11使用的時候無法釋放,不走- (void)dealloc 方法。通過Facebook的開源庫FBRetainCycleDetector檢測得到相應報告 如圖一 圖二。嘗試過切換第一響應者和在父類中置textfield為nil,未成功。
產生原因
根據FBRetainCycleDetector可以大致看到猜到原因。UITextField有一個名為_textContentView的私有變量,這個私有變量有一個名為_provider的私有變量,這個_provider就是UITextField自己。這些私有變量都是被強引用的,因此在使用當中引起了循環引用。
解決方案
在該UITextField子類當中置_provider為nil。
- (void)didMoveToWindow
{
? ? [super didMoveToWindow];
? ? if (@available(iOS 11.2, *)) {
? ? ? ? NSString *keyPath = @"textContentView.provider";
? ? ? ? @try {
? ? ? ? ? ? if (self.window) {
? ? ? ? ? ? ? ? id provider = [self valueForKeyPath:keyPath];
? ? ? ? ? ? ? ? if (!provider && self) {
? ? ? ? ? ? ? ? ? ? [self setValue:self forKeyPath:keyPath];
? ? ? ? ? ? ? ? }
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? [self setValue:nil forKeyPath:keyPath];
? ? ? ? ? ? }
? ? ? ? } @catch (NSException *exception) {
? ? ? ? ? ? NSLog(@"%@", exception);
? ? ? ? }
? ? }
}
疑惑
iOS11為什么多一個provider私有成員變量,有什么作用,置為nil后有什么影響。