Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- 리팩토링
- uitableview
- ios
- 스위프트
- RxCocoa
- clean architecture
- swiftUI
- combine
- UITextView
- ribs
- Observable
- map
- Clean Code
- Refactoring
- SWIFT
- MVVM
- 리펙토링
- swift documentation
- 클린 코드
- 애니메이션
- Human interface guide
- Xcode
- UICollectionView
- Protocol
- tableView
- collectionview
- rxswift
- HIG
- 리펙터링
- uiscrollview
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] app store로 이동 (버전 업데이트, 다시 돌아온 경우 처리, 현재 버전, 최신 버전 가져오는 방법) 본문
iOS 응용 (swift)
[iOS - swift] app store로 이동 (버전 업데이트, 다시 돌아온 경우 처리, 현재 버전, 최신 버전 가져오는 방법)
jake-kim 2021. 3. 15. 23:45현재 버전과 앱스토어에 있는 최신버전 확인 방법
- 현재 버전 정보 가져오기
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
- 상수로 설정
cf) bundle id와 buildNumber는 아래와 같이 획득
struct Constants {
struct System {
static let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
static let bundleIdentifier = Bundle.main.infoDictionary?["CFBundleIdentifier"] as? String
static let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String
}
}
- 최신버전 확인 방법
func latestVersion() -> String? {
let appleID = "이곳에 Apple ID"
guard let url = URL(string: "http://itunes.apple.com/lookup?id=\(appleID)"),
let data = try? Data(contentsOf: url),
let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any],
let results = json["results"] as? [[String: Any]],
let appStoreVersion = results[0]["version"] as? String else {
return nil
}
return appStoreVersion
}
- 버전 비교 방법: String에 내장된 compare(:options:) 메소드 이용
let oldVersion = "0.12.0"
let latestVersion = "0.13.1"
let compareResult = oldVersion.compare(latestVersion, options: .numeric)
switch compareResult {
case .orderedAscending:
print("<")
case .orderedDescending:
print(">")
case .orderedSame:
print("==")
}
- 상수로 설정
- 주의: let data = try? Data(contentsOf: url) 이 부분이 존재하므로 인터넷과 연결되지 않으면 nil 반환
struct Constants {
struct System {
static let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
static let bundleIdentifier = Bundle.main.infoDictionary?["CFBundleIdentifier"] as? String
static let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String
static func latestVersion() -> String? {
let appleID = "이곳에 appleID"
guard let url = URL(string: "http://itunes.apple.com/lookup?id=\(appleID)"),
let data = try? Data(contentsOf: url),
let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any],
let results = json["results"] as? [[String: Any]],
let appStoreVersion = results[0]["version"] as? String else {
return nil
}
return appStoreVersion
}
}
}
App Store Connect에서 Apple ID 확인
- Apple ID를 이용하여 앱스토어로 이동 가능 - 복사
Apple ID를 이용하여 앱스토어로 이동
- AppStore를 open하지 못하는 error 케이스 정의
enum AppstoreOpenError: Error {
case invalidAppStoreURL
case cantOpenAppStoreURL
}
- openAppStore 함수 정의: 실패 시 위에서 정의한 오류 표출
func openAppStore(urlStr: String) -> Result<Void, AppstoreOpenError> {
guard let url = URL(string: urlStr) else {
print("invalid app store url")
return .failure(.invalidAppStoreURL)
}
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
return .success(())
} else {
print("can't open app store url")
return .failure(.cantOpenAppStoreURL)
}
}
- App store로 이동하는 url 정의
static let appStoreOpenUrlString = "itms-apps://itunes.apple.com/app/apple-store/1548711244" // 1548711244는 Apple ID
- openAppStore에 appStoreOpenurlString을 넣으면 이동 완료
* 주의사항: real device에서 동작하며, simulator로 할 경우 "This app is not allowed to query for scheme itms-apps" 에러메시지 표출
응용 - MVVM에서 앱스토어 이동 후 다시 화면으로 돌아올 때 처리
* RxSwift, RxCocoa 이용
- ViewModel에 foreground로 진입할 경우 등록한 postTask를 처리하는 함수 정의 (최초 한번 바인딩할 함수)
- PostTaskManager: 특정 task를 등록해 놓는 PostTaskManager 개념 참고
private func registerNotification() {
NotificationCenter.default.rx.notification(UIApplication.willEnterForegroundNotification)
.asDriverOnErrorNever()
.drive(onNext: { [weak self] _ in
self?.processPostTask()
}).disposed(by: bag)
}
- processPostTask() 함수 정의
private func processPostTask() {
guard let tasks = dependencies.postTaskManager.postTasks(postTastTarget: .splash) else {
return
}
for task in tasks {
switch task {
case .checkVersion:
checkVersion()
default:
break
}
}
dependencies.postTaskManager.remove(for: .splash)
}
- ViewModel에 output 변수, 함수 정의
// output 변수
let openAppStore = PublishRelay<String>()
// 초기
func viewWillAppear() {
checkVersion()
}
private func checkVersion() {
// Something to do
// require update
updateVersion()
}
...
// 버전 업데인트
private func updateVersion() {
openAppStore.accept(Constants.appStoreOpenUrlString)
}
- VC에서 문자열을 받아서 appstore 오픈, result는 ViewModel에서 처리
private func setupOutputBinding() {
viewModel.openAppStore.asDriverOnErrorNever()
.drive(onNext: { [weak self] in
let result = self?.openAppStore(urlStr: $0)
self?.viewModel.processAppstoreOpen(result: result)
}).disposed(by: bag)
}
- ViewModel에서, 앱스토어를 여는데 성공했으면 task 등록하여 foreground로 돌아온 경우 version을 다시 체크하도록 정의
func processAppstoreOpen(result: Result<Void, AppstoreOpenError>?) {
guard let result = result else {
return
}
switch result {
case .success:
dependencies.postTaskManager.register(
postTask: .init(
target: .splash,
task: .checkVersion
)
)
case .failure(let error):
print(error.errorString)
// 일시적인 오류
}
}
'iOS 응용 (swift)' 카테고리의 다른 글
[iOS - swift] os_log, Logger, 통합 로깅 시스템 (unified logging system) (0) | 2021.03.21 |
---|---|
[iOS - swift] Web crawling(웹 크롤링), web scraping, (swiftsoup, Alamofire, 한글 깨짐) (0) | 2021.03.17 |
[iOS - swift] tableView refresh (상단, 하단 새로고침) (0) | 2021.03.13 |
[iOS - swift] keychain에 암호화/복호화하여 저장 방법 (SecureEnclave) (0) | 2021.03.12 |
[iOS - swift] view위에 올라가있는 다른 view들을 하나의 tap gesture로 변경 (2) | 2021.03.09 |
Comments