iOS11 UITextField memory leak

Hi,

When I run my Demo on my iPhone or simulator with system iOS11.2 , textField never perform dealloc. For a long time, I cann't find any sulution for this problem.

So I find help here for some progress, Thanks!

Replies

A lot of developers met the same problem, but no solutioins~ waiting for help

may be you have a retain cycle somewhere.


You should declare the textField as weak probably

You can test the retain by adding this print each time you reference theTextField :

Swift.print(#function, "CFGetRetainCount ", CFGetRetainCount(theTextField))

Have a look here : h ttps://forums.developer.apple.com/message/223351#223351

I just define a subClass of UITextField , named "ZYTextField". In "ZYTextField", I did nothing but rewrite the method "dealloc", in which I add a print log. Have a look below:


```

ZYTextField.m

-(void)dealloc {

NSLog(@"------- %s",__func__);

}

```

```

ZYViewController.m

- (void)viewDidLoad {

[super viewDidLoad];


ZYTextField * textField = [[ZYTextField alloc] initWithFrame:CGRectMake(100,200,100,50)];

[self.view addSubview:textField];

}

```

In ZYViewController.m file, I just add a textField as above code.

When ZYViewController dealloc , but ZYTextField's dealloc method never perform.

dealloc is not called probably because you still have a non zero reference count (that's how ARC is working).


Are you sure ZYViewController deallocs ?

I'm sure that ZYViewController deallocs~

You can build a Demo to test UITextField's leak in iOS11.2

Please, if you want some help, tell the results of proposed tests and report precisely what you get.


Did you do this ? What do you get ?

You can test the retain by adding this print each time you reference theTextField :

Swift.print(#function, "CFGetRetainCount ", CFGetRetainCount(theTextField))

Have a look here : h ttps://forums.developer.apple.com/message/223351#223351


How are you sure ZYViewController deallocs ?

ok, thanks for your reply seriously. Now I paste all precise code here

```

ZYTextField.m

-(void)dealloc {

NSLog(@"------- %s",__func__);

}

-(void)removeFromSuperview {

NSLog(@"------- %s",__func__);

}

```

```

ZYViewController.m

- (void)viewDidLoad {

[super viewDidLoad];


ZYTextField * textField = [[ZYTextField alloc] initWithFrame:CGRectMake(100,200,100,50)];

[self.view addSubview:textField];

}

-(void)dealloc {

NSLog(@"------- %s",__func__);

}

```

then ,console log as below: (when iOS11.2)

------- -[ZYViewController dealloc]

------- -[ZYTextField removeFromSuperview

then ,console log as below: (when iOS10)

------- -[ZYViewController dealloc]

------- -[ZYTextField removeFromSuperview

------- -[ZYTextField dealloc]

Did you try (sorry, I do not practice objc a lot, so not totally sure of the syntax)


__weak ZYTextField * textField = [[ZYTextField alloc] initWithFrame:CGRectMake(100,200,100,50)];

I think It's iOS11.2's bug, the memory graph is so strange when ZYViewController dealloc.

Do you know any apple's Engineer in the forum? Then get their attension on this issue.

In iOS 11.2, UITextField has a private member variable named '_textContentView', and '_textContentView' has a private variable named '_provider', which is the UITextField itself. These variables are all marked strong so retain cycle occurs. I got rid of it by subclassing it and setting '_provider' to 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.wmb_originalProvider) {
                    [self setValue:self.wmb_originalProvider forKeyPath:keyPath];
                }
            } else {
                self.wmb_originalProvider = [self valueForKeyPath:keyPath];
                [self setValue:nil forKeyPath:keyPath];
            }
        } @catch (NSException *exception) {
            NSLog(@"%@", exception);
        }
    }
}

I have the same problem, retain cycle is:

"_UITextFieldContentView._provider -> UITextField -> _textContentView -> _UITextFieldContentView "

iOS 11.2(15C114)

We have same problem, waiting for help

Here's the memory graph Image

http://upload-images.jianshu.io/upload_images/2684540-34caa821038666e6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240


The memory graph shows there's a obvious retainCycle. Now I provide a way to cut down the cycle. Code as below:

-(void)removeFromSuperview {
    NSLog(@"------- %s retainCount:%zd",__func__,CFGetRetainCount((__bridge CFTypeRef)(self)));
      
    if (self) {
        CFRelease((__bridge CFTypeRef)(self));
    }
}

That perfectly work~ But it's just for a way to solve without crash or other bug.

In fact , I want to kill _UITextFieldContentView , but that will cause crash. Have a look at the code below:

for (UIView * view in self.subviews) {
    if ([view isKindOfClass:NSClassFromString(@"_UITextFieldContentView")]) {
        NSLog(@"----- _UITextFieldContentView ------- %@",view);
        [view removeFromSuperview];
        CFRelease((__bridge CFTypeRef)(view));
    }
}

You can have a try, Have fun~ ^_^

Thankyou~

But that's all working code ? Any more code? I have test using your code, but no effect.

same problem a day wasted for nothing, I wait for the solution as soon as possible.