Skip to content

Commit

Permalink
#171 feat: 위치 버튼을 눌렀을 때 현재 위치의 좌표를 받아오는 일련의 흐름 구축
Browse files Browse the repository at this point in the history
  • Loading branch information
LEEYOONJONG committed Dec 7, 2022
1 parent f7346a3 commit cf8ab4c
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 14 deletions.
10 changes: 10 additions & 0 deletions Segno/Segno.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@
79767E64293E2A1200E489DD /* DiaryDeleteEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79767E63293E2A1200E489DD /* DiaryDeleteEndpoint.swift */; };
98003E0E293F20F6009FBC35 /* DarkModeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98003E0D293F20F6009FBC35 /* DarkModeManager.swift */; };
98138D292940B00900D2CEDF /* DeleteTapGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98138D282940B00900D2CEDF /* DeleteTapGestureRecognizer.swift */; };
98138D2B2940EA0800D2CEDF /* LocationRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98138D2A2940EA0800D2CEDF /* LocationRepository.swift */; };
98138D4D2940F53F00D2CEDF /* LocationUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98138D4C2940F53F00D2CEDF /* LocationUseCase.swift */; };
9825F41B29377875005F2163 /* ChangeNicknameUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9825F41A29377875005F2163 /* ChangeNicknameUseCase.swift */; };
9825F41D29377ACF005F2163 /* SettingsRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9825F41C29377ACF005F2163 /* SettingsRepository.swift */; };
982A2A472924AE74006F6ACD /* UserDefaultsKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 982A2A462924AE74006F6ACD /* UserDefaultsKey.swift */; };
Expand Down Expand Up @@ -172,6 +174,8 @@
79767E63293E2A1200E489DD /* DiaryDeleteEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryDeleteEndpoint.swift; sourceTree = "<group>"; };
98003E0D293F20F6009FBC35 /* DarkModeManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DarkModeManager.swift; sourceTree = "<group>"; };
98138D282940B00900D2CEDF /* DeleteTapGestureRecognizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteTapGestureRecognizer.swift; sourceTree = "<group>"; };
98138D2A2940EA0800D2CEDF /* LocationRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRepository.swift; sourceTree = "<group>"; };
98138D4C2940F53F00D2CEDF /* LocationUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationUseCase.swift; sourceTree = "<group>"; };
9825F41A29377875005F2163 /* ChangeNicknameUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangeNicknameUseCase.swift; sourceTree = "<group>"; };
9825F41C29377ACF005F2163 /* SettingsRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsRepository.swift; sourceTree = "<group>"; };
982A2A462924AE74006F6ACD /* UserDefaultsKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsKey.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -335,6 +339,7 @@
988414DA2923606B007C9132 /* DiaryListUseCase.swift */,
7940FB32292E065F00276EFC /* DiaryDetailUseCase.swift */,
791529D72932F364005A8DDB /* DiaryEditUseCase.swift */,
98138D4C2940F53F00D2CEDF /* LocationUseCase.swift */,
66A8CF682937945300C17F84 /* UserDetailUseCase.swift */,
9894EAF429373385005F2B15 /* SettingsUseCase.swift */,
4F307A49293889C200FA36A0 /* SearchMusicUseCase.swift */,
Expand Down Expand Up @@ -476,6 +481,7 @@
4FCAC5C1292B5C9000BF9CDD /* LoginSession.swift */,
4F307A4529387C1100FA36A0 /* ShazamSession.swift */,
4F307A472938832900FA36A0 /* MusicSession.swift */,
98138D2A2940EA0800D2CEDF /* LocationRepository.swift */,
);
path = Session;
sourceTree = "<group>";
Expand Down Expand Up @@ -629,11 +635,13 @@
66A8CF692937945300C17F84 /* UserDetailUseCase.swift in Sources */,
988414AE2922235B007C9132 /* LocalUtilityRepository.swift in Sources */,
66A8CF612935F44100C17F84 /* MyPageViewModel.swift in Sources */,
98138D4D2940F53F00D2CEDF /* LocationUseCase.swift in Sources */,
988414D929235345007C9132 /* DiaryCollectionViewModel.swift in Sources */,
4F589DD6293FB9AB00DB39E5 /* ShazamSongDTO.swift in Sources */,
4FEBFAAF291CF9F300E78139 /* MusicInfo.swift in Sources */,
4FEBFAAB291CF30E00E78139 /* DiaryListItem.swift in Sources */,
7918380829233F7100BC6992 /* UIButton+.swift in Sources */,
98138D2B2940EA0800D2CEDF /* LocationRepository.swift in Sources */,
4F4E0D7B29252526005ABA8F /* TokenDTO.swift in Sources */,
666E6F81291CF49E00CECD4B /* LoginCoordinator.swift in Sources */,
7940FB31292E065100276EFC /* DiaryDetailEndpoint.swift in Sources */,
Expand Down Expand Up @@ -832,6 +840,7 @@
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = Segno/Resource/Info.plist;
INFOPLIST_KEY_NSAppleMusicUsageDescription = "";
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "위치 정보를 받아오기 위해 권한이 필요합니다.";
INFOPLIST_KEY_NSMicrophoneUsageDescription = "음악 검색 기능을 위해 마이크 사용 허가가 필요합니다.";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
Expand Down Expand Up @@ -863,6 +872,7 @@
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = Segno/Resource/Info.plist;
INFOPLIST_KEY_NSAppleMusicUsageDescription = "";
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "위치 정보를 받아오기 위해 권한이 필요합니다.";
INFOPLIST_KEY_NSMicrophoneUsageDescription = "음악 검색 기능을 위해 마이크 사용 허가가 필요합니다.";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
Expand Down
81 changes: 81 additions & 0 deletions Segno/Segno/Data/Session/LocationRepository.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//
// LocationSession.swift
// Segno
//
// Created by YOONJONG on 2022/12/08.
//

import CoreLocation
import Foundation

import RxSwift

protocol LocationRepository {
var locationSubject: PublishSubject<Location> { get set }
var addressSubject: PublishSubject<String> { get set }
func getLocation()
func stopLocation()
}

final class LocationRepositoryImpl: NSObject, LocationRepository {
var locationSubject = PublishSubject<Location>()
var addressSubject = PublishSubject<String>()
private var locationManager = CLLocationManager()

override init() {

}

func getLocation() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
DispatchQueue.global().async {
if CLLocationManager.locationServicesEnabled() {
debugPrint("위치 서비스 on")
self.locationManager.startUpdatingLocation()
} else {
print("위치 서비스 off 상태")
}
}
}

func stopLocation() {
DispatchQueue.global().async {
self.locationManager.stopUpdatingLocation()
}
}

func getAddress(location: CLLocation) {
let geocoder = CLGeocoder()
let locale = Locale(identifier: "Ko-kr")
geocoder.reverseGeocodeLocation(location, preferredLocale: locale) { placemarks, error in
guard let placemarks = placemarks,
let address = placemarks.last else { return }
// debugPrint("description : ", address.description)
let fullAddress = address.description.components(separatedBy: ", ")[1]
let array = Array(fullAddress.components(separatedBy: " ").dropFirst())
let refinedAddress = array.joined(separator: " ")
debugPrint("full : ", refinedAddress)

self.addressSubject.onNext(refinedAddress)
}
}
}

extension LocationRepositoryImpl: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
debugPrint("didUpdateLocations")
if let cllocation = locations.first {
print("위도 : \(cllocation.coordinate.latitude)")
print("경도 : \(cllocation.coordinate.longitude)")
let location = Location(latitude: cllocation.coordinate.latitude, longitude: cllocation.coordinate.longitude)
getAddress(location: cllocation)
locationSubject.onNext(location)
}
}

func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
debugPrint("didFailWithError")
}
}
47 changes: 47 additions & 0 deletions Segno/Segno/Domain/UseCase/LocationUseCase.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// LocationUseCase.swift
// Segno
//
// Created by YOONJONG on 2022/12/08.
//

import Foundation

import RxSwift

protocol LocationUseCase {
var locationSubject: PublishSubject<Location> { get set }
var addressSubject: PublishSubject<String> { get set }
func getLocation()
func stopLocation()
}

final class LocationUseCaseImpl: LocationUseCase {
var locationSubject = PublishSubject<Location>()
var addressSubject = PublishSubject<String>()
let repository: LocationRepository
private let disposeBag = DisposeBag()

init(repository: LocationRepository = LocationRepositoryImpl()) {
self.repository = repository
subscribeResults()
}

func getLocation() {
repository.getLocation()
}

func stopLocation() {
repository.stopLocation()
}

private func subscribeResults() {
repository.addressSubject
.bind(to: addressSubject)
.disposed(by: disposeBag)

repository.locationSubject
.bind(to: locationSubject)
.disposed(by: disposeBag)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ final class DiaryEditViewController: UIViewController {
// 스택 뷰 안에 들어가는 컨텐츠 설정
static let majorContentHeight: CGFloat = 400
static let minorContentHeight: CGFloat = 60
static let tagTextFieldHeight: CGFloat = 40
static let semiMinorContentHeight: CGFloat = 40
static let halfMinorContentHeight: CGFloat = 30
static let standardCornerRadius: CGFloat = 8
static let mediumFontSize: CGFloat = 24
Expand All @@ -43,12 +43,15 @@ final class DiaryEditViewController: UIViewController {
static let locationButtonImage = UIImage(systemName: "location.fill")
static let saveButtonTitle = "저장"
static let buttonCornerRadius = CGFloat(minorContentHeight / 2)
static let tagButtonCornerRadius = CGFloat(halfMinorContentHeight / 2)
static let halfMinorCornerRadius = CGFloat(halfMinorContentHeight / 2)
static let semiMinorCornerRadius = CGFloat(semiMinorContentHeight / 2)
}

let viewModel: DiaryEditViewModel
private let viewModel: DiaryEditViewModel
private var disposeBag = DisposeBag()
private var tags: [String] = []
private var location: Location?
private var address = Metric.locationPlaceholder

private lazy var mainScrollView: UIScrollView = {
let scrollView = UIScrollView()
Expand Down Expand Up @@ -177,13 +180,14 @@ final class DiaryEditViewController: UIViewController {
let label = UILabel()
label.font = .appFont(.surroundAir, size: Metric.smallFontSize)
label.text = Metric.locationPlaceholder
label.adjustsFontSizeToFitWidth = true
return label
}()

private lazy var saveButton: UIButton = {
let button = UIButton()
button.backgroundColor = .appColor(.color4)
button.layer.cornerRadius = Metric.standardCornerRadius
button.layer.cornerRadius = Metric.semiMinorCornerRadius
button.setTitle(Metric.saveButtonTitle, for: .normal)
button.titleLabel?.font = .appFont(.surroundAir, size: Metric.smallFontSize)
return button
Expand All @@ -195,7 +199,7 @@ final class DiaryEditViewController: UIViewController {

init(viewModel: DiaryEditViewModel = DiaryEditViewModel()) {
self.viewModel = viewModel

super.init(nibName: nil, bundle: nil)
}

Expand All @@ -213,6 +217,7 @@ final class DiaryEditViewController: UIViewController {
bindButtonAction()
subscribeSearchingStatus()
sunscribeSearchResult()
subscribeLocationResult()
}

override func viewWillAppear(_ animated: Bool) {
Expand Down Expand Up @@ -265,7 +270,7 @@ final class DiaryEditViewController: UIViewController {

contentsStackView.addArrangedSubview(tagTextField)
tagTextField.snp.makeConstraints {
$0.height.equalTo(Metric.tagTextFieldHeight)
$0.height.equalTo(Metric.semiMinorContentHeight)
}

contentsStackView.addArrangedSubview(tagScrollView)
Expand All @@ -287,6 +292,9 @@ final class DiaryEditViewController: UIViewController {
setupLocationStackView()

contentsStackView.addArrangedSubview(saveButton)
saveButton.snp.makeConstraints {
$0.height.equalTo(Metric.semiMinorContentHeight)
}
}

private func setupTagScrollView() {
Expand Down Expand Up @@ -404,14 +412,20 @@ extension DiaryEditViewController {
}
.disposed(by: disposeBag)

addlocationButton.rx.tap
.withUnretained(self)
.bind { _ in
self.locationButtonTapped()
}
.disposed(by: disposeBag)

saveButton.rx.tap
.withUnretained(self)
.bind { _ in
if self.photoImageView.image == nil {
debugPrint("이미지를 넣지 않으면 저장할 수 없습니다!")
} else {
// TODO: 저장
self.viewModel.saveDiary()
self.saveDiary()
}
}
.disposed(by: disposeBag)
Expand Down Expand Up @@ -439,8 +453,55 @@ extension DiaryEditViewController {
private func searchTapped() {
viewModel.toggleSearchMusic()
}

private func locationButtonTapped() {
viewModel.toggleLocation()
}

private func saveDiary() {
// TODO: 제목 없으면 날짜로 제목 만들기
debugPrint("title : ", titleTextField.text)
debugPrint("tags : ", tags)
// TODO: 이미지 업로드 해야
debugPrint("bodyText : ", bodyTextView.text)
// TODO: MusicInfo엔 어떤 정보가 string으로?
debugPrint("location : ", location)

// TODO: 저장
self.viewModel.saveDiary()
}
}


extension DiaryEditViewController {
private func subscribeLocationResult() {
viewModel.isReceivingLocation
.withUnretained(self)
.subscribe(onNext: { _, searchState in
switch searchState {
case true:
self.locationInfoLabel.text = Metric.searching
self.addlocationButton.tintColor = .systemRed
case false:
self.locationInfoLabel.text = self.address
self.addlocationButton.tintColor = .appColor(.white)

}
})
.disposed(by: disposeBag)

viewModel.addressSubject
.bind(to: locationInfoLabel.rx.text)
.disposed(by: disposeBag)

viewModel.locationSubject
.withUnretained(self)
.subscribe(onNext: { _, location in
self.location = location
})
.disposed(by: disposeBag)
}
}
extension DiaryEditViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
var newImage: UIImage? = nil // update 할 이미지
Expand Down Expand Up @@ -492,7 +553,6 @@ extension DiaryEditViewController: UITextFieldDelegate {

extension DiaryEditViewController: UITextViewDelegate {
func textViewDidBeginEditing(_ textView: UITextView) {
print("진입 : ", textView.text)
if textView.text == Metric.bodyPlaceholder {
textView.text = nil
textView.textColor = .appColor(.black)
Expand Down
Loading

0 comments on commit cf8ab4c

Please sign in to comment.