- This topic has 6개 답변, 3명 참여, and was last updated 4 years, 7 months 전에 by 멍단비.
1 답변 글타래를 보이고 있습니다
-
글쓴이글
-
-
광현참가자
- 글작성 : 15
- 답글작성 : 26
스토리보드를 통한 UI 생성에도 익숙해지고자 스토리보드를 공부하던 도중, @IBOutlet weak var: …를 쓰는 것에 처음에는 의문이 없었지만 weak 키워드를 쓰는 것에 의문이 생겼습니다. ARC(자동 참조 계수)와 깊은 연관이 있다는 것을 알게 되어 공부 중에 있습니다.
- 스토리보드에서 UIObject를 생성했을 때, 스토리보드 내에서 해당 UIObject의 인스턴스가 생성되는 것인지 궁금합니다.
- 그렇다면 ViewController는 @IBOutlet 변수 또는 상수를 통해 접근하는 것으로 이해했습니다. 그리고 weak으로 선언하는 이유가 위의 사이트를 참조하고 생각해 본 결과 strong 참조 (강한 참조)를 하게 되면 ViewController 와 View 간에 서로를 참조하는 관계?(맞는 표현인지는 모르겠습니다.) 다른 분의 블로그에서는 서로 멱살을 잡은 상태라고 표현하는 상태라고 생각하는 데 틀린 부분이 있다면 알고 싶습니다.
- 위 참조 사이트 중 하나에서는 strong 으로 해도 오류는 발생하지 않는다는 문구가 있었습니다. 다만 필요에 따라 weak, unowned, strong 을 구분해서 써야한다고 알고 있습니다. 혹시 그 구분 방법이 있는지 알고 싶습니다.
- 이 게시글은 광현에 의해 4 years, 7 months 전에 수정됐습니다. 이유: 줄 바꿈 고침
2020-04-03 오후 8:57 #6020 -
야곰키 마스터
- 글작성 : 37
- 답글작성 : 579
- 스토리보드에서 생성되는 것은 아닙니다. 앱이 실행되어 뷰를 스토리보드에서 불러오는 순간, 스토리보드에 구성해 놓은 모양대로 그 때 뷰의 인스턴스가 생성되어 동작하게 됩니다. 즉, 스토리보드에는 어떤 뷰 클래스의 뷰가 어디에 위치할지 등의 정보만 담아두고, 실제로 뷰 클래스의 인스턴스가 생성되는 시점은 스토리보드로부터 뷰 구성 정보를 불러와서 화면에 보여주려 할 때(앱 동작 중)입니다. 그래서 뭔가 런타임 오류 발생여지가 있어도 스토리보드에서는 직접 오류가 발생하지 않고, 실행해서 화면이 보여지려고 하는 순간 오류로 앱이 죽죠. 스토리보드는 앱 동작 전에 이미 만들어져있으므로 스토리보드에 직접 인스턴스가 생성된다고 볼 수는 없습니다. 그저 우리 눈에 그렇게 보이는것 뿐입니다.
- `@IBOutlet`은 변수만 가능합니다. 상수는 불가능합니다. 그 이유는 위의 설명과 연관있는데요, 이미 `@IBOutlet` 프로퍼티가 메모리에 생성된 후에 동적으로 스토리보드 정보로부터 만들어진 인스턴스를 `@IBOutlet` 프로퍼티에 할당해야 하기 때문입니다. 그런데 해당 프로퍼티가 상수면 변경(할당)이 불가하기 때문에 항상 변수(`var`)여야 합니다.
- 통상 처음 배우는 분들은 뷰 컨트롤러의 view 위에 얹어지는 subview를 `@IBOutlet` 프로퍼티로 지정하므로 그 기준으로 설명하겠습니다. 뷰 컨트롤러의 뷰 위에 얹어지는 자식뷰를 `@IBOutlet` 프로퍼티에 `strong`으로 할당되면 retain count가 1 증가합니다. 그리고 어딘가의 자식 뷰로 얹어지면 retain count가 1 추가로 증가합니다. 그래서 뷰컨트롤러의 view 위에 얹어진 자식뷰의 retain count는 `@IBOutlet`이 `strong` 프로퍼티인 경우 기본적으로 retain count가 2입니다. 꼭 서로 멱살잡고 있는 구조는 아닙니다… 서로 멱살잡고 있는 모습은 순환참조 문제인데, 이 문제는 순환참조 문제에 해당하지 않습니다.
- 위의 설명처럼 `strong`으로 해도 전혀 오류는 발생하지 않습니다. 다만 자식뷰가 부모뷰에서 떨어져 나와도 retain count가 1이 남아있으므로 뷰컨트롤러가 메모리에서 해제되기 전까지 @IBOutlet 변수의 뷰는 메모리에서 해제되지 않습니다(물론 부모 뷰에서 떨어져나온 후 아웃렛 변수에 `nil`을 할당하면 메모리에서 해제됩니다. 이해가 안가면 ARC 조금 더 공부하면 좋습니다). 이를 의도하고 `strong`으로 할당한다면 괜찮습니다. 가령 경우에 따라서 해당 뷰를 부모 뷰에 붙였다 뗐다 해야 하는 경우엔 유용합니다. 하지만 이것도 뷰를 직접 뗐다(`removeFromSuperview`) 붙였다(`addSubview:`) 보다는 그냥 뷰를 잠깐 안보이게 hidden하는 방법이 있습니다. 이때는 부모 뷰에서 실질적으로 떨어져 나온 것이 아니기 때문에 retain count의 변화는 없습니다. 그래서 통상 의도적인 목적이 없는 경우에는 `@IBOutlet` 변수를 `weak`로 선언하여 아웃렛 인스턴스의 retain count를 1로 만들어줍니다. 부모 뷰에서 떨어져 나오면 retain count가 0이 되므로 바로 메모리에서 해제되죠.
위 내용을 검증하고 싶다면 아래 클래스를
@IBOutlet
변수의 클래스로 지정해 준 후에strong
으로 할당한 후 실행했을 때, 아웃렛 변수에 해당하는 뷰를 부모 뷰에서 떼어내면(removeFromSuperview
)deinit
이 호출되지 않아요. 반대로weak
로 할당한 후에 실행하면removeFromSuperview
이후엔deinit
이 호출되는 것을 확인할 수 있을겁니다.class MyView: UIView { deinit { print("뷰가 메모리에서 해제됨") } }
2020-04-03 오후 9:48 #6033-
-
멍단비참가자
- 글작성 : 10
- 답글작성 : 98
덕분에 버스타서 같이 공부 좀 했네요. 감사합니다.
추가로 공식문서 링크도 설명이 잘 나와있는 것 같아서 참고하시라고 첨부합니다.
https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html
<p style=”color: red !important;”>파이팅하세요~</p>
@yagom 이거 왜 안될까요..?- 이 답변은 멍단비에 의해 4 years, 7 months 전에 수정됐습니다.
- 이 답변은 멍단비에 의해 4 years, 7 months 전에 수정됐습니다.
- 이 답변은 멍단비에 의해 4 years, 7 months 전에 수정됐습니다.
- 이 답변은 멍단비에 의해 4 years, 7 months 전에 수정됐습니다.
- 이 답변은 멍단비에 의해 4 years, 7 months 전에 수정됐습니다.
- 이 답변은 멍단비에 의해 4 years, 7 months 전에 수정됐습니다.
- 이 답변은 멍단비에 의해 4 years, 7 months 전에 수정됐습니다.
- 이 답변은 멍단비에 의해 4 years, 7 months 전에 수정됐습니다.
- 이 답변은 멍단비에 의해 4 years, 7 months 전에 수정됐습니다.
- 이 답변은 멍단비에 의해 4 years, 7 months 전에 수정됐습니다.
- 이 답변은 멍단비에 의해 4 years, 7 months 전에 수정됐습니다.
- 이 답변은 멍단비에 의해 4 years, 7 months 전에 수정됐습니다.
- 이 답변은 멍단비에 의해 4 years, 7 months 전에 수정됐습니다.
- 이 답변은 멍단비에 의해 4 years, 7 months 전에 수정됐습니다.
2020-04-03 오후 11:39 #6043
-
-
글쓴이글
1 답변 글타래를 보이고 있습니다
- 답변은 로그인 후 가능합니다.