iOS - @IBOutlet / @IBAction

이한솔·2023년 8월 2일
0

iOS 앱개발 🍏

목록 보기
3/49

💡 IB : Interface Bulider의 줄임말

@IBAction

함수 형태로 storyboard와 viewController를 연결하여 해당 UI컴포넌트의 동작을 정의한다. 즉 IBAction은 Interface Builder를 통해 받아온 정보로 Action을 수행하겠다는 의미이다.



@

앞에 붙은 @ 는 컴파일러에게 어떤 속성을 가지고있다고 전하는 예약어이다.



@IBOutlet

변수 형태로 storyboard와 viewController를 연결하는 것이다.
StoryBoard 상에 선언한 view객체를 Interface Builder가 알아볼 수 있게 만드는 것이다.



IBOutlet 연결 strong VS weak

💡 RC란?
메모리가 내부적으로 몇번 참조되었는지를 자동으로 카운팅하는 Reference Counting으로 강한 참조시 RC가 +1증가한다.
(ARC 공부할 때 더 알아보자!)

기본적으로 VC는 자신이 관리하는 View에 강한 참조를 유지한다. (RC +1)

View는 자신의 하위 View객체에 대해 강한 참조를 유지하기 때문에 개발자가 view에 올린 View객체들은 기본적으로 강한 참조 된다. (RC +1)

View객체들은 각 클래스 인스턴스로서 Heap영역에 각자 저장되고, IBOutlet으로 VC와 연결되면 VC는 Outlet 변수로 각 View객체의 참조를 저장한다.

@IBOutlet strong (강한참조)

VCView를 강하게 참조한다 ➡️ View의 RC: 1
ViewView객체를 강하게 참조한다 ➡️ 뷰객체의 RC: 1
VCView객체를 강하게 참조한다 ➡️ 뷰객체의 RC: 2

@IBOutlet wesak (약한참조)

VCView를 강하게 참조한다 ➡️ View의 RC: 1
ViewView객체를 강하게 참조한다 ➡️ 뷰객체의 RC: 1
VCView객체를 약하게 참조한다 ⇨ 뷰객체의 RC: 1 (변동없음)



💡 @IBOutlet strong 참조 시

VC가 정상적으로 메모리에서 해제되면 메모리 누수가 발생하지 않는다.

  1. VC가 메모리에서 해제되면서 View와 View객체에 대한 참조를 잃는다
    ⇨ View RC 0 / View객체 RC 1
  2. View가 메모리에서 해제되면서 View객체에 대한 참조를 읽는다
    ⇨ View객체 RC 0

결론적으로 ViewController, View, View객체 모두 RC가 0이 되어 메모리에서 잘 해제된다.

하지만, 앱을 사용하다가 메모리가 부족해지면 메모리 누수가 발생한다.

  1. 메모리가 부족해지면 VC는 "didReceiveMemoryWarning()"라는 인스턴스 메서드를 호출하는데 이 메서드는 View를 메모리에서 해제시키면서 View가 강하게 참조하는 View객체들을 메모리에서 해제시키고 메모리를 확보하기 위해서 VC 내부의 View를 nil로 처리한다.
  2. View의 RC는 0이되고, View가 참조하던 View객체들에 대한 RC도 1 감소하지만
    ⇨ View RC 0 / View객체 RC 1
  3. VC가 View객체들을 강하게 참조하고 있기 때문에 View객체들의 RC가 1 남아있고 메모리에서 해제되지 않는다.
    ⇨ View객체 RC 1

결론적으로 메모리를 관리하기 위해 View를 해제시켰음에도 View객체들은 여전히 메모리에 남아서 메모리 누수가 발생한다.



❓ IBOutlet에서 옵셔널 강제 언래핑을 하는 이유

옵셔널 언래핑 방법 중 강제언래핑은 nil이 확실히 아닌 상황에서만 사용을 권고한다.
IBOutlet을 공부하다가 그렇다면 왜 IBOutlet은 옵셔널 강제 언래핑을 하는가? 궁금해져서 이유를 찾아봤다.

  1. 애플에서 권장하기 때문에 (가장 속 편한 대답인것 같다.)

  2. IBOutlet은 StoryBoard의 View 객체와 Interface Builder를 연결한다. IBOutlet으로 선언한 View가 nil인건 "에러"일 가능성이 높아서 IBOutlet 객체가 nil일 때는 앱을 크래시 해서라도 수정해야 하고 만약 IBOutlet 객체를 사용하지 않을 것이라면 선언조차 하지 말라는 의미인것 같기도 하다.

  3. viewDidLoad()가 아직 되지 않은 상태라면, 각종 레이블이나 서브뷰 처럼 뷰컨트롤러가 들고 있는 프로퍼티들은 아직 로드되지 않은 상태인 것이다.
    바꿔서 말하면, viewDidLoad() 호출 이후에는 해당 값들이 존재함이 보장되므로, 강제 언래핑이어도 일단은 괜찮다는 것이다.

이렇게 세가지 이유로 정리되었다.
결론은, IBOutlet에서 옵셔널 강제 언래핑을 하는 것은 통상적이라는 것이다.







[ 참고 ]

https://cocoacasts.com/should-outlets-be-optionals-or-implicitly-unwrapped-optionals
https://developer.apple.com/library/archive/documentation/General/Conceptual/Devpedia-CocoaApp/Outlet.html

3개의 댓글

comment-user-thumbnail
2023년 8월 2일

@의 예약어 개념 잘 배워갑니다!

답글 달기
comment-user-thumbnail
2023년 8월 2일

정리해주셔서 감사합니다!

답글 달기
comment-user-thumbnail
2023년 8월 2일

IBAction과 IBOutlet의 개념을 잘 배우고 갑니다!

답글 달기