암묵적 언랩 옵셔널 타입이 함수의 인자로 오는 경우 (Swift)

간혹 T! 타입이 함수의 인자로 들어가는 경우를 종종 볼 때가 있다. 주로 C나 Objective-C 라이브러리를 사용할 때, 이런 경우를 볼 수 있었다. 특정 연산의 결과를 T! 타입으로 미리 선언하는 것은 그럴 수 있다 하겠는데, 함수의 인자라면 호출하는 곳의 관점으로는 옵셔널이거나 아니면 옵셔널이 아니거나 둘 중 하나일 것인데 왜 이런 시그니쳐가 보이는 것일까?

결론부터 이야기하면 Objective-C 의 언어적 한계 때문이다. 임의의 클래스의 객체를 받는 인터페이스가 있다고 하자. Objective-C에서 객체를 가리킬 수 있는 모든 변수 타입에는 nil이 들어갈 수 있고, nil에 어떤 메시지를 보내는 것은 아무런 일도 일어나지 않지만 Objective-C 에서는 문법적으로 합당한 행위이다. 따라서 모든 Objective-C 객체 타입은 Swift의 입장에서 보면 옵셔널인데, 정작 Objective-C 문법은 별도로 옵셔널을 지원하지 않는데. 이러한 차이에서 Swift 컴파일러는 Objective-C API를 반입할 때, T? 타입일 수 있을 값을 T! 로 바꿔서 표시해준다.

물론 사용하는 Swift 코드의 입장에서는 이러한 API를 호출할 때에는 T? 타입의 옵셔널이든 T 타입의 객체값이든 어떤 것을 넘겨도 동작에는 상관없다.

참고로 Objective-C에서 nullable, nonnull 어노테이션이 추가되면서 많은 API에서 이러한 표현은 제거되었고, 실제 옵셔널이 필요한 부분에서는 T? 타입을, 그렇지 않은 부분에서는 T 타입을 받도록 업데이트되어 있다.

arc4random

전통적인 C 함수로 srandome, rand를 이용해서 난수를 생성하는 방법이 있는데, 보다 진보된(?)형태의 함수로 arc4random 함수가 있다. 이 역시 표준 C 라이브러리(libc)에 탑재되어 있다. (stdlib.h에 선언됨)

u_int32_t arc4random(void);

이 함수는 32비트 범위값 내에서 정수의 형태로 난수를 생성하며, rand(), randome() 함수에 비해 두 배의 범위를 가진다. 게다가 seed 값을 미리 정의해줄 필요가 없다.

Swift에서도 난수를 만들기 위해서는 이 함수를 쓰는 것을 추천한다. arc4random 더보기

Swift – Interacting with C Pointers

https://developer.apple.com/swift/blog/?id=6

Objective-C 및 C의 API들은 종종 포인터를 사용한다. Swift의 데이터 타입들은 포인터 기반의 Cocoa API들과 자연스럽게 어울리도록 디자인되었고, Swift는 포인터를 파라미터로 일부 다루고 있다.

포인터와 in/out 파라미터

C와 Objective-C의 함수는 복수의 값을 리턴하지 못하기 때문에 부가정보를 함수 외부로 내보내기 위해서 포인터를 사용한다. Swift는 이런 경우 inout 어트리뷰트를 가진 파라미터를 정의할 수 있어서 Swift에서는 & 문법을 사용하여 var 변수의 포인터를 넘겨줄 수 있다. 예를 들어 UIColorgetRed(_:green:blue:alpha:) 메소드는 4개의 CGFloat* 포인터를 받는데 이는 다음과 같이 사용하여 4개의 변수에 대해 각 컬러 값을 얻어낼 수 있다. Swift – Interacting with C Pointers 더보기

Swift 타입으로 변형되는 C 타입들

Swift와 C의 데이터타입 호환

Swift는 기본적인 C 포인터 타입에 대해서는 내부적으로 자동으로 변환을 하게 된다. 예를 들어 const char * 타입의 인자를 받는 함수에는 Swift 문자열을 그대로 넣으면 된다. (이는 해당 C 라이브러리를 import 하는 과정에서 Swift가 C 함수의 인자 타입을 자동으로 변환해준다.) 그 외의 임의 포인터를 사용하는 함수라든지, C 포인터 데이터 타입을 Swift 코드에서 사용해야 하는 경우에는 각 포인터 타입을 Swift 타입으로 사용할 수 있다. 이미 이러한 예는 이전에 다룬 Swift에서 Sqlite 사용하기에서 다루고 있다. Swift 타입으로 변형되는 C 타입들 더보기

C로 간단한 TODO앱을 구현해보자.

C로 구현하는 간단한 Todo List 관리 앱

구조체 정보를 디스크에 기록하는 부분과 관련하여 두어개의 글을 쓴 적이 있는데, 오늘은 그 최종정리 편으로, C로 구현하는 간단한 TodoList 관리 앱을 만들어보도록 하겠다. 이 앱의 스펙은 다음과 같다.

  1. 각 할일은 구조체의 포인터를 사용, 객체처럼 다룰 수 있게 한다.
  2. 파일에 읽고 쓰는 것은 일련의 데이터 시퀀스를 저장하는 것이므로, 할일 목록 객체를 추가한다. 할일 목록 객체는 100개의 할일을 담을 수 있도록 한다.
    C로 간단한 TODO앱을 구현해보자. 더보기