주희하세요!

[면접질문] iOS 관련 질문

2019-03-16
Juhee Kim

안녕하세요! caution입니다. 면접 질문~ 두 번째~~ iOS 관련 질답을 대략적으로 정리해보고자 합니다. 간략하게 Q - A 정도로 작성할게요!

Q. bound와 frame의 차이점을 설명하세요.

bound와 frame 모두 해당 주체의 너비, 높이와 위치 좌표 값(x,y)를 나타냅니다. 다만 frame부모 뷰의 좌표시스템에서 자신의 위치를 나타내고, bound자신의 내부 좌표 시스템을 사용하여 위치를 나타냅니다. frame의 x, y 좌표를 변경하게 되면 자기 자신의 위치가 변경되지만 bound의 x,y 좌표를 변경하면 자신이 포함하는 하위 뷰들의 위치가 옮겨지게 됩니다.

Q. Foundation Kit은 무엇이고 어떤 클래스들이 포함되어있는지 설명하세요.

Foundation Kit은 Cocoa Touch framework에 포함되어 있는 프레임워크 중 하나입니다. String, Int 등의 원시 데이터 타입과 컬렉션 타입 및 운영체제 서비스를 사용해 앱의 기본적인 기능을 관리하는 프레임워크입니다.

Q. Cocoa Framework와 Cocoa Touch Framework의 차이는 무엇인가요?

Cocoa 는 Object-C 런타임을 기반으로 하고 NSObject를 상속받는 모든 클래스 또는 객체를 가리킵니다.

  • Cocoa framework는 macOS를 개발할 때 사용합니다.
  • Cocoa Touch Framework는 iOS 앱을 개발할 때 필수 프레임워크인 UIKit을 포함하며 iOS 개발에 필요한 Foundation, Coredata, MapKit, CoreAnimation 등을 포함합니다.

iOS 앱을 만들고 User Interface를 구성하는데 필수적인 프레임워크는 무엇인가요?

UIKit 입니다.

Q.두 개의 UIVIewController간 화면 전환이 이루어질 때의 시나리오를 UIVIewController life cycle과 관련해서 설명해주세요.

  1. UIVIewController A를 띄운다.
    • loadView : viewController의 최상위 view를 로드합니다. 이 메소드를 override하면 기본 뷰를 교체할 수 있습니다. 만약 전체 뷰가 웹뷰여야 한다면 이 메소드에서 교체할 수 있겠죠!?
    • viewDidLoad
    • viewWillAppear
    • viewDidAppear
  2. UIVIewController B로 화면을 이동한다.
    • A.viewWillDisappear : 사라질꺼야
    • B.viewDidLoad : 뷰 로드했어
    • B.viewWillAppear : 뷰 보일 준비 됐어
    • A.viewdidDisappear : 뷰 사라졌어
    • B.viewDidAppear : 뷰 떴어!

사라질거야 > 로드했어 > 보일거야 > 사라졌어 > 보였다!

Q.뷰의 위치나 크기를 재조정하려면 어떻게 해야하나요?

viewWillLayoutSubviews()와 viewDidLayoutSubviews()

ViewController의 bounds가 변경되어 뷰의 서브 뷰의 위치를 재조정해야 할 때, 다음과 같은 순서로 메서드가 호출됩니다.

  • viewWillLayoutSubviews() : 뷰의 bounds가 변경되면, 뷰는 하위뷰의 레이아웃을 변경해야 하는데 그 작업을 하기전에 호출되는 메서드입니다.
  • layoutSubViews() : 여기서 서브 뷰의 레이아웃을 조정해줍니다.
  • viewDidLayoutSubviews() : 뷰의 bounds가 변경되면, 서브뷰들의 위치를 조정하고 나서 그 때 시스템이 이 메서드를 호출합니다. 그러나 일반적으로 서브뷰의 개별 레이아웃이 조정되기만 했을 때에는 호출되지 않습니다.

view의 위치나 크기를 조정해야 한다면 viewDidLayoutSubviews()에서 조정해야합니다. 왜냐하면 layoutSubViews()가 호출되기 이전에는 frame과 bound가 정확하지 않기 때문입니다.

그렇다면 뷰를 업데이트하기 위해서는 결론적으로 layoutSubViews()가 호출되게 해야하는데요, 이를 직접적으로 호출하면 안됩니다. 대신에 다음 Rendering Cycle에 다시 레이아웃해야한다는 것을 알려주기 위해서 setNeedsLayout() 메서드를 호출합니다. 만약 뷰의 레이아웃을 즉시 업데이트 해야 한다면 layoutIfNeeded()를 사용합니다.

setNeedsLayout()

layoutSubviews() 예약하는 행위 중 가장 비용이 적게 드는 방법이 setNeedsLayout()을 호출하는 것입니다. 이 메소드를 호출한 View는 재계산되어야 하는 View라고 수동으로 체크가 되며 update cycle에서 layoutSubviews()가 호출되게 됩니다.

이 메소드는 비동기적으로 작동하기 때문에 호출되고 바로 반환됩니다. 그리고 View의 보여지는 모습은 update cycle에 들어갔을 때 바뀌게 됩니다.

layoutIfNeeded()

이 메소드는 setNeedsLayout()과 같이 수동으로 layoutSubviews() 호출을 예약하는 행위이지만 update cycle이 올 때까지 기다리지 않고 layoutSubviews()를 호출시키는 것이 아니라 그 즉시 layoutSubviews()를 발동시키는 메소드입니다.

만일 main run loop에서 하나의 View가 setNeedsLayout()을 호출하고 그 다음 layoutIfNeeded()를 호출한다면 layoutIfNeeded()는 그 즉시 View의 값이 재계산되고 화면에 반영하기 때문에 setNeedsLayout()이 예약한 layoutSubViews() 메소드는 update cycle에서 반영해야할 변경된 값이 존재하지 않기 때문에 호출되지 않습니다(결론적으로 한 번만 호출됩니다).

이러한 동작 원리로 layoutIfNeeded() 그 즉시 값이 변경되어야 하는 애니매이션에서 많이 사용됩니다. 만일 setNeedsLayout을 사용한다면 애니매이션 블록에서 그 즉시 View의 값이 변경되는 것이 아니라 추후 update cycle에서 값이 반영되므로 값의 변경은 이루어지지만 애니매이션 효과는 볼 수 없는 것입니다.

setNeedsLayout과 layoutIfNeeded의 차이점은 동기적으로 동작하느냐 비동기적으로 동작하느냐의 차이입니다.

Q. Delegate Pattern과 Notification의 동작 방식의 차이에 대해 설명하세요.

Delegate Pattern이란 필요한 동작들을 Protocol로 정의해 놓고, 어떤 작업이 필요할 때 위임자 인스턴스에게 protocol에 정의된 method들을 호출함으로써 작업을 위임하는 방식을 말합니다. 이 패턴의 장점은 위임자가 어떤 동작을 하는지, 혹은 위임자가 어떤 형태인지 알 필요 없이 그저 필요한 시점에 필요한 메소드를 호출하도록 설계함으로써 관심사를 분리할 수 있습니다. 예를 들어 흔히 사용하는 UITableView는 UITableViewDataSource protocol을 채택한 위임자를 가집니다. TableView를 그리기 위해 데이터가 필요하다면 UITableView는 Datasource 위임자에게 요청함 수 있습니다. 이러한 방식을 통해서 매번 UITableView를 커스텀할 필요 없이 같은 UITableView로 다른 모양과 다른 동작을 가지는 TableView를 구현할 수 있습니다.

Notification은 특정 이벤트가 발생했을 때 사전에 등록된 Notification 이름으로 알림이 발생했다는 것을 Notification Center에게 알려줍니다. 그럼 Notification Center는 해당 알림을 수신하겠다고 등록되어있는 곳에 다시 알려주는 방식입니다.

둘의 차이는 Delegate Pattern은 알림을 발생시키는 주체와 그에 대응하는 위임자가 1:1로 소통한다는 것이고, Notification은 1:N로 하나의 알림을 여러 주체가 받을 수 있습니다. 그렇기 때문에 Notification을 사용할 때 의도하지 않은 곳에서 알림을 수신하고 있는 지 주의해야합니다.

Q. Code로 Autolayout을 작성할 수 있는 방법

  1. Anchor를 사용한다.
    thumbImageView.leftAnchor.constraint(equalTo: leftAnchor, constant: 5).isActive = true
    
  2. NSLayoutConstraints를 사용한다.
    NSLayoutConstraint(item: myView, attribute: .leading, relatedBy: .Equal, toItem: view, attribute: .leadingMargin, multiplier: 1.0, constant: 0.0).isActive = true
    
  3. 비주얼 포맷 사용하기
let views = ["redView": redView,
             "blueView": blueView,
             "greenView": greenView]

let format1 = "V:|-[redView]-8-[greenView]-|"
let format2 = "H:|-[redView]-8-[blueView(==redView)]-|"
let format3 = "H:|-[greenView]-|"

var constraints = NSConstraint.constraints(withVisualFormat: format1,
                    options: alignAllLeft,
                    matrics: nil,
                    views: views)
constraints += NSConstraint.constraints(withVisualFormat: format2,
                    options: alignAllTop,
                    matrics: nil,
                    views: views)
constraints += NSConstraint.constraints(withVisualFormat: format3,
                    options: []
                    matrics: nil,
                    views: views)
NSConstraint.activateConstraints(constraints)
비주얼 포맷의 장점
  • 오토레이아웃의 디버깅은 콘솔을 통해 비주얼 포맷을 사용하여 출력한다. 따라서 디버깅시에 사용되는 포맷과 생성에 사용하는 포맷이 일치한다.
  • 비주얼 포맷을 사용하면 여러 제약 요소를 한 번에 만들 수 있다.
  • 유효한 제약요소들만이 만들어진다. (단, 모든 필요한 제약요소가 다 만들어지는 것은 아니다.)
  • 완전성보다는 좋은 시각화에 집중한 방식이다. 따라서 일부 제약요소는 이 방식으로 만들 수 없다.
  • 단 포맷은 컴파일 타임에 체크할 수 없다. 실행하여 확인할 수만 있다.

Q. Layer 가 무엇인가요?

뷰는 이미지, 비디오, 글자들을 보여주는 객체이며 터치, 제스쳐 등의 이벤트를 받을 수 있습니다. (UIResponser) UIView는 렌더링, 레이아웃, 애니메이션 등을 관리하는 Core Animation Class인 CALayer가 있습니다. UIView와는 유사하지만 뷰의 비쥬얼적인 특성만을 가집니다. CALayer를 사용하면 shadow, rounded corner, colored border나 masking contents, Animation 등의 기능을 사용할 수 있습니다. 예를 들어 실제 뷰는 UIView이지만 layer단에 보여줄 image를 설정할 수 있습니다.

let image = UIImage(named: "temp")
view.layer.contents = image.cgImage

clipsToBounds() vs masksToBounds()

컨텐츠가 뷰의 크기를 벗어나지 않게 하기 위해서 view.clipsToBounds()를 사용합니다. 이와 비슷한 동작을 하는 메소드가 CALayer에는 masksToBounds()입니다.

만약 이미지는 rounded corner를 주고 싶고, 또 view의 shadow 효과도 주고 싶다면 어떻게 해야 할까요? layer는 view에 여러 곂으로 곂칠 수 있기 때문에, image를 rounded corner로 변경하고 masksToBounds()를 적용한 layer 하위에 shadow를 주는 layer를 추가하면 되지 않을까요?

UIButton이 상속받는 것들

image image UIControl과 NSCoding을 상속받는다. UIControl은 UIView를 상속받는다.

CGFloat과 Float의 차이

CGFloat는 CPU가 34bit 기반인지 64bit 기반인지에 따라 Float 혹은 Double입니다. Cocoa의 그래픽 API는 항상 CGFloat을 사용하기 때문에 그래픽 작업을 할 때에는 CGFloat을 사용해야 합니다. 그렇기 때문에 CGFloat으로 변환할 때에는 반드지 CGFloat(float), CGFloat(double)을 사용해야 합니다.

Array vs NSArray

Swift에서 Array는 구조체인 값 타입입니다. NSArray는 immutable한 Object-C 클래스로, Swift에서는 참조타입이며 Array로 브릿징됩니다. NSMutableArray는 NSArray의 변경 가능한 하위 클래스입니다.

참조


Similar Posts

Comments