ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 특정 버전에 대한 분기 처리하기 (systemVersion)
    iOS 2023. 7. 13. 08:50

    안녕하세요. 그린입니다 🍏

    이번 포스팅에서는 특정 버전에 대한 분기처리하는 방법에 대해 알아보겠습니다 🙋🏻

     

    일단 간단한 포스팅이 될 수도 있을것 같네요ㅎㅎ

     

    분기 처리?

    개발을 하다보면 버전 별로 코드를 다르게 동작시키는 경우가 종종 있습니다.

     

    iOS를 예를들어본다면 iOS 17에서부터 지원되는 Keyframe Animator의 사용을 하고 싶은 경우 현재 프로젝트의 미니멈 타겟은 만약 iOS 15라고 가정해볼께요.

     

    그렇다면 우리는 특정 파일에서 해당 코드를 사용하기 위해 iOS 17 이상에서는 저 동작 그 밑에서는 요 동작 이렇게 분기 처리가 필요하죠? 

     

    자 이럴때 어떻게 처리하면 될까요?

     

    available

    해당 속성을 이용해 버전을 체크하고 분기처리를 할 수 있습니다.

    일단 간단하게 #available과 @available로 사용할 수 있는데요.

     

    #available은 조건문과 같이 사용할 때 사용됩니다.

     

    즉, 아래와 같이 말이죠!

    if #available(iOS 17, *) {
      // 17 이상 버전 코드
    }
    else {
      // 17 미만 버전 코드
    }

    즉, Bool 타입을 반환시켜주니 꼭 조건문과 같이 사용됩니다.

     

    @available은 조건문과 같이 분기 처리를 할 수 없고, 배포 타겟 버전을 체크합니다.

    즉 아래와 같이 보통 클래스, 프로토콜, 메서드 같은 곳에 붙여 사용합니다.

    @available(iOS 17, *)
    func example() { }

    만약 배포 타겟이 17 미만이라면 컴파일 시 에러가 나게 되죠!

     

    우선 available의 간단한 사용은 요정도면 될것 같습니다.
    이후 포스팅에서 이참에 available을 파보면서 싹 한번 정리해볼께요 🕺🏻

     

    자 그러면 돌아와서 우리가 필요한건 특정 버전의 분기 처리 였으니 #available로 분기 처리를 사용해줄 수 있습니다.

     

    근데 하나 생각해보면 이런 케이스는 대처할 수 있을까요?

    iOS 15와 iOS 17에서는 같은 동작 iOS 16에서는 다른 동작을 하도록 말이죠.

    즉 징검다리처럼 분기 처리를 사용할 수 있을까요?

     

    우선, 위 #available을 사용해 가능한지 봐볼께요.

     

    if #available(iOS 15, *) {
      //
    } else if #available(iOS 16, *) {
      //
    } else {
      //
    }

    이런식으로 하면 될까요?

    절대 안되죠... 왜냐면 이미 iOS 15 이상부터라는 *가 포함되었으니 모든 경우가 종료되고 말죠.

    그럼 * 대신에 15.0, 15.9 처럼 넣으면 안될까요?

    안됩니다😭 해당 사용에 있어 그 이상이라는 *는 필수이기에 변경할 수 없죠.

     

    그렇기에 제가 알기론 available을 사용해서 15, 17은 같은 동작을 16은 다른 동작을 하는 코드 분기 처리를 할 수 없습니다 🫠

     

    그럼 방법이 없는걸까요?

     

    찾아낸 방법이 있어요!

     

    UIDevice > systemVersion

    UIKit의 UIDevice 클래스에는 다양한 프로퍼티들이 제공됩니다.

    즉, 현재 빌드되고 있는 디바이스의 정보들을 제공해주죠!

    @MainActor open class UIDevice : NSObject {
        open class var current: UIDevice { get }
        open var name: String { get } // Synonym for model. Prior to iOS 16, user-assigned device name (e.g. @"My iPhone").
        open var model: String { get } // e.g. @"iPhone", @"iPod touch"
        open var localizedModel: String { get } // localized version of model
        open var systemName: String { get } // e.g. @"iOS"
        
        // 🎉 이거 사용하면 될듯?
        open var systemVersion: String { get } // e.g. @"4.0"
        ...
    }

    보시면 어떤 플랫폼에서 실행시켰는지, 제품 모델은 무엇인지 등과 가장 중요한 플랫폼 OS의 버전이 뭔지 systemVersion을 제공합니다!

     

    그럼 이거 이용하면 충분히 가능하겠죠?

     

    사용하고자하는 코드에서 . 뒤 마이너 버전까지는 필요없고 메이저한 4, 15, 16의 버전만 알면 충분하기에 별도 상수를 하나 만들어서 분기 처리를 진행해볼께요!

    let systemVersion = Int(UIDevice.current.systemVersion.split(separator: ".").first ?? "0")
    
    if systemVersion == 16 {
      // 16 버전 처리
    } else {
      // 15, 17 버전 처리
    }

    요렇게 해당 String을 쪼개서 앞 메이저한 버전 부분만 가져와서 Int 타입으로 변환시켜줍니다.

    그리고 이걸 아주 쉽게 분기 처리를 위해서 사용하면 끝!

    15, 17 버전은 동일 코드를 돌고 16 버전은 해당 코드를 돌도록 쉽게 구현할 수 있어요 🙌

     

    마무리

    available만 사용하려고 하다 보니 안되는걸 직감하고 다른 방법을 찾자 아주 쉬운 방법이 있었어요ㅎ

    근데 이 과정에서 available에 대해 확실히 더 연습한 계기가 되어서 다음 포스팅에서는 available로 돌아오겠습니다😄

Designed by Tistory.