Skip to content

Commit 661ea8b

Browse files
authored
Merge pull request #16 from DDD-3/location
위치 관련 모듈 작성 (#5)
2 parents fc7d75e + c0c92f4 commit 661ea8b

File tree

4 files changed

+172
-1
lines changed

4 files changed

+172
-1
lines changed

gigi.xcodeproj/project.pbxproj

+24
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
19A964D32381250200AAC7D3 /* KakaoMapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A964D22381250200AAC7D3 /* KakaoMapView.swift */; };
5858
19A964D62381253D00AAC7D3 /* KakaoMapUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A964D52381253D00AAC7D3 /* KakaoMapUIView.swift */; };
5959
19A964DD23812C8300AAC7D3 /* LinkShareView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A964DC23812C8300AAC7D3 /* LinkShareView.swift */; };
60+
19A964E12382673000AAC7D3 /* LocationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A964E02382673000AAC7D3 /* LocationService.swift */; };
61+
19A964E8238279EB00AAC7D3 /* Result+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A964E7238279EB00AAC7D3 /* Result+.swift */; };
6062
749CA54119529C4ED25615781282B52E /* Pods_gigi.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F40FDE06DB803CBF6F0561C7EB7F2D6 /* Pods_gigi.framework */; };
6163
/* End PBXBuildFile section */
6264

@@ -122,6 +124,8 @@
122124
19A964D52381253D00AAC7D3 /* KakaoMapUIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KakaoMapUIView.swift; sourceTree = "<group>"; };
123125
19A964D7238126AD00AAC7D3 /* gigi-bridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "gigi-bridge.h"; sourceTree = "<group>"; };
124126
19A964DC23812C8300AAC7D3 /* LinkShareView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkShareView.swift; sourceTree = "<group>"; };
127+
19A964E02382673000AAC7D3 /* LocationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationService.swift; sourceTree = "<group>"; };
128+
19A964E7238279EB00AAC7D3 /* Result+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Result+.swift"; sourceTree = "<group>"; };
125129
2925A7B9682F3DCFCD77A171DA8532CD /* Pods-gigi.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-gigi.release.xcconfig"; path = "Target Support Files/Pods-gigi/Pods-gigi.release.xcconfig"; sourceTree = "<group>"; };
126130
2BB003C5ED0784D898EA9387BFCD2162 /* gigi.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = gigi.app; sourceTree = BUILT_PRODUCTS_DIR; };
127131
9F40FDE06DB803CBF6F0561C7EB7F2D6 /* Pods_gigi.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_gigi.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -193,6 +197,8 @@
193197
19A96465238122D600AAC7D3 /* Sources */ = {
194198
isa = PBXGroup;
195199
children = (
200+
19A964E923827AFA00AAC7D3 /* Service */,
201+
19A964E6238279E400AAC7D3 /* Extension */,
196202
19A9646B238122D600AAC7D3 /* KakaoAPI */,
197203
19A96466238122D600AAC7D3 /* Common */,
198204
19A96468238122D600AAC7D3 /* View */,
@@ -296,6 +302,22 @@
296302
path = "UIKit Bridge";
297303
sourceTree = "<group>";
298304
};
305+
19A964E6238279E400AAC7D3 /* Extension */ = {
306+
isa = PBXGroup;
307+
children = (
308+
19A964E7238279EB00AAC7D3 /* Result+.swift */,
309+
);
310+
path = Extension;
311+
sourceTree = "<group>";
312+
};
313+
19A964E923827AFA00AAC7D3 /* Service */ = {
314+
isa = PBXGroup;
315+
children = (
316+
19A964E02382673000AAC7D3 /* LocationService.swift */,
317+
);
318+
path = Service;
319+
sourceTree = "<group>";
320+
};
299321
7CADB359813AD0C8A020F1B508392C9A = {
300322
isa = PBXGroup;
301323
children = (
@@ -486,6 +508,8 @@
486508
files = (
487509
19A964D32381250200AAC7D3 /* KakaoMapView.swift in Sources */,
488510
19A96475238122D600AAC7D3 /* AppDelegate.swift in Sources */,
511+
19A964E8238279EB00AAC7D3 /* Result+.swift in Sources */,
512+
19A964E12382673000AAC7D3 /* LocationService.swift in Sources */,
489513
19A96477238122D600AAC7D3 /* KakaoSearchByCategoryResponse.swift in Sources */,
490514
19A96476238122D600AAC7D3 /* KakaoPlaceCategory.swift in Sources */,
491515
19A96474238122D600AAC7D3 /* ContentView.swift in Sources */,

gigi/Sources/Extension/Result+.swift

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//
2+
// Result+.swift
3+
// gigi
4+
//
5+
// Created by Presto on 2019/11/18.
6+
// Copyright © 2019 ieungieung. All rights reserved.
7+
//
8+
9+
extension Result {
10+
var success: Success? {
11+
guard case let .success(success) = self else { return nil }
12+
return success
13+
}
14+
15+
var failure: Failure? {
16+
guard case let .failure(failure) = self else { return nil }
17+
return failure
18+
}
19+
}
+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//
2+
// LocationService.swift
3+
// gigi
4+
//
5+
// Created by Presto on 2019/11/18.
6+
// Copyright © 2019 ieungieung. All rights reserved.
7+
//
8+
9+
import Combine
10+
import CoreLocation
11+
12+
typealias CoordinateResult = Result<CLLocationCoordinate2D, CLError>
13+
14+
final class LocationService: NSObject {
15+
static let shared = LocationService()
16+
17+
private let locationManagerDelegateObject = LocationManagerDelegateObject()
18+
19+
private let locationManager: CLLocationManager = {
20+
let manager = CLLocationManager()
21+
manager.desiredAccuracy = kCLLocationAccuracyBest
22+
manager.distanceFilter = kCLDistanceFilterNone
23+
return manager
24+
}()
25+
26+
private override init() {
27+
super.init()
28+
locationManager.delegate = locationManagerDelegateObject
29+
}
30+
31+
var authorizationStatus: CLAuthorizationStatus {
32+
return CLLocationManager.authorizationStatus()
33+
}
34+
35+
var coordinateResult: CoordinateResult? {
36+
guard let result = locationManagerDelegateObject.coordinateResultSubject.value
37+
else { return nil }
38+
return result
39+
}
40+
41+
var authorizationStatusPublisher: AnyPublisher<CLAuthorizationStatus, Never> {
42+
return locationManagerDelegateObject.authorizationStatusSubject
43+
.compactMap { $0 }
44+
.eraseToAnyPublisher()
45+
}
46+
47+
var coordinateResultPublisher: AnyPublisher<CoordinateResult, Never> {
48+
return locationManagerDelegateObject.coordinateResultSubject
49+
.compactMap { $0 }
50+
.eraseToAnyPublisher()
51+
}
52+
53+
func requestAuthorization() {
54+
locationManager.requestWhenInUseAuthorization()
55+
}
56+
57+
func startUpdatingLocation() {
58+
locationManager.startUpdatingLocation()
59+
}
60+
61+
func stopUpdatingLocation() {
62+
locationManager.stopUpdatingLocation()
63+
}
64+
}
65+
66+
// MARK: - Location Manager Delegate Object
67+
68+
private final class LocationManagerDelegateObject: NSObject, CLLocationManagerDelegate {
69+
let authorizationStatusSubject = CurrentValueSubject<CLAuthorizationStatus?, Never>(nil)
70+
71+
let coordinateResultSubject = CurrentValueSubject<CoordinateResult?, Never>(nil)
72+
73+
func locationManager(_ manager: CLLocationManager,
74+
didChangeAuthorization status: CLAuthorizationStatus) {
75+
authorizationStatusSubject.send(status)
76+
}
77+
78+
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
79+
guard let location = locations.first else { return }
80+
coordinateResultSubject.send(.success(location.coordinate))
81+
}
82+
83+
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
84+
guard let clError = error as? CLError else { return }
85+
coordinateResultSubject.send(.failure(clError))
86+
}
87+
}

gigi/Supports/AppDelegate.swift

+42-1
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@
66
// Copyright © 2019 ieungieung. All rights reserved.
77
//
88

9+
import Combine
910
import UIKit
1011

1112
@UIApplicationMain
1213
final class AppDelegate: UIResponder, UIApplicationDelegate {
14+
private var cancellables = Set<AnyCancellable>()
1315

1416
func application(_ application: UIApplication,
1517
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18+
setInitialCoordinate()
1619
return true
1720
}
1821

@@ -25,5 +28,43 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
2528
}
2629

2730
func application(_ application: UIApplication,
28-
didDiscardSceneSessions sceneSessions: Set<UISceneSession>) { }
31+
didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {}
32+
}
33+
34+
extension AppDelegate {
35+
private func setInitialCoordinate() {
36+
let service = LocationService.shared
37+
38+
service.requestAuthorization()
39+
40+
service.authorizationStatusPublisher
41+
.filter { $0 == .authorizedWhenInUse || $0 == .authorizedAlways }
42+
.sink(receiveValue: { _ in
43+
Log.debug("위치 정보 권한 허용됨")
44+
service.startUpdatingLocation()
45+
})
46+
.store(in: &cancellables)
47+
48+
service.authorizationStatusPublisher
49+
.filter { !($0 == .authorizedWhenInUse || $0 == .authorizedAlways) }
50+
.sink(receiveValue: { _ in
51+
Log.error("위치 정보 권한 허용되지 않음")
52+
})
53+
.store(in: &cancellables)
54+
55+
service.coordinateResultPublisher
56+
.compactMap { $0.success }
57+
.sink(receiveValue: { coordinate in
58+
Log.debug("현재 위치 갱신됨 : \(coordinate)")
59+
service.stopUpdatingLocation()
60+
})
61+
.store(in: &cancellables)
62+
63+
service.coordinateResultPublisher
64+
.compactMap { $0.failure }
65+
.sink(receiveValue: { error in
66+
Log.error("위치 갱신 에러 : \(error.localizedDescription)")
67+
})
68+
.store(in: &cancellables)
69+
}
2970
}

0 commit comments

Comments
 (0)