Skip to content

Latest commit

 

History

History
216 lines (143 loc) · 14.3 KB

week-4.md

File metadata and controls

216 lines (143 loc) · 14.3 KB

iOS 질문 모음 - 4

Q.

class 와 final class 의 차이가 무엇인가요?

그냥 선언한 클래스와 final 을 붙여 선언한 클래스의 차이가 무엇인가요?

질문 바로가기

A.

  • 클래스를 선언할 때 final 을 사용해 클래스의 상속을 막을 수 있습니다. final 로 선언된 클래스는 다른 클래스에서 상속할 수 없습니다.

    final class A {
    }
    
    // Inheritance from a final class 'A' 에러 발생
    class B: A {
    }

    final 로 선언된 클래스를 상속받으려 하면 컴파일 에러가 발생합니다.

  • 클래스뿐만 아니라 메소드, 프로퍼티, 서브스크립트에도 final 을 명시하여 재정의를 막을 수 있습니다.

    class A {
        final var name: String {
            return "A"
        }
        
        final subscript() -> Any? {
            get { nil }
            set(newValue) { }
        }
        
        final func hello() {
            print("hello A")
        }
    }
    
    class B: A {
        // Property overrides a 'final' property 에러 발생
        override var name: String {
            return "B"
        }
        
        // Subscript overrides a 'final' subscript 에러 발생
        override subscript() -> Any? {
            get { "override!" }
            set (newValue) { }
        }
        
        // Instance method overrides a 'final' instance method
        override func hello() {
            print("hello B")
        }
    }

    클래스의 상속은 허용하되 부분적으로 재정의를 막고 싶을 때 주로 사용합니다. Swift: Inheritance - Preventing Overrides 도 읽어보세요!

  • 만약 구현한 클래스를 상속할 일이 없다면 final 로 선언해주는 게 좋습니다. 상속하지 않을 클래스를 final 로 선언해주면 컴파일러에게 선언된 함수를 찾지 않고 직접 호출해야 한다고 알려주어 함수 호출에 의한 오버헤드를 줄여 성능을 향상시킵니다. 자세한 내용은 Increasing Performance by Reducing Dynamic Dispatch 를 참고하세요.

참고할 만한 비슷한 질문들


Q.

UI 업데이트는 왜 메인 스레드에서만 해야 하나요?

애플은 모든 UI 관련 작업이 메인 스레드에서 수행되어야 한다고 합니다.

백그라운드 스레드에서 UI 업데이트 작업을 하면 왜 오류가 발생하나요?

질문 바로가기

A.

  • 앱을 실행하면 Cocoa Touch 에서 UIApplication 의 인스턴스가 메인 스레드에서 설정됩니다.

    responderchain

    앱의 UI event 는 일반적으로 UIApplication -> UIWindow -> UIViewController -> UIView -> subviews(UILabel, UIButton 등) 와 같이 chain 으로 연결되는데, 이 responder chain 을 따라 UIApplication 으로 전달됩니다. 이러한 event chain 이 메인 스레드에서 동작하므로 responder chain 에 포함된 모든 UI 관련 동작들은 메인 스레드에서 수행되어야 합니다.

    간단하게 요약하자면 UI 와 관련된 모든 이벤트 처리를 메인 스레드에서 하므로 UI 업데이트는 반드시 메인 스레드에서 해야 합니다. UIKit 공식문서에서도 Important 로 메인 스레드에서의 UI 업데이트를 강조하고 있습니다.

  • 또 다른 이유는 아이폰의 그래픽 렌더링 방식입니다. 아이폰의 그래픽스 파이프라인은 동기식으로 동작합니다.

    CoreAnimationPipeline1

    레이블의 텍스트를 업데이트하는 상황을 예로 들어보겠습니다. 먼저 화면에 표시할 레이블의 계층 구조를 인코딩하여 렌더 서버로 전송합니다(Commit Transaction). 전송된 레이블의 뷰 계층은 렌더 서버에서 디코딩되고(Decode), 렌더 서버는 GPU 에게 렌더링 요청을 합니다(Draw Calls). 그런 다음 GPU 가 렌더링 작업을 시작합니다(Render). 벡터 형태의 글꼴을 래스터화하여 텍스트를 픽셀로 변환합니다. 텍스트를 자르거나, 투명도를 적용할 때와 같이 해당 텍스트가 혼합된 레이어의 일부분일 경우 그래픽 렌더러는 보여줘야 할 레이블의 픽셀을 계산합니다. 렌더링 작업이 모두 완료되면 픽셀 정보들을 화면에 표시하게 됩니다(Display).

    CoreAnimationPipeline2

    Core Animation Pipeline 에서는 1/60 초 만에 준비작업을 끝내고, 렌더링 서버로 데이터를 전송한 후 1/60 초 만에 렌더링을 완료합니다. 이런 식으로 동기식임에도 불구하고 앱이 멈추지 않고 화면 표시가 가능합니다.

    하지만 백그라운드 스레드에서 UI 업데이트를 하게 된다면, 많은 백그라운드 스레드가 각기 다른 뷰 계층 구조를 인코딩하여 렌더 서버로 전송할 것이고, 이에 따라 GPU 에 많은 렌더링 요청을 보내게 됩니다. 렌더링은 시스템 리소스가 많이 드는 작업이므로 GPU 가 이를 처리할 수 없어 심각한 문제가 발생합니다. 그래서 UI 업데이트는 메인 스레드에서만 수행되어야 합니다.

    Core Animation 과 모바일 GPU 의 작동 방식에 대해 더 자세한 정보를 얻고 싶다면 WWDC 2014: Advanced Graphics and Animations 를 읽어보세요.

참고할 만한 비슷한 질문들


Q.

클래스 이름의 NS 접두사의 의미가 무엇인가요?

Cocoa / Cocoa Touch 의 많은 클래스의 이름에 NS 접두사가 붙어있는 것을 볼 수 있었는데요. 어떤 의미인가요?

질문 바로가기

A.

  • 먼저 NS 접두사를 이해하려면 Objective-C 의 특징을 알아야합니다. Objective-C 는 C 언어를 동적이고 객체 지향적으로 확장한 언어입니다. C 언어를 확장했기에 C++ 의 namespace 같은 기능이 없습니다. 그래서 전역 namespace 에서 이름 충돌을 피하기위해 접두사가 필요합니다. 자기 자신만 사용할 목적으로 작성한 코드에서는 이 충돌을 신경쓰지 않아도 되지만, 다른 사람이 사용할 수 있도록 프레임워크 또는 라이브러리를 작성하는 경우 고유 접두사를 붙여야합니다. Coding Guidelines for CocoaGoogle Objective-C Style Guide 에 접두사에 대한 설명이 있습니다. CocoaDev: ChooseYourOwnPrefix 를 보면 Cocoa community 의 수많은 개발자가 자신이 선택한 고유한 접두사를 기록해놓은 것을 볼 수 있습니다.

    Cocoa 프레임워크는 NeXTSTEP 운영체제용 앱을 만들기 위한 코드로부터 시작되었습니다. 1996년 애플이 다시 NeXT 를 인수했을 때 기존 클래스 이름을 포함하여 NeXTSTEP 의 라이브러리인 Foundation 과 AppKit 이 OS X 에 통합되었습니다(애플의 Cocoa 프레임워크에서는 현재까지도 같은 이름을 사용 중입니다). 이때 NeXTSTEP 의 개발자들은 앞서 설명한 충돌을 피하기 위한 접두사를 이름 앞에 추가하였는데, 이것이 바로 NS 입니다.

  • NS 접두사가 붙어있는 타입들은 Swift 가 나오기 전 Objective-C 에서 사용되었던 타입들입니다. Working with Foundation Types 를 보면 알 수 있듯이 현재는 대부분의 NS 타입들이 Swift 의 타입들로 Bridge 되어 있어 Swift 의 타입들을 많이 사용하지만, NS 타입만의 고유한 특성을 활용하기 위해 NS 타입을 사용하기도 합니다.

참고할 만한 비슷한 질문들


Q.

guard 와 if 의 차이점이 무엇인가요?

guard 를 사용해 조건문을 작성하면 if 를 사용할 때와 어떤 차이가 있나요?

질문 바로가기

A.

  • 먼저 if 를 사용한 코드입니다.

    func foo(x: Int?) {
        if let x = x where x > 0 {
            // 조건을 만족했을 때 실행할 코드를 이곳에 작성합니다.
        } else {
            // 조건을 만족하지 못했을 때 실행할 코드를 이곳에 작성합니다.
        }
        // 이곳에 작성하는 코드는 위 조건과 관계없이 실행되게 됩니다.
    }

    if 안에 조건을 만족했을 때 실행할 코드들을 모두 작성하게 됩니다. if 블록을 벗어나면 옵셔널 바인딩 된 x 는 사용할 수 없습니다.

    guard 와는 달리 if 밖에서 조건과 관계없이 실행되는 코드를 작성할 수 있습니다.

  • guard 를 사용한 코드입니다.

    func foo(x: Int?) {
        guard let x = x where x > 0 else {
            // 조건을 만족하지 못했을 때 실행할 코드를 이곳에 작성합니다.
            return
        }
    
        // 조건을 만족했을 때 실행할 코드를 이곳에 작성합니다.
    }

    조건을 만족하지 않으면 else 문이 실행되어 else 문 안의 코드를 실행하고 함수를 종료합니다. guard 를 사용하면 조건을 만족하지 않을 땐 항상 continue, break, return 등을 사용하여 guard 가 선언된 스코프를 빠져나가야 합니다.

    조건을 만족하면 현재 함수 내 guard 문이 실행된 이후의 모든 범위에서 옵셔널 바인딩 한 x 를 사용할 수 있습니다.

  • 몇가지 팁을 드리자면, if 안에 스코프를 빠져나가는 코드가 있는 경우에는 guard 로 바꾸는 것이 좋습니다. 예외처리를 할 때도 guard 를 사용하면 좀 더 명시적인 예외처리가 가능합니다. if 가 여러개 중첩되어 코드 줄바꿈의 깊이가 깊어졌을 때도 guard 를 사용하면 깊이를 줄이고 가독성을 향상시킬 수 있습니다.

    func isZero(x: String) -> Bool? {
        if let x = Int(x) {
            if x == 0 {
                return true
            } else {
                return false
            }
        } else {
            return nil
        }
    }
    func isZero(x: String) -> Bool? {
        guard let x = Int(x) else { return nil }
        guard x == 0 else { return false }
        return true
    }

    String 을 인자로 받아 Int 로 변환하고, 그 값이 0 인지 아닌지 확인하는 함수입니다. 인자로 받은 문자열이 숫자가 아니면 nil 을 반환하고 0이면 true, 0이 아니면 false 를 반환합니다. if 를 사용해서 구현한 함수보다 guard 를 사용한 함수가 코드의 깊이도 얕고, 어떤 때에 어떤 값을 반환하는지 좀 더 명확하게 알 수 있는 것을 확인할 수 있습니다.

  • if 보다 guard 를 사용했을 때 더 좋은 상황이 많지만, if 를 사용해야만 하는 상황도 있으므로 위의 특징들을 참고해서 본인이 작성한 코드의 상황에 맞게 사용하시면 됩니다.

참고할 만한 비슷한 질문들