diff --git a/Runnect-iOS/.swiftlint.yml b/Runnect-iOS/.swiftlint.yml
index 05d158e0..bbe4a629 100644
--- a/Runnect-iOS/.swiftlint.yml
+++ b/Runnect-iOS/.swiftlint.yml
@@ -6,6 +6,7 @@ disabled_rules:
- legacy_constructor
- unused_setter_value
- file_length
+ - void_function_in_ternary
included:
- Runnect-iOS
diff --git a/Runnect-iOS/Runnect-iOS.xcodeproj/xcshareddata/xcschemes/Runnect-iOS.xcscheme b/Runnect-iOS/Runnect-iOS.xcodeproj/xcshareddata/xcschemes/Runnect-iOS.xcscheme
index 1ee1ed34..03f5e3ec 100644
--- a/Runnect-iOS/Runnect-iOS.xcodeproj/xcshareddata/xcschemes/Runnect-iOS.xcscheme
+++ b/Runnect-iOS/Runnect-iOS.xcodeproj/xcshareddata/xcschemes/Runnect-iOS.xcscheme
@@ -54,7 +54,7 @@
+ isEnabled = "NO">
diff --git a/Runnect-iOS/Runnect-iOS/Global/Analytics/GAEvent.swift b/Runnect-iOS/Runnect-iOS/Global/Analytics/GAEvent.swift
index e18bfe74..b97ef3e3 100644
--- a/Runnect-iOS/Runnect-iOS/Global/Analytics/GAEvent.swift
+++ b/Runnect-iOS/Runnect-iOS/Global/Analytics/GAEvent.swift
@@ -9,8 +9,20 @@ import Foundation
struct GAEvent {
struct View {
+
+ // 진입 화면
static let viewHome = "view_home" // 앱 실행
static let viewSocialLogin = "view_social_login"
+
+ // 코스발견
+ static let viewCourseSearch = "view_course_search"
+ static let viewCourseDetail = "view_course_detail"
+ static let viewUserProfile = "view_user_profile"
+ static let viewCourseUpload = "view_course_upload"
+
+ // 마이페이지
+ static let viewSuccessLogout = "view_success_logout"
+ static let viewSuccessWithdraw = "view_success_withdraw"
}
struct Button {
@@ -43,15 +55,13 @@ struct GAEvent {
static let clickUploadButton = "click_upload_button"
static let clickTrySearchCourse = "click_try_search_course"
static let clickTryBanner = "click_try_banner"
- static let clickSearchCourse = "click_search_course"
- static let clickCourseDetail = "click_course_detail"
static let clickShare = "click_share"
static let clickUserProfile = "click_user_profile"
static let clickScrapPageStartCourse = "click_scrap_page_start_course"
- static let clickUploadCourse = "click_upload_course"
+ static let clickCourseUpload = "click_course_upload"
/// 보관함
- static let clickMyStorageCourseStart = "click_my_storage_course_start"
+ static let clickMyStorageCourseDrawingStart = "click_my_storage_course_drawing_start"
static let clickMyStorageTryModify = "click_my_storage_try_modify"
static let clickMyStorageTryRemove = "click_my_storage_try_remove"
static let clickScrapCourse = "click_scrap_course"
@@ -64,8 +74,6 @@ struct GAEvent {
static let clickCourseUploadInUploadedCourse = "click_course_upload_in_uploaded_course"
static let clickTryLogout = "click_try_logout"
static let clickTryWithdraw = "click_try_withdraw"
- static let clickSuccessLogout = "click_success_logout"
- static let clickSuccessWithdraw = "click_success_withdraw"
/// 방문자 모드
static let clickJoinInCourseDrawing = "click_join_in_course_drawing"
diff --git a/Runnect-iOS/Runnect-iOS/Global/Extension/UIKit+/UIGestureRecognizer+.swift b/Runnect-iOS/Runnect-iOS/Global/Extension/UIKit+/UIGestureRecognizer+.swift
index 027a8bda..a9ae72da 100644
--- a/Runnect-iOS/Runnect-iOS/Global/Extension/UIKit+/UIGestureRecognizer+.swift
+++ b/Runnect-iOS/Runnect-iOS/Global/Extension/UIKit+/UIGestureRecognizer+.swift
@@ -15,6 +15,7 @@ enum GestureType {
case pan(UIPanGestureRecognizer = .init())
case pinch(UIPinchGestureRecognizer = .init())
case edge(UIScreenEdgePanGestureRecognizer = .init())
+
func get() -> UIGestureRecognizer {
switch self {
case let .tap(tapGesture):
@@ -33,51 +34,55 @@ enum GestureType {
}
}
-extension UIGestureRecognizer {
- struct GesturePublisher: Publisher {
- typealias Output = GestureType
- typealias Failure = Never
- private let view: UIView
- private let gestureType: GestureType
- init(view: UIView, gestureType: GestureType) {
- self.view = view
- self.gestureType = gestureType
- }
-
- func receive(subscriber: S) where S: Subscriber,
- GesturePublisher.Failure == S.Failure,
- GesturePublisher.Output == S.Input {
- let subscription = GestureSubscription(
- subscriber: subscriber,
- view: view,
- gestureType: gestureType
- )
- subscriber.receive(subscription: subscription)
- }
+struct GesturePublisher: Publisher {
+ typealias Output = GestureType
+ typealias Failure = Never
+
+ private let view: UIView
+ private let gestureType: GestureType
+
+ init(view: UIView, gestureType: GestureType) {
+ self.view = view
+ self.gestureType = gestureType
}
- class GestureSubscription: Subscription where S.Input == GestureType, S.Failure == Never {
- private var subscriber: S?
- private var gestureType: GestureType
- private var view: UIView
- init(subscriber: S, view: UIView, gestureType: GestureType) {
- self.subscriber = subscriber
- self.view = view
- self.gestureType = gestureType
- configureGesture(gestureType)
- }
- private func configureGesture(_ gestureType: GestureType) {
- let gesture = gestureType.get()
- gesture.addTarget(self, action: #selector(handler))
- view.addGestureRecognizer(gesture)
- }
- func request(_ demand: Subscribers.Demand) { }
- func cancel() {
- subscriber = nil
- }
- @objc
- private func handler() {
- _ = subscriber?.receive(gestureType)
- }
+ func receive(subscriber: S) where S: Subscriber,
+ Failure == S.Failure,
+ Output == S.Input {
+ let subscription = GestureSubscription(
+ subscriber: subscriber,
+ view: view,
+ gestureType: gestureType
+ )
+ subscriber.receive(subscription: subscription)
+ }
+}
+
+class GestureSubscription: Subscription where S.Input == GestureType, S.Failure == Never {
+ private var subscriber: S?
+ private var gestureType: GestureType
+ private var view: UIView
+
+ init(subscriber: S, view: UIView, gestureType: GestureType) {
+ self.subscriber = subscriber
+ self.view = view
+ self.gestureType = gestureType
+ configureGesture(gestureType)
+ }
+
+ func request(_ demand: Subscribers.Demand) { }
+
+ func cancel() {
+ subscriber = nil
+ }
+
+ private func configureGesture(_ gestureType: GestureType) {
+ let gesture = gestureType.get()
+ gesture.addTarget(self, action: #selector(handler))
+ view.addGestureRecognizer(gesture)
+ }
+
+ @objc private func handler() {
+ _ = subscriber?.receive(gestureType)
}
}
diff --git a/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/img_banner1.imageset/Contents.json b/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/img_banner1.imageset/Contents.json
index bf0d6034..334c5c52 100644
--- a/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/img_banner1.imageset/Contents.json
+++ b/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/img_banner1.imageset/Contents.json
@@ -1,17 +1,17 @@
{
"images" : [
{
- "filename" : "ios 앱 배너.png",
+ "filename" : "ios배너x1.png",
"idiom" : "universal",
"scale" : "1x"
},
{
- "filename" : "ios 앱 배너@2x.png",
+ "filename" : "ios배너x2.png",
"idiom" : "universal",
"scale" : "2x"
},
{
- "filename" : "ios 앱 배너@3x.png",
+ "filename" : "ios배너x3.png",
"idiom" : "universal",
"scale" : "3x"
}
diff --git "a/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/img_banner1.imageset/ios \354\225\261 \353\260\260\353\204\210.png" "b/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/img_banner1.imageset/ios\353\260\260\353\204\210x1.png"
similarity index 100%
rename from "Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/img_banner1.imageset/ios \354\225\261 \353\260\260\353\204\210.png"
rename to "Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/img_banner1.imageset/ios\353\260\260\353\204\210x1.png"
diff --git "a/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/img_banner1.imageset/ios \354\225\261 \353\260\260\353\204\210@2x.png" "b/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/img_banner1.imageset/ios\353\260\260\353\204\210x2.png"
similarity index 100%
rename from "Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/img_banner1.imageset/ios \354\225\261 \353\260\260\353\204\210@2x.png"
rename to "Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/img_banner1.imageset/ios\353\260\260\353\204\210x2.png"
diff --git "a/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/img_banner1.imageset/ios \354\225\261 \353\260\260\353\204\210@3x.png" "b/Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/img_banner1.imageset/ios\353\260\260\353\204\210x3.png"
similarity index 100%
rename from "Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/img_banner1.imageset/ios \354\225\261 \353\260\260\353\204\210@3x.png"
rename to "Runnect-iOS/Runnect-iOS/Global/Resource/Assets.xcassets/img_banner1.imageset/ios\353\260\260\353\204\210x3.png"
diff --git a/Runnect-iOS/Runnect-iOS/Global/UIComponents/MapView/RNMapView.swift b/Runnect-iOS/Runnect-iOS/Global/UIComponents/MapView/RNMapView.swift
index 1f72ab51..f9862441 100644
--- a/Runnect-iOS/Runnect-iOS/Global/UIComponents/MapView/RNMapView.swift
+++ b/Runnect-iOS/Runnect-iOS/Global/UIComponents/MapView/RNMapView.swift
@@ -19,7 +19,7 @@ final class RNMapView: UIView {
@Published var pathDistance: Double = 0
@Published var markerCount = 0
- var eventSubject = PassthroughSubject, Never>()
+ var eventSubject = PassthroughSubject<[Double], Never>()
private let screenWidth = UIScreen.main.bounds.width
private let screenHeight = UIScreen.main.bounds.height
diff --git a/Runnect-iOS/Runnect-iOS/Network/Service/NetworkProvider.swift b/Runnect-iOS/Runnect-iOS/Network/Service/NetworkProvider.swift
index d98f8cba..b3718175 100644
--- a/Runnect-iOS/Runnect-iOS/Network/Service/NetworkProvider.swift
+++ b/Runnect-iOS/Runnect-iOS/Network/Service/NetworkProvider.swift
@@ -7,8 +7,8 @@
import Moya
-class NetworkProvider : MoyaProvider {
- func request(target: Provider, instance: Model.Type , vc: UIViewController, completion: @escaping(Model) -> ()){
+class NetworkProvider: MoyaProvider {
+ func request(target: Provider, instance: Model.Type, vc: UIViewController, completion: @escaping(Model) -> Void) {
self.request(target) { result in
switch result {
/// 서버 통신 성공
diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift
index 0c743b2f..856d7150 100644
--- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift
+++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDetail/VC/CourseDetailVC.swift
@@ -144,7 +144,7 @@ final class CourseDetailVC: UIViewController {
setLayout()
setAddTarget()
setRefreshControl()
- analyze(screenName: "코스 상세 페이지")
+ analyze(screenName: GAEvent.View.viewCourseDetail)
self.hideTabBar(wantsToHide: true)
}
@@ -177,6 +177,8 @@ extension CourseDetailVC {
return
}
+ analyze(buttonName: GAEvent.Button.clickShare)
+
let publicCourse = model.publicCourse
let title = publicCourse.title
let courseId = publicCourse.id // primaryKey
@@ -231,6 +233,9 @@ extension CourseDetailVC {
self.showToast(message: "회원만 조회 가능 합니다.")
return
}
+
+ analyze(screenName: GAEvent.Button.clickUserProfile)
+
guard let userId = self.userId else {return}
let userProfile = UserProfileVC()
userProfile.setUserId(userId: userId)
diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/MarathonMapCollectionViewCell.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/MarathonMapCollectionViewCell.swift
index e67307e3..d371faa9 100644
--- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/MarathonMapCollectionViewCell.swift
+++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/MarathonMapCollectionViewCell.swift
@@ -205,16 +205,20 @@ extension MarathonMapCollectionViewCell {
private func scrapCourse(publicCourseId: Int, scrapTF: Bool) {
LoadingIndicator.showLoading()
+
scrapProvider.request(.createAndDeleteScrap(publicCourseId: publicCourseId, scrapTF: scrapTF)) { [weak self] response in
- LoadingIndicator.hideLoading()
+ defer {
+ LoadingIndicator.hideLoading()
+ }
+
guard let self = self else { return }
+
switch response {
case .success(let result):
let status = result.statusCode
if 200..<300 ~= status {
print("스크랩 성공")
- }
- if status >= 400 {
+ } else if status >= 400 {
print("400 error")
}
case .failure(let error):
diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseDiscoveryVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseDiscoveryVC.swift
index 0d7c9f6f..a048ff5a 100644
--- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseDiscoveryVC.swift
+++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseDiscoveryVC.swift
@@ -165,6 +165,8 @@ extension CourseDiscoveryVC {
return
}
+ analyze(buttonName: GAEvent.Button.clickUploadButton)
+
let nextVC = MyCourseSelectVC()
nextVC.delegate = self
self.navigationController?.pushViewController(nextVC, animated: true)
@@ -552,5 +554,14 @@ extension CourseDiscoveryVC: TitleCollectionViewCellDelegate {
sort = ordering
self.courseList.removeAll()
getCourseData(pageNo: pageNo)
+
+ switch ordering {
+ case "date":
+ analyze(buttonName: GAEvent.Button.clickDate)
+ case "scrap":
+ analyze(buttonName: GAEvent.Button.clickScrap)
+ default:
+ break
+ }
}
}
diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseSearchVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseSearchVC.swift
index ac5879b2..d340141d 100644
--- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseSearchVC.swift
+++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseSearchVC.swift
@@ -73,6 +73,7 @@ final class CourseSearchVC: UIViewController {
setDelegate()
layout()
setTabBar()
+ analyze(screenName: GAEvent.View.viewCourseSearch)
}
override func viewWillAppear(_ animated: Bool) {
@@ -228,6 +229,7 @@ extension CourseSearchVC {
do {
let responseDto = try result.map(BaseResponse.self)
guard let data = responseDto.data else { return }
+ self.analyze(buttonName: GAEvent.Button.clickTrySearchCourse)
self.setData(data: data.publicCourses)
} catch {
self.setData(data: [])
diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseUploadVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseUploadVC.swift
index 92eba72f..b69a82da 100644
--- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseUploadVC.swift
+++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDiscovery/Views/VC/CourseUploadVC.swift
@@ -66,6 +66,7 @@ class CourseUploadVC: UIViewController {
setKeyboardNotification()
setTapGesture()
addKeyboardObserver()
+ analyze(screenName: GAEvent.View.viewCourseUpload)
}
override func viewWillDisappear(_ animated: Bool) {
@@ -95,8 +96,8 @@ extension CourseUploadVC {
courseModel.departure.town,
courseModel.departure.name
]
- .compactMap { $0 }
- .joined(separator: " ")
+ .compactMap { $0 }
+ .joined(separator: " ")
self.departureInfoView.setDescriptionText(description: departureString)
}
@@ -192,6 +193,8 @@ extension CourseUploadVC {
@objc func uploadButtonDidTap() {
self.uploadCourse()
+
+ analyze(buttonName: GAEvent.Button.clickCourseUpload)
}
}
@@ -264,7 +267,7 @@ extension CourseUploadVC {
make.leading.trailing.equalTo(view.safeAreaLayoutGuide).inset(16)
make.height.equalTo(35)
}
-
+
dividerView.snp.makeConstraints { make in
make.top.equalTo(courseTitleTextField.snp.bottom).offset(0)
make.leading.trailing.equalTo(view.safeAreaLayoutGuide).inset(16)
diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDrawing/VC/CourseDrawingHomeVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDrawing/VC/CourseDrawingHomeVC.swift
index 6e421753..af6c4282 100644
--- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDrawing/VC/CourseDrawingHomeVC.swift
+++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDrawing/VC/CourseDrawingHomeVC.swift
@@ -50,6 +50,9 @@ extension CourseDrawingHomeVC {
// MARK: - @objc Function
extension CourseDrawingHomeVC {
@objc private func pushToDepartureSearchVC() {
+
+ analyze(buttonName: GAEvent.Button.clickCourseDrawing)
+
let departureSearchVC = DepartureSearchVC()
departureSearchVC.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(departureSearchVC, animated: true)
diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseDrawing/VC/CourseDrawingVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseDrawing/VC/CourseDrawingVC.swift
index e7234907..e61af314 100644
--- a/Runnect-iOS/Runnect-iOS/Presentation/CourseDrawing/VC/CourseDrawingVC.swift
+++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseDrawing/VC/CourseDrawingVC.swift
@@ -194,7 +194,7 @@ extension CourseDrawingVC {
mapView.eventSubject.sink { [weak self] arr in
guard let self = self else { return }
self.searchLocationTmapAddress(latitude: arr[0], longitude: arr[1])
-// self.searchTest(latitude: arr[0], longitude: arr[1])
+ // self.searchTest(latitude: arr[0], longitude: arr[1])
}.store(in: cancelBag)
}
@@ -206,15 +206,21 @@ extension CourseDrawingVC {
let alertVC = CustomAlertVC()
alertVC.modalPresentationStyle = .overFullScreen
+ // 보관함 가기
alertVC.leftButtonTapped.sink { [weak self] _ in
guard let self = self else { return }
+ analyze(buttonName: GAEvent.Button.clickStoredAfterCourseComplete)
+
self.tabBarController?.selectedIndex = 1
self.navigationController?.popToRootViewController(animated: true)
alertVC.dismiss(animated: true)
}.store(in: cancelBag)
+ // 바로 달리기
alertVC.rightButtonTapped.sink { [weak self] _ in
guard let self = self else { return }
+ analyze(buttonName: GAEvent.Button.clickRunAfterCourseComplete)
+
let countDownVC = CountDownVC()
let runningModel = RunningModel(courseId: courseId,
locations: self.mapView.getMarkersLatLng(),
@@ -283,6 +289,77 @@ extension CourseDrawingVC {
self.departureInfoContainerView.addSubviews(departureLocationLabel, departureDetailLocationLabel, decideDepartureButton)
view.bringSubviewToFront(naviBarContainerStackView)
+ setNotchCoverViewLayout()
+ setNaviBarLayout()
+ setMapViewLayout()
+ setStartMarkStackViewLayout()
+ setDepartureInfoContainerViewLayout()
+ setAboutMapNoticeViewLayout()
+ }
+
+ private func setHiddenViewsLayout() {
+ view.addSubviews(naviBarForEditing, guideView, distanceContainerView, completeButton, undoButton)
+ view.sendSubviewToBack(naviBarForEditing)
+
+ naviBarForEditing.snp.makeConstraints { make in
+ make.leading.top.trailing.equalTo(view.safeAreaLayoutGuide)
+ make.height.equalTo(48)
+ }
+
+ guideView.snp.makeConstraints { make in
+ make.centerY.equalTo(naviBarForEditing.snp.centerY)
+ make.leading.equalTo(view.safeAreaLayoutGuide).inset(55)
+ make.trailing.equalTo(view.safeAreaLayoutGuide).inset(27)
+ }
+
+ distanceContainerView.snp.makeConstraints { make in
+ make.width.equalTo(96)
+ make.height.equalTo(44)
+ make.leading.equalTo(view.safeAreaLayoutGuide).inset(16)
+ make.top.equalTo(view.snp.bottom)
+ }
+
+ distanceContainerView.addSubviews(distanceStackView)
+
+ distanceStackView.snp.makeConstraints { make in
+ make.center.equalToSuperview()
+ }
+
+ undoButton.snp.makeConstraints { make in
+ make.trailing.equalTo(view.safeAreaLayoutGuide)
+ make.top.equalTo(view.snp.bottom)
+ }
+
+ completeButton.snp.makeConstraints { make in
+ make.leading.trailing.equalTo(view.safeAreaLayoutGuide).inset(16)
+ make.height.equalTo(44)
+ make.top.equalTo(view.snp.bottom).offset(34)
+ }
+ }
+
+ private func showHiddenViews(withDuration: TimeInterval = 0) {
+ [naviBarForEditing, guideView, distanceContainerView, completeButton, undoButton].forEach { subView in
+ view.bringSubviewToFront(subView)
+ }
+
+ UIView.animate(withDuration: withDuration) {
+ let naviBarContainerStackViewHeight = self.naviBarContainerStackView.frame.height
+ self.naviBarContainerStackView.transform = CGAffineTransform(translationX: 0, y: -naviBarContainerStackViewHeight)
+ self.departureInfoContainerView.transform = CGAffineTransform(translationX: 0, y: 172)
+ }
+
+ self.guideView.transform = CGAffineTransform(translationX: 0, y: -100)
+
+ UIView.animate(withDuration: withDuration) {
+ self.naviBarForEditing.alpha = 1
+ self.guideView.transform = .identity
+ self.distanceContainerView.transform = CGAffineTransform(translationX: 0, y: -151)
+ self.completeButton.transform = CGAffineTransform(translationX: 0, y: -112)
+ self.undoButton.transform = CGAffineTransform(translationX: 0, y: -(self.undoButton.frame.height+95))
+ }
+ }
+
+ private func setNotchCoverViewLayout() {
notchCoverView.snp.makeConstraints { make in
var notchHeight = calculateTopInset()
if notchHeight == -44 {
@@ -291,7 +368,9 @@ extension CourseDrawingVC {
}
make.height.equalTo(-notchHeight)
}
-
+ }
+
+ private func setNaviBarLayout() {
naviBar.snp.makeConstraints { make in
make.height.equalTo(56)
}
@@ -299,15 +378,20 @@ extension CourseDrawingVC {
naviBarContainerStackView.snp.makeConstraints { make in
make.leading.top.trailing.equalToSuperview()
}
-
+ }
+
+ private func setMapViewLayout() {
mapView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
-
+ }
+
+ private func setStartMarkStackViewLayout() {
startLabelUIImage.snp.makeConstraints { make in
make.height.equalTo(34)
make.width.equalTo(58)
}
+
startMarkUIImage.snp.makeConstraints { make in
make.height.width.equalTo(65)
}
@@ -318,7 +402,9 @@ extension CourseDrawingVC {
make.centerX.equalToSuperview()
make.centerY.equalToSuperview().offset(-17)
}
-
+ }
+
+ private func setDepartureInfoContainerViewLayout() {
departureInfoContainerView.snp.makeConstraints { make in
make.leading.bottom.trailing.equalToSuperview()
make.height.equalTo(172)
@@ -339,10 +425,12 @@ extension CourseDrawingVC {
make.leading.trailing.equalToSuperview().inset(16)
make.height.equalTo(44)
}
-
+ }
+
+ private func setAboutMapNoticeViewLayout() {
if SelectedInfo.shared.type == .map {
- self.aboutMapNoticeView.addSubview(aboutMapNoticeLabel)
- self.naviBarContainerStackView.addArrangedSubviews(underlineView, aboutMapNoticeView)
+ aboutMapNoticeView.addSubview(aboutMapNoticeLabel)
+ naviBarContainerStackView.addArrangedSubviews(underlineView, aboutMapNoticeView)
underlineView.snp.makeConstraints {
$0.leading.trailing.equalToSuperview()
@@ -359,68 +447,6 @@ extension CourseDrawingVC {
}
}
}
-
- private func setHiddenViewsLayout() {
- view.addSubviews(naviBarForEditing, guideView, distanceContainerView, completeButton, undoButton)
- view.sendSubviewToBack(naviBarForEditing)
-
- naviBarForEditing.snp.makeConstraints { make in
- make.leading.top.trailing.equalTo(view.safeAreaLayoutGuide)
- make.height.equalTo(48)
- }
-
- guideView.snp.makeConstraints { make in
- make.centerY.equalTo(naviBarForEditing.snp.centerY)
- make.leading.equalTo(view.safeAreaLayoutGuide).inset(55)
- make.trailing.equalTo(view.safeAreaLayoutGuide).inset(27)
- }
-
- distanceContainerView.snp.makeConstraints { make in
- make.width.equalTo(96)
- make.height.equalTo(44)
- make.leading.equalTo(view.safeAreaLayoutGuide).inset(16)
- make.top.equalTo(view.snp.bottom)
- }
-
- distanceContainerView.addSubviews(distanceStackView)
-
- distanceStackView.snp.makeConstraints { make in
- make.center.equalToSuperview()
- }
-
- undoButton.snp.makeConstraints { make in
- make.trailing.equalTo(view.safeAreaLayoutGuide)
- make.top.equalTo(view.snp.bottom)
- }
-
- completeButton.snp.makeConstraints { make in
- make.leading.trailing.equalTo(view.safeAreaLayoutGuide).inset(16)
- make.height.equalTo(44)
- make.top.equalTo(view.snp.bottom).offset(34)
- }
- }
-
- private func showHiddenViews(withDuration: TimeInterval = 0) {
- [naviBarForEditing, guideView, distanceContainerView, completeButton, undoButton].forEach { subView in
- view.bringSubviewToFront(subView)
- }
-
- UIView.animate(withDuration: withDuration) {
- let naviBarContainerStackViewHeight = self.naviBarContainerStackView.frame.height
- self.naviBarContainerStackView.transform = CGAffineTransform(translationX: 0, y: -naviBarContainerStackViewHeight)
- self.departureInfoContainerView.transform = CGAffineTransform(translationX: 0, y: 172)
- }
-
- self.guideView.transform = CGAffineTransform(translationX: 0, y: -100)
-
- UIView.animate(withDuration: withDuration) {
- self.naviBarForEditing.alpha = 1
- self.guideView.transform = .identity
- self.distanceContainerView.transform = CGAffineTransform(translationX: 0, y: -151)
- self.completeButton.transform = CGAffineTransform(translationX: 0, y: -112)
- self.undoButton.transform = CGAffineTransform(translationX: 0, y: -(self.undoButton.frame.height+95))
- }
- }
}
// MARK: - Network
@@ -456,7 +482,7 @@ extension CourseDrawingVC {
private func searchLocationTmapAddress(latitude: Double, longitude: Double) {
departureSearchingProvider.request(target: .getLocationTmapAddress(latitude: latitude, longitude: longitude), instance: TmapAddressSearchingResponseDto.self, vc: self) { data in
- self.updateData(model: data.toDepartureLocationModel(latitude: latitude, longitude: longitude))
+ self.updateData(model: data.toDepartureLocationModel(latitude: latitude, longitude: longitude))
}
}
}
diff --git a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift
index e332277c..996a3489 100644
--- a/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift
+++ b/Runnect-iOS/Runnect-iOS/Presentation/CourseStorage/VC/CourseStorageVC.swift
@@ -91,6 +91,8 @@ extension CourseStorageVC {
privateCourseListView.courseDrawButtonTapped.sink { [weak self] in
guard let self = self else { return }
+
+ analyze(buttonName: GAEvent.Button.clickMyStorageCourseDrawingStart) // 내가 그린 코스 코스 그리기 진입
self.tabBarController?.selectedIndex = 0
}.store(in: cancelBag)
@@ -101,11 +103,13 @@ extension CourseStorageVC {
privateCourseListView.cellDidTapped.sink { [weak self] index in
guard let self = self else { return }
+ analyze(buttonName: GAEvent.Button.clickScrapPageStartCourse) // 코스 발견_스크랩코스 상세페이지 시작하기 Event
+
let title = self.privateCourseList[index].title
let runningWaitingVC = RunningWaitingVC()
runningWaitingVC.setData(courseId: self.privateCourseList[index].id, publicCourseId: nil, courseTitle: title)
- /// 코스 이름을 여기서 가져오는 로직
+ /// 코스 이름을 여기서 가져오는 로직
runningWaitingVC.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(runningWaitingVC, animated: true)
}.store(in: cancelBag)
@@ -204,12 +208,12 @@ extension CourseStorageVC {
private func setLayout() {
view.addSubviews(naviBar)
-
+
naviBar.snp.makeConstraints { make in
make.leading.top.trailing.equalTo(view.safeAreaLayoutGuide)
make.height.equalTo(56)
}
-
+
guard UserManager.shared.userType != .visitor else {
self.showSignInRequestEmptyView()
return
diff --git a/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/InfoVC/ActivityRecordInfoVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/InfoVC/ActivityRecordInfoVC.swift
index 148d1a3d..90afa4ea 100644
--- a/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/InfoVC/ActivityRecordInfoVC.swift
+++ b/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/InfoVC/ActivityRecordInfoVC.swift
@@ -293,6 +293,8 @@ extension ActivityRecordInfoVC: UITableViewDataSource {
extension ActivityRecordInfoVC: ListEmptyViewDelegate {
func emptyViewButtonTapped() {
+ analyze(buttonName: GAEvent.Button.clickCourseDrawingInRunningRecord)
+
self.tabBarController?.selectedIndex = 0
}
}
diff --git a/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/InfoVC/UploadedCourseInfoVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/InfoVC/UploadedCourseInfoVC.swift
index 3c69fa85..80ded91c 100644
--- a/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/InfoVC/UploadedCourseInfoVC.swift
+++ b/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/InfoVC/UploadedCourseInfoVC.swift
@@ -68,8 +68,8 @@ final class UploadedCourseInfoVC: UIViewController {
$0.titleLabel?.font = .b5
$0.layer.backgroundColor = UIColor.m3.cgColor
$0.layer.cornerRadius = 11
-// $0.layer.borderColor = UIColor.m1.cgColor
-// $0.layer.borderWidth = 1
+ // $0.layer.borderColor = UIColor.m1.cgColor
+ // $0.layer.borderWidth = 1
}
private lazy var deleteCourseButton = CustomButton(title: "삭제하기").then {
@@ -283,7 +283,7 @@ extension UploadedCourseInfoVC: UICollectionViewDelegate, UICollectionViewDataSo
} else {
cell.selectCell(didSelect: false)
}
-
+
let model = uploadedCourseList[indexPath.item]
let cellTitle = "\(model.departure.region) \(model.departure.city)"
cell.setData(imageURL: model.image, title: cellTitle, location: nil, didLike: nil, isEditMode: isEditMode)
@@ -389,6 +389,8 @@ extension UploadedCourseInfoVC {
extension UploadedCourseInfoVC: ListEmptyViewDelegate {
func emptyViewButtonTapped() {
+ analyze(buttonName: GAEvent.Button.clickCourseUploadInUploadedCourse)
+
let myCourseSelectVC = MyCourseSelectVC()
self.navigationController?.pushViewController(myCourseSelectVC, animated: true)
diff --git a/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/MyPageVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/MyPageVC.swift
index b4918a8b..5f9ad7a5 100644
--- a/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/MyPageVC.swift
+++ b/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/MyPageVC.swift
@@ -14,16 +14,16 @@ import KakaoSDKTalk
import KakaoSDKUser
final class MyPageVC: UIViewController {
-
+
// MARK: - Properties
private var userProvider = Providers.userProvider
let stampNameImageDictionary: [String: UIImage] = GoalRewardInfoModel.stampNameImageDictionary
-
+
var sendEmail = String()
var sendNickname = String()
-
+
// MARK: - UI Components
private lazy var navibar = CustomNavigationBar(self, type: .title).setTitle("마이페이지")
@@ -88,7 +88,7 @@ final class MyPageVC: UIViewController {
let tap = UITapGestureRecognizer(target: self, action: #selector(self.touchUpUploadedCourseRecordInfoView))
$0.addGestureRecognizer(tap)
}
-
+
private lazy var settingView = makeInfoView(title: "설정").then {
let tap = UITapGestureRecognizer(target: self, action: #selector(self.touchUpSettingView))
$0.addGestureRecognizer(tap)
@@ -231,16 +231,19 @@ extension MyPageVC {
extension MyPageVC {
@objc
private func touchUpActivityRecordInfoView() {
+ analyze(buttonName: GAEvent.Button.clickRunningRecord)
pushToActivityRecordInfoVC()
}
@objc
private func touchUpGoalRewardInfoView() {
+ analyze(buttonName: GAEvent.Button.clickGoalReward)
pushToGoalRewardInfoVC()
}
@objc
private func touchUpUploadedCourseRecordInfoView() {
+ analyze(buttonName: GAEvent.Button.clickUploadedCourse)
pushToUploadedCourseInfoVC()
}
@@ -256,7 +259,7 @@ extension MyPageVC {
@objc
private func touchUpkakaoChannelAsk() {
- if let url = TalkApi.shared.makeUrlForChannelChat(channelPublicId: "_hXduG") {
+ if let url = TalkApi.shared.makeUrlForChatChannel(channelPublicId: "_hXduG") {
UIApplication.shared.open(url)
}
}
diff --git a/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/SettingVC/PersonalInfoVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/SettingVC/PersonalInfoVC.swift
index 9aaab093..20fc0680 100644
--- a/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/SettingVC/PersonalInfoVC.swift
+++ b/Runnect-iOS/Runnect-iOS/Presentation/MyPage/VC/SettingVC/PersonalInfoVC.swift
@@ -12,13 +12,13 @@ import SnapKit
import Then
final class PersonalInfoVC: UIViewController {
-
+
// MARK: - Properties
private let userProvider = Providers.userProvider
var email = String()
-
+
// MARK: - UI Components
private lazy var navibar = CustomNavigationBar(self, type: .titleWithLeftButton).setTitle("계정 정보")
@@ -63,11 +63,15 @@ final class PersonalInfoVC: UIViewController {
extension PersonalInfoVC {
@objc
func touchUpLogoutView() {
+ analyze(buttonName: GAEvent.Button.clickTryLogout)
+
pushToLogoutVC()
}
@objc
func touchUpDeleteAccountView() {
+ analyze(buttonName: GAEvent.Button.clickTryWithdraw)
+
pushToDeleteAccountVC()
}
}
@@ -130,17 +134,21 @@ extension PersonalInfoVC {
private func logout() {
UserManager.shared.logout()
+ analyze(screenName: GAEvent.View.viewSuccessLogout)
+
self.showSplashVC()
}
private func deleteUserDidComplete() {
+ analyze(screenName: GAEvent.View.viewSuccessWithdraw)
+
self.logout()
}
private func requestAppleToken() {
let appleIDProvider = ASAuthorizationAppleIDProvider()
let request = appleIDProvider.createRequest()
-
+
let authorizationController = ASAuthorizationController(authorizationRequests: [request])
authorizationController.delegate = self
authorizationController.presentationContextProvider = self
@@ -287,21 +295,21 @@ extension PersonalInfoVC: ASAuthorizationControllerPresentationContextProviding,
/// Apple ID 연동 성공 시
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
- switch authorization.credential {
- /// Apple ID
- case let appleIDCredential as ASAuthorizationAppleIDCredential:
-
- /// 계정 정보 가져오기
- let userIdentifier = appleIDCredential.user
- let idToken = appleIDCredential.identityToken!
- guard let tokenStr = String(data: idToken, encoding: .utf8) else { return }
-
- print("User ID : \(userIdentifier)")
- print("token : \(String(describing: tokenStr))")
-
- self.deleteUser(appleToken: tokenStr)
- default:
- break
+ switch authorization.credential {
+ /// Apple ID
+ case let appleIDCredential as ASAuthorizationAppleIDCredential:
+
+ /// 계정 정보 가져오기
+ let userIdentifier = appleIDCredential.user
+ let idToken = appleIDCredential.identityToken!
+ guard let tokenStr = String(data: idToken, encoding: .utf8) else { return }
+
+ print("User ID : \(userIdentifier)")
+ print("token : \(String(describing: tokenStr))")
+
+ self.deleteUser(appleToken: tokenStr)
+ default:
+ break
}
}
diff --git a/Runnect-iOS/Runnect-iOS/Presentation/Running/VC/RunningRecordVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/Running/VC/RunningRecordVC.swift
index 2cf56c18..552ce207 100644
--- a/Runnect-iOS/Runnect-iOS/Presentation/Running/VC/RunningRecordVC.swift
+++ b/Runnect-iOS/Runnect-iOS/Presentation/Running/VC/RunningRecordVC.swift
@@ -305,6 +305,7 @@ extension RunningRecordVC {
case .success(let result):
let status = result.statusCode
if 200..<300 ~= status {
+ analyze(buttonName: GAEvent.Button.clickStoreRunningTracking)
self.showToastOnWindow(text: "저장한 러닝 기록은 마이페이지에서 볼 수 있어요.")
self.navigationController?.popToRootViewController(animated: true)
}
diff --git a/Runnect-iOS/Runnect-iOS/Presentation/Running/VC/RunningWaitingVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/Running/VC/RunningWaitingVC.swift
index c712e77c..2aba81c8 100644
--- a/Runnect-iOS/Runnect-iOS/Presentation/Running/VC/RunningWaitingVC.swift
+++ b/Runnect-iOS/Runnect-iOS/Presentation/Running/VC/RunningWaitingVC.swift
@@ -323,8 +323,10 @@ extension RunningWaitingVC {
switch item {
case "수정하기":
+ analyze(buttonName: GAEvent.Button.clickMyStorageTryModify)
ModifyCourseTitle()
case "삭제하기":
+ analyze(buttonName: GAEvent.Button.clickMyStorageTryRemove)
let deleteAlertVC = RNAlertVC(description: "러닝 기록을 정말로 삭제하시겠어요?").setButtonTitle("취소", "삭제하기")
deleteAlertVC.modalPresentationStyle = .overFullScreen
deleteAlertVC.rightButtonTapAction = {
diff --git a/Runnect-iOS/Runnect-iOS/Presentation/SignIn/VC/SignInSocialLoginVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/SignIn/VC/SignInSocialLoginVC.swift
index d5c69d92..b6511707 100644
--- a/Runnect-iOS/Runnect-iOS/Presentation/SignIn/VC/SignInSocialLoginVC.swift
+++ b/Runnect-iOS/Runnect-iOS/Presentation/SignIn/VC/SignInSocialLoginVC.swift
@@ -218,7 +218,11 @@ extension SignInSocialLoginVC: ASAuthorizationControllerPresentationContextProvi
switch result {
case .success(let type):
self?.analyze(buttonName: GAEvent.Button.clickAppleLogin)
- type == "Signup" ? self?.pushToNickNameSetUpVC() : self?.pushToTabBarController()
+ if type == "Signup" {
+ self?.pushToNickNameSetUpVC()
+ } else {
+ self?.pushToTabBarController()
+ }
case .failure(let error):
print(error)
self?.showNetworkFailureToast()
diff --git a/Runnect-iOS/Runnect-iOS/Presentation/TabBar/TaBarController.swift b/Runnect-iOS/Runnect-iOS/Presentation/TabBar/TaBarController.swift
index 208d54cf..bf72afe2 100644
--- a/Runnect-iOS/Runnect-iOS/Presentation/TabBar/TaBarController.swift
+++ b/Runnect-iOS/Runnect-iOS/Presentation/TabBar/TaBarController.swift
@@ -13,6 +13,7 @@ final class TabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
+ delegate = self
setUI()
setTabBarControllers()
}
@@ -32,21 +33,21 @@ extension TabBarController {
private func setTabBarControllers() {
let courseDrawingNVC = templateNavigationController(title: "코스 그리기",
- unselectedImage: ImageLiterals.icCourseDraw,
- selectedImage: ImageLiterals.icCourseDrawFill,
- rootViewController: CourseDrawingHomeVC())
+ unselectedImage: ImageLiterals.icCourseDraw,
+ selectedImage: ImageLiterals.icCourseDrawFill,
+ rootViewController: CourseDrawingHomeVC())
let courseStorageNVC = templateNavigationController(title: "보관함",
- unselectedImage: ImageLiterals.icStorage,
- selectedImage: ImageLiterals.icStorageFill,
- rootViewController: CourseStorageVC())
+ unselectedImage: ImageLiterals.icStorage,
+ selectedImage: ImageLiterals.icStorageFill,
+ rootViewController: CourseStorageVC())
let courseDiscoveryNVC = templateNavigationController(title: "코스 발견",
- unselectedImage: ImageLiterals.icCourseDiscover,
- selectedImage: ImageLiterals.icCourseDiscoverFill,
- rootViewController: CourseDiscoveryVC())
+ unselectedImage: ImageLiterals.icCourseDiscover,
+ selectedImage: ImageLiterals.icCourseDiscoverFill,
+ rootViewController: CourseDiscoveryVC())
let myPageNVC = templateNavigationController(title: "마이페이지",
- unselectedImage: ImageLiterals.icMypage,
- selectedImage: ImageLiterals.icMypageFill,
- rootViewController: MyPageVC())
+ unselectedImage: ImageLiterals.icMypage,
+ selectedImage: ImageLiterals.icMypageFill,
+ rootViewController: MyPageVC())
viewControllers = [courseDrawingNVC, courseStorageNVC, courseDiscoveryNVC, myPageNVC]
}
@@ -59,5 +60,23 @@ extension TabBarController {
nav.navigationBar.isHidden = true
return nav
}
-
+}
+
+extension TabBarController: UITabBarControllerDelegate {
+ func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
+ guard let title = viewController.title else { return }
+
+ switch title {
+ case "코스 그리기":
+ analyze(buttonName: GAEvent.Button.clickCourseDrawingTabBar)
+ case "보관함":
+ analyze(buttonName: GAEvent.Button.clickStorageTabBar)
+ case "코스 발견":
+ analyze(buttonName: GAEvent.Button.clickCourseDiscoveryTabBar)
+ case "마이페이지":
+ analyze(buttonName: GAEvent.Button.clickMyPageTabBar)
+ default:
+ break
+ }
+ }
}
diff --git a/Runnect-iOS/Runnect-iOS/Presentation/UserProfile/UserProfileVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/UserProfile/UserProfileVC.swift
index 6b25dc48..881c264d 100644
--- a/Runnect-iOS/Runnect-iOS/Presentation/UserProfile/UserProfileVC.swift
+++ b/Runnect-iOS/Runnect-iOS/Presentation/UserProfile/UserProfileVC.swift
@@ -45,6 +45,7 @@ final class UserProfileVC: UIViewController {
setNavigationBar()
setDelegate()
setLayout()
+ analyze(screenName: GAEvent.View.viewUserProfile)
}
override func viewWillAppear(_ animated: Bool) {
diff --git a/Runnect-iOS/fastlane/Appfile b/Runnect-iOS/fastlane/Appfile
index 82aa07e8..83428cd7 100644
--- a/Runnect-iOS/fastlane/Appfile
+++ b/Runnect-iOS/fastlane/Appfile
@@ -2,7 +2,7 @@ app_identifier("com.runnect.Runnect-iOS") # The bundle identifier of your app
apple_id(ENV["APPLE_ID"]) # Your Apple Developer Portal username
itc_team_id("125287287") # App Store Connect Team ID
-team_id("9K86FQHDLU") # Developer Portal Team ID
+team_id("8Q4H7X3Q58") # Developer Portal Team ID
# For more information about the Appfile, see:
# https://docs.fastlane.tools/advanced/#appfile