티스토리 뷰

iOS

iOS TextField memory leak

경표다 2021. 7. 16. 10:50

becomeFirstResponder의 시점에 따라 deinit이 되지 않아 메모리 릭이 생기는 문제를 겪었다.

// viewWillAppear에서 becomeFirstResponder를 하면
// 뷰컨이 deinit될 때 TextField가 같이 deinit 되지 않음.
// viewWillDisappear에서 명시적으로 resign을 해줘도 안됨.
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    couponCodeTextField.becomeFirstResponder()
}

// 굳이 명시적으로 resign 안해줘도 잘 deinit 됨
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    couponCodeTextField.becomeFirstResponder()
}

도대체 머가 문제지;;;;;;

 

일단 becomeFirstResponder를 언제 호출하느냐의 문제가 아니었음.

 

아 그리고 becomeFirstResponder는 viewWillAppear에서 해주면 안 됨!

becomeFirstResponder의 공식문서 설명 →

 

활성화된 뷰 계층에 속하지 않은(뷰 계층에 올라가지 않은) 뷰에서 이 메소드를 절대 부르지 마라!

그런데 viewWillAppear 는 ?

 

대충 "이 메소드는 뷰컨의 뷰가 뷰 계층에 막 추가되기 전에! 불린다 그니깐 이런저런 거~ 하면 된다"라는 뜻

즉 viewWillAppear가 불리는 시점은 뷰컨이 뷰 계층에 올라가기 전! 이기 때문에 becomeFirstResponder는 viewWillAppear에서 하면 안 됨!

여기서 하면 뷰컨이 deinit 될 때 같이 안됨..

 

 

추가적인 문제는,,

 

viewDidAppear에서 했는데도 메모리 해제가 안된다?? 이때의 문제는,,

 

viewDidLoad에서 setUp() 이런 식으로 전체적인 뷰 레이아웃을 잡거나 뷰를 초기화하거나 할 때 textField.text = "TEXT"

 

이렇게 textField의 초기 text값을 설정해두면, (보통 이렇게 값을 넣어둘 일이 없지만 테스트용으로 넣어뒀다가;;)

즉 textField에 becomeFirstResponder 를 호출하기 전에 text 값을 임의로 넣는다면 이것 때문에도 메모리 해제가 안될 수 있음.

 

중간 정리를 하자면 becomeFirstResponder는 뷰 계층에 올라간 후에! 호출해야 함.

 

그리고 text를 흔히 말하는 programmatical 방법으로 임의로 넣어야 한다면 becomeFirstResponder가 호출된 후에! 해야 함.

 

뷰컨이 해제된 후 메모리에 남아있는 TextField를 메모리 그래프로 본다면 이렇게 보임..

 

저 진한 선이 strong 참조를 나타내는데 UIKBAutofillController에 연결된 것을 알 수 있음.

 

구글링,, ios kbautofillcontroller

iOS 14.3 UITextField leak?

 

iOS 14.3 UITextField leak? | Apple Developer Forums

I cannot offer any help, but I have the same issue. I noticed that it appears when I switch the view while the cursor is still in the text field. I tried adding resignFirstResponder in different ways, it did not help.

developer.apple.com

정확히는 알 수 없지만 대충 키보드의 자동완성 기능이랑 나의 TextField랑 눈 맞아서 서로를 안 놔주게 된 상황인 거 같으다..

 

그래서 위 링크에 나와있는 것처럼

textField.autocorrectionType = .no textField에 이러한 속성을 추가해주면 viewWillAppear에서 하든(하면 안 되지만!!!), viewDidAppear에서 하든 메모리 해제가 아주 잘 된다...

 

근데 이렇게 하는 것은 결국엔 textField에 autocorrection을 지원하지 않겠다는 것이니 상황에 맞게 주의해서 사용해야겠다.

그리구 이때 OneTime Code(textContentType = .oneTimeCode) 자동 완성도 안될지 테스트해봐야 할 것 같다.

 

 

❓추가적인 의문,,,

viewWillAppear에서 textField를 becomeFirstResponder 할 때랑 viewDidAppear에서 할때랑 눈으로 보이는 애니메이션 반응속도가 꽤 차이가 나는데,,,

 

이전에 사용해봤던 몇몇 앱에서 화면 전환하자마자 키보드가 올라왔던 경우를 생각해봤을 때 viewWillAppear에서 becomeFirstResponder를 하는 것 같은 반응속도였던 것 같은데,, 그런 데서는 어떤 식으로 대응을 했을지 궁금하다

'iOS' 카테고리의 다른 글

[번역] WatchKit  (0) 2022.01.20
iOS status bar style 변경하기  (1) 2021.11.18
Bastard Injection  (0) 2021.08.17
iOS App Life Cycle  (2) 2021.07.11
swift static, class, final class  (0) 2020.08.02