Opaque 리턴타입(Swift 5.1)

이 글을 다음 문서를 부분 번역한 것입니다.
https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html

Opaque 리턴 타입이 있는 함수나 메소드는 리턴 값에 대한 정보를 숨깁니다. 함수의 리턴 타입에 대한 구체적인 타입 정보를 제시하는 대신에, 리턴 값은 그 것이 따르는 프로토콜만으로 기술됩니다. 타입 정보를 숨기는 것은 모듈이 외부에 내놓는 코드에서 실제 리턴값의 타입은 내부에서만 유지관리될 수 있게 만들기 때문에 유용하게 사용될 수 있습니다. 리턴 값의 타입이 프로토콜 타입인 것과는 달리 Opaque 타입은 동일성을 유지합니다. 그리고 이때 컴파일러는 타입 정보에 액세스할 수 있지만, 모듈의 클라이언트는 그렇게 할 수 없습니다.

Opaque 리턴타입(Swift 5.1) 더보기

Swift 프로퍼티의 옵저버에 대한 규칙

  • lazy 프로퍼티는 옵저버를 가질 수 없다. (단 최초 액세스 이후 변경하는 것은 가능하다.)
  • computed 프로퍼티에 대해서는 옵저버를 설치하는 것이 의미가 없다. 단 상속받은 computed 프로퍼티에 대해서는 옵저버를 설치할 수 있다.
  • 옵저버는 해당 클래스의 지정 이니셜라이저 내에서 값을 변경하는 경우에는 호출되지 않는다.
  • 단, 상속받은 프로퍼티가 옵저버가 설치되어 있다면 부모의 지정 이니셜라이저 호출 후에 변경한다면, 부모의 옵저버가 호출될 것이다.
  • 비슷하게 편의 이니셜라이저에서는 지정 이니셜라이저를 통해 초기화한 후, 프로퍼티값을 다시 변경하면 옵저버가 실행된다.

lazy 프로퍼티와 옵저버

lazy 프로퍼티는 옵저버를 가질 수 없다. 위에서 설명한 옵저버와 관련된 규칙들을 살펴보면, 다음과 같은 가설을 세울 수 있다. 1) 옵저버는 객체 인스턴스의 초기화가 완료된 시점부터 작동한다. 2) 객체의 초기화는 지정 이니셜라이저가 실행을 완료한 시점으로 본다.

그런데 lazy 프로퍼티는 약간 예외적이다. 왜냐하면 지정이니셜라이저가 실행을 완료했다하더라도 느긋하게 초기화되는 프로퍼티는 아직 초기화 되기 전이기 때문이다. 따라서 위 가설에서 1번 항목에 따라 지정 이니셜라이저가 실행되었더라도 옵저버가 동작 가능한 시점이 결정되지 않는다. 아래는 이 부분이 언급된 공식 문서의 내용.


You can add property observers to any stored properties you define, except for lazy stored properties. You can also add property observers to any inherited property (whether stored or computed) by overriding the property within a subclass. You don’t need to define property observers for nonoverridden computed properties, because you can observe and respond to changes to their value in the computed property’s setter. Property overriding is described in Overriding.

상속된 계산 프로퍼티에는 옵저버 설치가 가능하다?

보통 옵저버는 저장 프로퍼티에 설치한다. 계산 프로퍼티의 경우에는 set 하는 과정 자체가 별도의 코드를 실행하는 것이므로 사실상 옵저버가 필요 없다. 하지만 이렇게 set이 가능한 계산 프로퍼티에 대해서 이를 상속받는 서브 클래스는 해당 프로퍼티를 오버라이드하여 didSet, willSet 옵저버만 추가하는 것이 가능하다. (당연히 setter를 오버라이드하는 경우에는 옵저버를 추가할 수 없다.)

코코아바인딩에서 집합 타입의 프로퍼티를 연결할 때 유의할 점

코코아 바인딩을 사용할 때 특정한 키 이름이 변경가능한 배열(NSMutableArray)일 때, UI를 통해 값을 추가/제거하거나 변경한다 하더라도 이러한 변경이 원래 데이터에 반영되지 않는 문제가 발생하는 경우가 있다.

원문 : 코코아 바인딩 문제해결(Troubleshooting Cocoa Bindings)
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CocoaBindings/Concepts/Troubleshooting.html

집합 컨트롤러가 현재 데이터를 표시하지 않아요.

“이러한 문제는 보통 여러분의 애플리케이션이 집합 콘텐츠를 키-밸류 옵저빙 호환 방식으로 데이터를 변경하지 않기 때문에 일어납니다. 배열을 addObject:removeObject: 로 제거하는 것만으로는 부족합니다.”

코코아바인딩에서 집합 타입의 프로퍼티를 연결할 때 유의할 점 더보기

Asyncio를 사용한 비동기 소켓 통신

이 블로그에서는 파이썬으로 소켓 통신을 구현하는 몇 가지 방법을 이미 살펴본 바 있습니다. 원시 소켓인 socket.socket을 사용하는 방법zmq의 REQ-REP 패턴을 사용한 방법이 있었고, 다중 접속을 허용하도록 스레드를 통해 처리하거나, 셀렉터를 사용하여 단일 스레드에서 멀티플렉싱하는 방법도 알아보았습니다. 이번 글에서는 asyncio에서는 과연 소켓 통신을 어떤식으로 구현하는지 살펴보고 역시나 간단한 비동기 다중 접속 에코 서버를 구현하는 과정을 함께 살펴보겠습니다.

Asyncio를 사용한 비동기 소켓 통신 더보기

Raw 포인터 사용에 대해

https://developer.apple.com/documentation/swift/unsaferawpointer

UnsafeRawPointer 타입은 자동 메모리 관리, 타입 안정성 및 메모리 정렬 보장이 되지 않는 원시 포인터 액세스를 제공합니다. 이 타입을 사용하려면 누수를 피하고, 할당된 메모리의 라이프 사이클을 직접 관리해야 하며, 그 외의 정의되지 않는 동작들을 회피해야 합니다. 수동으로 직접 관리하는 메모리 영역은 특정한 타입에 바운드되거나, 타입이 지정되지 않을 수도 있습니다. 메모리 영역에서 해당 영역이 특정 타입에 묶여있는지 여부와 무관하게 순수 바이트를 액세스하려할 때 UnsafeRawPointer 타입을 사용할 수 있습니다.

막 할당된 Raw 메모리는 타입화되지도 초기화되지도 않은 상태입니다. 이 메모리는 타입화된 연산을 사용하기 전에 반드시 초기화되어야 합니다. (초기화되려면 초기값을 가져야하고, 이는 타입화를 수반해야한다는 의미가 됩니다.) 초기화되지 않은 상태에서 특정 타입에 바인등하려면 bindMemory(to: count:)를 사용합니다. 이 메소드는 타입화된 포인터를 반환하며, 이후에는 해당 포인터를 사용해야 합니다.

Raw 포인터 사용에 대해 더보기