데이터가 매번 교체되기보다는 앱스토어 업데이트가 진행되었을 때만 추가 데이터를 비교하며 받아오도록 해 불필요한 연산을 피하고 싶어서, 방법을 찾아보다가 앱의 번들 버전을 코드로 받아올 수 있다는 점을 알게되었다.
이 때 가져올 수 있는 번들 버전은 두 종류가 있다.
하나는 CFBundleVersion과 CFBundleVersionString이다.
간단하게 예를 들면 앱스토어에 올라와있는 앱 버전 정보는 이런 식으로 작성되어있다.
이 번호는 앞에서부터 더 큰 버전의 변화를 나타낸다.
맨 앞은 주요, 중간은 부차적인, 사소한 수정을, 맨 마지막은 작은 패치, 유저 관리 릴리스 번호이다. 점점 작은 릴리즈 변화를 나타낸다.
이 정보는 별도 설정 없이도 xcode info.plist에 지정되어 있다.
초기값은 각각 (MARKETING_VERSION) 이라고만 나와있다.
뒤의 번들 버전 스트링(short)에 마케팅 버전이라고 쓰여있는 게 빈말이 아니다. 두 값의 주된 차이는 전자는 앱 전체에 적용되며, 릴리즈 되지 않은 비공식 정보를 포함하여 확인되는 버전이고 뒤의 버전은 앱스토어 등을 통해 사용자가 확인 가능한 정보이다.
따라서 내부 테스팅 용도로 빈번한 업데이트가 필요할 때는 전자의 값을 통한 코드 테스트를, 나처럼 앱업데이트 시에만 사용자를 위한 데이터 업데이트가 필요할 경우 후자의 값을 사용하면 된다.
이 두 숫자를 코드 상 확인하기 위해서는 다음과 같이 작성하면 된다.
guard let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String else {
fatalError("App version not found")
}
번들 메인의 infoDictionary에는 두 정보에 대한 각각의 키값을 가지는 프로퍼티 리스트가 자동적으로 지정되어 있다.
CFBundleShortVersionString값만 CFBundleVersion으로 바꿔주면 된다.
이 버전이 바뀔 때마다 변경해주기 위해서는 비교값을 위해 이전 버전 값을 저장하도록 UserDefault에 이전 버전값을 별도로 저장해주도록 설정했다.
let preloadedDataKey = "preloadedDataVersion"
let userDefaults = UserDefaults.standard
//앱버전 따라 확인 후 데이터 맞춰주도록 설정
let loadedVersion = userDefaults.string(forKey: preloadedDataKey)
if let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String,
(loadedVersion ?? "0").compare(appVersion, options: .numeric) == .orderedAscending {
do {
//데이터 업데이트 func 추가
} catch {
fatalError(error.localizedDescription)
}
//업데이트 종료 후에 유저디폴트에 새로운 버전 정보 저장
userDefaults.set(appVersion, forKey: preloadedDataKey)
}
이 코드를 찾아서 작성해보는 것보다, 이 코드를 테스트하는 게 훨씬 어려웠다.
info.plist에서 리스트보기로 값을 변경하거나, 코드 보기에서 직접 값을 변경해보기도 했지만 변경 사항이 반영되지 않았다.
검색을 해보았지만 답을 찾기 어려웠는데,
General에 값을 직접 바꿔 xcode 시뮬레이터로 돌리는 것으로 해결했다.
앱 General에 가보면 > Version과 Build를 설정할 수 있다.
기본값은 1.0, 1으로 각각 세팅되어있지만 이를 변경하면 각각 CFBundleShortString과 CFBundle값이 바뀐다.
이 때 빌드 번호는 1.0.0이런 식이 아니라 1 처럼 작성해서
릴리즈 정보인 1.0과 혼합해서 1.0(1) 이런 식으로 합쳐서 보여주게 업데이트하는 사람도 있는 듯하다.
이런 식으로 했는데 값이 바뀌지 않는다면 clean build folder를 반드시 하고 build를 해야 적용이 된다. 왜인지는 잘 모르겠다.
빌드 파일이 내부에 적용될 때 temp 상태로 저장되어있고 이런 코드 자체 영향이 없는 변화에는 바뀌지 않는 걸까?
General 변경값은 프로젝트 파일인 pbxproj에서 바꿔줄 수도 있기 때문에 코드로 바꾸는 걸 선호하는 분은 pbxproj에서 CURRENT_PROJECT_VERSION (CFBundleVersion) 또는 MARKETING_VERSION (CFBundleShortString) 값을 바꿔주면 된다