제가 만들고 있는 앱은 Mac에서 일본어 단어를 입력하고 iPhone에서 해당 단어들을 학습하는 앱입니다. 물론 2개의 프로젝트를 만들어서 서버만 공유해도 해당 기능을 구현할 수 있겠지만 저는 하나의 프로젝트로 2개의 OS에서 돌아가는 앱을 구현하고자 합니다.
전처리문을 통해서 하나의 프로젝트에서 구현하게 되면 MacOS와 iOS에서 중복해서 사용되는 코드 (예를 들면 단어 데이터의 Model)을 한번만 선언해서 사용할 수 있는 장점이 있습니다.
Preprocessor statement는 컴파일 단계에서 컴파일러에게 특정 조건을 만족할 때만 컴파일하도록 하는 코드입니다.
os나 swift 버전, 빌드 타겟에 따라 다르게 컴파일 할 수 있도록 해줍니다.
아래에서 예시를 통해서 전처리문을 통해서 어떻게 하나의 코드로 macOS용 앱과 iOS용 앱을 동시에 만들 수 있는지 알아봅시다.
아래는 전처리문을 통해서 각각 다른 View를 보여주도록 작성한 코드입니다. os가 iOS인 경우 HomeView를 os가 macOS일 경우 MacHomeView를 각각 컴파일 합니다.
import SwiftUI
struct ContentView: View {
var body: some View {
Group {
#if os(iOS)
HomeView()
#elseif os(macOS)
MacHomeView()
#endif
}
}
}
아래 코드는 단어를 저장할 때 사용하는 WordInput이라는 구조체를 선언하는 코드입니다. WordInput안에는 이미지를 저장하는 property가 존재하는데요.
os별로 iOS에서는 UIKit에 있는 UIImage라는 타입을 사용하고 macOS에서는 Cocoa에 있는 NSImage를 사용해서 이미지를 저장합니다.
이때 각각의 os마다 구조체를 따로 선언하면 코드의 중복이 너무 많겠죠? typealias를 같은 이름으로 선언해주면 중복 없이 필요한 타입을 지정할 수 있습니다.
아래의 동일한 구조체를 활용해서 macOS와 iOS에서 모두 단어를 서버에 저장할 수 있습니다!
#if os(iOS)
import UIKit
typealias InputImageType = UIImage
#elseif os(macOS)
import Cocoa
typealias InputImageType = NSImage
#endif
struct WordInput {
let frontText: String
let frontImage: InputImageType?
let backText: String
let backImage: InputImageType?
let studyState: StudyState = .undefined
let timestamp: Timestamp = Timestamp(date: Date())
}