앱 실행
낮일 때 배경 이미지
밤일 때 배경 이미지
카메라 열었을 때 접근 권한 알림
카메라 열렸을 때
뷰에 업로드
온도에 맞춰서 추천 아이템 실시간으로 변경
About
•
사용자 위치의 날씨 데이터에 따른 실시간 옷 추천 + 다양한 패션 정보 제공
•
CoreLocation과 WeatherKit 사용
사용된 오픈소스라이브러리
•
SnapKit
•
Then
사용된 프레임워크
•
CoreLocation
•
WeatherKit
주요 코드
[ LocationManager.swift ]
•
싱글톤 패턴을 통해 앱 전체에서 하나의 인스턴스만 사용하도록 구현하였다.
◦
싱글톤 패턴 장점
1. 싱글톤 패턴은 하나의 인스턴스만 생성되므로 메모리 사용이 최소화된다.
2. 앱 전체에서 같은 인스턴스에 접근함으로써 데이터 일관성을 유지할 수 있다. 예를 들어, 여러 화면에서 같은 위치 정보를 사용하거나 업데이트할 때 유용하다.
3. 인스턴스가 단 한 번만 생성되도록 보장한다. 이는 예기치 않은 중복 생성이나 오류를 방지하는 데 도움이 된다.
4. 어느 곳에서나 쉽게 접근할 수 있어 편리하다. 다른 객체나 클래스에서 별도의 초기화 과정 없이 바로 LocationManager 의 인스턴스를 사용할 수 있다.
◦
싱글톤 패턴 단점
1. 전역 상태를 가지고 있어 테스트가 어려울 수 있다. 테스트 환경에서 예상치 못한 상태 변경이 발생할 수 있으며 이는 테스트 결과에 영향을 줄 수 있다.
2. 객체 간의 강한 결합을 유발할 수 있으며 이는 코드의 유연성을 떨어뜨릴 수 있다. 다른 클래스들이 지나치게 의존하게 되면 시스템의 다른 부분을 수정할 때 예상치 못한 부작용이 발생할 수 있다.
3. 멀티스레드 환경에서 동시성 문제를 일으킬 수 있다. 여러 스레드가 동시에 싱글톤 인스턴스에 접근할 때 동기화 문제가 발생할 가능성이 있다.
4. 싱글톤 패턴은 확장성에 제한을 두며 특히 대규모 시스템이나 복잡한 애플리케이션에서는 유연성이 떨어질 수 있다.
•
사용자의 현재 위치를 얻기 위해 CLLocationManager 를 사용한다. 이 클래스는 사용자의 위치 변화를 추적한다.
•
위치 정보와 권한 상태가 변경될 때마다 이를 앱에 알려줄 수 있는 콜백 메서드들을 제공한다. 이를 통해 앱은 사용자의 위치 변화나 권한 상태 변화에 신속하게 반응할 수 있다.
var locationStatus: CLAuthorizationStatus?
...
private var statusString: String {
guard let status = locationStatus else {
return "unknown"
}
switch status {
case .notDetermined: return "notDetermined"
case .authorizedWhenInUse: return "authorizedWhenInUse"
case .authorizedAlways: return "authorizedAlways"
case .restricted: return "restricted"
case .denied: return "denied"
default: return "unknown"
}
}
Swift
복사
•
desiredAccuracy 속성을 통해 위치 정보의 정확도를 설정한다. 이는 앱의 성능과 배터리 사용량에 균형을 맞추는 데 중요한 역할을 한다.
locationManager.desiredAccuracy = kCLLocationAccuracyKilometer
Swift
복사
[ WeatherDataCenter.swift ]
func getWeatherForLocation(
location: CLLocation,
completion: @escaping (_ result: Result<ParsedWeather, Error>) -> Void
) {
Task {
do {
// 시작 시간을 현재 시간으로 설정
let hourlyStartDate = Date.now
// 종료 시간을 현재 시간으로부터 24시간 뒤로 설정
let hourlyEndDate = Calendar.current.date(
byAdding: .hour,
value: 24,
to: hourlyStartDate
)!
let weatherData: (
currentWeather: CurrentWeather,
hourlyForecast: Forecast<HourWeather>,
weatherAlerts: [WeatherAlert]?,
dailyForecast: Forecast<DayWeather>
) = try await weatherService.weather(
for: location,
including: .current,
.hourly(
startDate: hourlyStartDate,
endDate: hourlyEndDate
),
.alerts,
.daily
)
let parsed = ParsedWeather(
currentWeather: weatherData.currentWeather,
hourlyForecast: weatherData.hourlyForecast,
dailyForecast: weatherData.dailyForecast,
weatherAlerts: weatherData.weatherAlerts
)
DispatchQueue.main.async {
completion(.success(parsed))
}
} catch {
DispatchQueue.main.async {
completion(.failure(error))
}
}
}
}
Swift
복사
•
위 메서드는 주어진 위치에 대한 상세한 날씨 정보(현재 날씨, 시간별 날씨, 일별 날씨, 날씨 경보)를 요청하고 결과를 ‘ParsedWeather’ 객체로 변환하여 반환한다. 또한, 비동기적으로 실행되며 결과는 메인 스레드에서 처리된다.