오늘의 공부(28)

주방·2022년 8월 10일
0

Swift

목록 보기
14/17
post-thumbnail

#1. 학습

1) .nib(feat. awakeFromNIB)

  • .Nib 파일은 무엇인가?
    • nib(Next Interface Builder): 뷰의 layout, display 등의 요소들을 object graph로 만들어서 직렬화한 파일
      • object graph? 객체지향 어플리케이션에서는 연관된 오브젝트끼리 매우 복잡한 관계(web)를 이루고 있다. 오브젝트들은 다른 오브젝트를 소유 또는 포함하거나, 참조를 가지고 있으면서 메세지를 전달한다. 적은 수의 오브젝트 관계만 표현하더라도, 하나의 어플리케이션의 object graph는 개개인의 오브젝트 간 순환 참조를 갖거나 여러개의 연결로 얽혀 구성되어 있다.(Window - > First responder -> Text -> Fomatter)
    • object graph내에 존재한 여러 관계들을 보존한 파일에 저장할 수 있는 형식이나, 다른 프로세스나 기기에 전달할 수 있는 형식으로 변환하고 싶을 때가 있다. 예를 들어 .Nib파일과 Property list는 Object graph를 파일 형태로 저장할 수 있는 수단이다.
    • 인터페이스 빌더에서 구성한 모든 정보는 .xib파일(XML Interface Builder)라는 파일에 저장
    • 프로젝트 컴파일 시 바이너리 파일인 .nib파일이 되는 것이다.
      • 컴파일? print("Hello World!")를 하게 되면 swift 컴파일러(swift 명령)는 사용자가 실행할 수 있는 바이너리 실행파일로 swift 소스파일을 컴파일 할 수 있게 된다.(사람이 있는 코드를 기계코드로 번역한다.)

      • 인터페이스 빌더? 코딩과 상반된 개념인 그래픽 사용자 인터페이스를 말한다.

        이해된 내용 - 처음 사용자가 interface builder에서 정보를 구성했을 때, .xib파일로 저장되며, 컴파일 과정을 통해 컴퓨터가 이해할 수 있는 바이너리 형태인 .nib파일로 전환된다.

    • 앱에 .nib파일이 로드되면 Cocoa는 Xcode에서 만든 객체들의 전체 Object graph를 재생성한다.
    • 메모리에 Nib파일의 컨텐츠와 참조된 모든 리소스 파일를 로드 후(단, 이미지와 사운드는 Cocoa 캐시에 추가) nib Object graph data를 Unarchive하고 객체들을 초기화 시킨다.
    • nib 파일의 객체들 간의 모든 연결(Action, Outlet, Binding)이 재생성되는데, 이때 File's Owner, Placeholder간의 연결도 포함된다.(awakeFromNib)메서드 불려지기 전에 발생한다.
  • .Nib 초기화 관련 메소드
    • awakeFromNib(): nib파일의 내용을 읽어서 object graph를 복원할 때, 모든 복원이 완료된 후 nib 파일 내의 모든 객체가 받게 되는 메세지(IBOutlet등의 참조가 완료됨.)
    • init(nibname: , bundle: ) - nib파일로부터 뷰 컨트롤러를 생성할 때 사용. nib 파일은 로딩안됨.
    • init(coder: ) - nib파일을 읽어들여 그 데이터로부터 뷰 컨트롤러, 내부 뷰 생성할 때 사용
    • prepareForInterfaceBuilder() - IB에서 속성을 변경할 때, 해당 코드가 내부적으로 호출되며 실시간으로 변경된 값을 확인할 수 있는 요소
    • init(frame: ) - nib이 아닌 코드를 통해 객체를 초기화 할 때 layout과 함께 초기화 해주는 코드
  • Placeholder, File's Owner, First Responder
    • Placeholder: 의미 그대로 UIView처럼 보여지는 주요 요소가 아닌 빠져있는 것을 대신해 연결해주는 역할
    • File's Owner 객체: nib파일을 앱코드와 연결시켜주는 객체(nib 파일의 내용을 책임지는 컨트롤로)
      • nib파일을 로드할 때, File's Owner 객체를 보고 지정한 객체를 생성하여 nib파일에서 해당 객체들을 참조할 수 있도록 하는 개념
      • File's Owner객체에서 nib파일에 저장된 top-level 객체의 참조를 유지하기 위해 사용하는 것이 @IBOutlet이다.
    • First Responder 객체: Responder객체가 이벤트를 받으면 이를 처리하거나 다른 Responder 객체에게 처리할 수 있도록 넘겨야 할 의무가 존재한다. UIKit은 적절한 Responder를 지정해서 이벤트를 넘겨 처리하는데, 처음으로 이벤트 받은 Responder를 First Responder로 지칭한다.
    • Responder Chain
      • 앱은 Responder 객체를 사용해 이벤트를 받고, 그 이벤트를 다룬다. Responder 객체는 UIResponder클래스의 인스턴스이며, UIView, UIViewController를 포함하는 서브클래스이다.
      • 앱이 이벤트를 받을 경우 UIKit은 First Responder라고 불리는 적절한 응답자 객체에게 해당 이벤트를 전송한다.
      • UIKIt은 정의된 규칙에 의해 다뤄지지 않은 이벤트들을 Responder 객체인 Responder Chain 에 의해, 이벤트를 처리할 수 있는 Responder가 나올 때까지 Responder끼리 전달한다.
      • [UILabel, UITextField, UIButton] => [UIVIew] => [UIViewController] => [UIWindow] => [UIApplication] => [UIApplicationDelegate]

참조 - Object graph

참조 - nib

2) dequeueReusableCell

  • 정의: 지정된 재사용 식별자에 대한 재사용 가능한 테이블 뷰 셀 객체를 반환하고, 이를 테이블에 추가합니다.
  • 테이블을 추가해줄 때 위치를 지정해야 한다. 이때, indexpath를 파라미터로 받아와 지정해주게 된다. 데이터 소스는 셀에 대한 요청이 있을 때 정보를 수선하며 이를 전달한다. 인덱스 경로를 사용해 테이블 뷰에서 셀의 위치를 기반으로 추가 구성을 수행한다.
  • 매번 새로운 위치를 지정해줘야 한다. 굳이 그렇게 할 필요있나? 필요한만큼 생성해버리면 되지 않은가? 생성해줄 수 있지만 데이터의 갯수가 10만개라면?? 이런 방식으로 cell을 모두 생성한다면 메모리 효율성이 매우 떨어지게 될 것이다.
  • 목적: 메모리 낭비를 막기 위해서 사용된다.
  • 과정
    • top cell is pushed out of table view visible areaplaced inside queuetaken out of queuesent to prepareForReusein prepareForReuse() // 해당 과정을 통해서 tableview의 delegate가 셀을 재사용할 수 있도록 돕는다.sent to cellForRowAt for customizationcellForRowAt indexPathcustomized cell is placed to the bottom of table view
  • 테이블뷰에서 위로 스크롤 되어 화면이 사라지는 셀들을 큐로 들어가고, 큐의 font에 있는 셀이 화면 하단에서 올라와 화면에 보여지는 셀로 사용된다.
  • 만약 prepareForReuse()사용하지 않는다면, 셀이 큐에 들어갔다가 indexPath.row에 따라 재사용되면 데이터는 바뀌어있겠지만, 뷰 자체는 이미 사용된 상태이기 때문에 이전 뷰상태에 나올 것이다. 그래서 prepareForReuse를 통해 처음처럼 비워내야 한다.

3) reloadData()

  • 특징
    • 해당 메소드의 경우 호출시 보여지는 rows값들에 대해서만 레이아웃이 변경된다.
    • collectionView, tableView의 view를 다시 그린다.
  • 동작
    • numberOfItemsInSection 메서드에서 Cell의 갯수를 결정
    • cellForItemAt 메서드에서 cell을 화면에 보여질만큼의 셀을 생성

4) @escaping(탈출 클로져)

  • 함수형 프로그래밍
    • 자료 처리를 수학적 함수의 계산으로 취급하고 상태와 가변 데이터를 멀리한다.
  • 함수형 프로래밍의 특징
    • 순수함수가. 동일한 입력에 항상 값을 반화해야 하는 함수나. 함수의 실행이 프로그램의 실행에 영향을 미치지 않아야 하는 함수다. 함수 내부에서 인자의 값을 변경하거나 프로그램 상태를 변경하는 Side Effect가 없는 것비상태, 불변성(stateless, Immutability)가. 함수형 프로그래밍에서의 데이터는 변하지 않는 불변성을 유지해야 한다.나. 데이터의 변경이 필요한 경우, 원본 데이터 구조를 변경하지 않고, 그데이터 복사본을 만들어서 그 일부를 변경하고, 변경된 복사본을 사용해 작업을 진행한다.1급객체와 고차함수가. 변수나 데이터 구조안에 담을 수 있다.나. 파라미터로 전달할 수 있음.다. 반환 값(return value)으로 사용할 수 있다.라. 할당에 사용된 이름과 관계없이 고유한 구별이 가능하다.마. 동적으로 프로퍼티 할당이 가능하다.바. 함수를 인자로써 전달할 수 있어야 한다.사. 함수의 반환 값으로 또 다른 함수를 사용할 수 있다.
  • 클로져?
    • 어떤 기능을 하는 코드를 하나의 블럭으로 모아놓은 것을 말한다.

      {(매개변수) -> 반환타입 in
          코드블럭
      }
    • 클로저를 매개변수 중 하나로 사용하는 함수를 선언할 때, 매개변수 유형 앞에 @escaping을 작성하여 클로저가 탈출하도록 나타낼 수 있다. 어떻게? 클로저를 변수에 저장한다. 언제 사용할까? 비동기 작업을 시작하는 많은 함수는 클로저 인수를 completion handler로 사용한다. 함수는 작업을 시작하고 나서 return하지만, 클로저는 작업이 완료되기전까지 불리지 않는다. 클로저는 탈출해야 하고 나중에 호출된다.

      • 매개변수(parameter): 함수를 정의할 때 외부로부터 받아들이는 임의의 값을 의미
      • 인수(Argument): 함수를 호출할 때 사용되는 값
    • 클로저가 함수로부터 escape한다는 것은 해당 함수의 인자로 클로저가 전달되지만, 함수가 반환된 다음에 실행되는 것을 의미한다. (q. 반환된 다음에 실행되는 것은 어떤 차이가 있길래 그렇게 사용하는 것일까?) 함수의 인자가 함수의 영역을 탈출하여 함수 밖에서 사용할 수 있는 개념은 기존에 우리가 알 고 있던 변수의 scope 개념을 무시한다. (a. 아, 우리는 어떤 함수나 값을 쓰려면 해당 scope안에서만 출력이 되는 한계가 있었다. 코딩하다 몇번 불편했던 기억이 있는데,,,세부 예시는 생각이 안나네. 그러면 안에서 함수를 호출하면, 그 호출된 함수로 넘어가서 거기서 코드 진행이 된다. 유용하게 쓸 수 있을 것 같은데?) 특히나 클로저의. excaping은 a함수가 무조건 마무리 되어야 하기 때문에 함수 진행의 순서를 할 수 있게 된다.

    • 엥? 함수 진행의 순서를 제공하는 건 또 무슨 이득이 있지? 이 순서를 보장하면 네트워크에서 데이터를 받아오고 표시할 때 굉장히 유용하다. 우리가 서버 api를 활용해 데이터를 받아오는데, 받아올 때마다 어땠어? 순서가 뒤죽박죽이잖아. 그런데 그것에 대한 순서를 정할 수 있지 않을까? 맞네. 그렇네. 네트워크에서 서버에서 request하여 데이터를 받아올 때, 주로 Alamofire를 쓴다. Alamofire로 request하면 get 방식으로 Json형식의 데이터를 받아온다. 그 결과는 response 객체로 받아오는데, request결과를 기다리고 있다. 엥?? 어떻게 ???? 바로 탈출 클로저이기 때문이다. 끝나야 실행이 된다. 알겠지? 끝나야 실행되는 이점이 아주 특징적이다. 또 responseJSON(queue: options: completionHandler: )에서 queue, options은 기본값이 지정되어 값을 주지 않아도 작동하지만, CompletionHandler는 다르다. 이 친구의 형태는 @escaping() -> (void) 탈출 클로저를 사용하고 있다. 그래서 responseJSON의 함수가 반환되고 그 이후에 CompletionHandler가 동작한다.



#3. 회고

  • 오늘은 학습만 하다가 구현은 하지 못했다. 클로져의 필요성은 인지되었지만, 구현이 생각만큼 쉽지 않다. 구현하려고 보니 지금 새벽 1시 30분. 코딩은 새벽코딩이라고 하는데,,,

0개의 댓글