본문 바로가기

Swift

[Swift] 버전 대응 Wrapper

버전 대응 Wrapper

Swift 애플리케이션에서 iOS, macOS 등 특정 플랫폼 버전에 따라 코드를 실행하거나 기능을 활성화해야 하는 경우가 종종 존재.

이러한 요구를 처리하기 위해 버전 대응 Wrapper를 활용하여 코드의 가독성과 재사용성을 높일 수 있음.


1. 기본 버전 조건 처리

Swift는 @available 및 #available 키워드를 사용하여 플랫폼 및 버전 조건을 확인.

if #available(iOS 16, macOS 13, *) {
    print("iOS 16 이상에서 동작")
} else {
    print("이전 버전에서 동작")
}
  • #available: 실행 시점에서 조건 확인.
  • @available: 컴파일 시점에서 사용 가능성을 표시.

예제: 뷰에 버전 따라 다른 스타일 적용

struct ContentView: View {
    var body: some View {
        if #available(iOS 16, *) {
            Text("iOS 16 이상 스타일")
                .font(.largeTitle)
        } else {
            Text("이전 버전 스타일")
                .font(.title)
        }
    }
}

2. 버전 대응 Wrapper 구현

반복적으로 #available을 사용하는 대신, 재사용 가능한 버전 대응 Wrapper를 정의하여 코드 중복을 줄일 수 있음.

struct VersionCompatibility {
    static func ifAvailable<T>(
        execute: () -> T,
        fallback: () -> T
    ) -> T {
        if #available(iOS 16, *) {
            return execute()
        } else {
            return fallback()
        }
    }
}
let label = VersionCompatibility.ifAvailable {
    "iOS 16 기능 사용"
} fallback: {
    "이전 버전 대체 기능"
}

3. View 버전 대응 Wrapper

버전별로 다른 뷰를 반환할 수 있는 Wrapper를 정의.

struct VersionedView<Content: View, Fallback: View>: View {
    @ViewBuilder let content: Content
    @ViewBuilder let fallback: Fallback

    var body: some View {
        if #available(iOS 16, *) {
            content
        } else {
            fallback
        }
    }
}
struct ContentView: View {
    var body: some View {
        VersionedView(
            content: {
                Text("iOS 16 이상에서 보이는 뷰")
                    .font(.largeTitle)
            },
            fallback: {
                Text("이전 버전에서 보이는 뷰")
                    .font(.title)
            }
        )
    }
}

4. 고급 Wrapper: Modifier 기반 처리

UI의 특정 구성 요소에 조건부로 Modifier를 적용할 수도 있음.

struct ForgroundWrapper: ViewModifier {  
    let color: Color
    
    func body(content: Content) -> some View {
        if #available(iOS 15.0, *) {
            content
                .foregroundStyle(color)
        } else {
            content
                .foregroundColor(color)
        }
    }
}

extension View {
    func forground(_ color: Color) -> some View {
        modifier(ForgroundWrapper(color: color))
    }
}
struct ContentView: View {
    var body: some View {
        Text("버전별 Modifier 적용")
            .forground(.white)
    }
}

5. API Wrapper

네트워크 호출이나 기능 구현에서도 플랫폼별 API를 Wrapper로 처리할 수 있음.

struct APIManager {
    static func fetchData() {
        if #available(iOS 16, *) {
            print("iOS 16 API 사용")
            // Use modern API
        } else {
            print("이전 버전 API 사용")
            // Use legacy API
        }
    }
}

6. 버전 대응 Swift Package

Swift Package Manager(SPM)를 사용하여 특정 플랫폼 버전 이상에서만 라이브러리를 활성화할 수도 있음.

let package = Package(
    name: "VersionedLibrary",
    platforms: [
        .iOS("15.0"),
        .macOS("12.0")
    ],
    products: [
        .library(name: "VersionedLibrary", targets: ["VersionedLibrary"])
    ],
    dependencies: [],
    targets: [
        .target(name: "VersionedLibrary", dependencies: [])
    ]
)

7. 선택 가이드

사용 사례 적합한 처리 방법
UI 요소를 버전별로 다르게 표시해야 함 View Wrapper, Modifier Wrapper
API 호출 로직이 버전에 따라 다름 함수 기반 Wrapper 처리
프로젝트 전체에서 일관된 조건을 사용 Static Wrapper 함수
Swift Package에서 버전 조건 설정 Package.swift의 platforms

'Swift' 카테고리의 다른 글

[Swift] @available  (0) 2024.05.19
[Swift] #available  (0) 2024.05.19
[Swift] Property Wrapper  (0) 2024.04.29
[Swift] Opaque Type (some 키워드)  (0) 2024.04.19
[Swift] map  (0) 2024.04.19