Skip to content
Merged
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,4 @@ iOSInjectionProject/

# End of https://www.toptal.com/developers/gitignore/api/xcode,swift,cocoapods
.DS_Store
Config.swift
240 changes: 234 additions & 6 deletions Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,9 @@ extension UIViewController {
func dismissKeyboard() {
view.endEditing(true)
}

/// tabBar 숨기기
func hideTabBar(wantsToHide: Bool) {
self.tabBarController?.tabBar.isHidden = wantsToHide
}
}
6 changes: 5 additions & 1 deletion Runnect-iOS/Runnect-iOS/Global/Supports/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import UIKit

import NMapsMap

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

Expand All @@ -16,7 +18,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.

NMFAuthManager.shared().clientId = Config.naverMapClientId

return true
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ final class CustomNavigationBar: UIView {
self.setUI(type)
self.setLayout(type)
self.setAddTarget()
self.setDelegate()
}

required init?(coder: NSCoder) {
Expand All @@ -70,6 +71,10 @@ extension CustomNavigationBar {
self.rightButton.addTarget(self, action: #selector(searchLocation), for: .touchUpInside)
}

private func setDelegate() {
textField.delegate = self
}

@discardableResult
func setTitle(_ title: String) -> Self {
self.leftTitleLabel.text = title
Expand Down Expand Up @@ -125,6 +130,12 @@ extension CustomNavigationBar {
self.rightButton.isHidden = true
return self
}

@discardableResult
func hideKeyboard() -> Self {
self.textField.resignFirstResponder()
return self
}
}

// MARK: - @objc Function
Expand All @@ -136,6 +147,7 @@ extension CustomNavigationBar {

@objc private func searchLocation() {
guard let text = textField.text else { return }
self.hideKeyboard()
delegate?.searchButtonDidTap(text: text)
}

Expand All @@ -152,6 +164,7 @@ extension CustomNavigationBar {

extension CustomNavigationBar {
private func setUI(_ type: NaviType) {
self.textField.returnKeyType = .search
self.naviType = type
self.backgroundColor = .m4

Expand Down Expand Up @@ -233,3 +246,14 @@ extension CustomNavigationBar {
}
}
}

// MARK: - UITextFieldDelegate

extension CustomNavigationBar: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
guard let text = textField.text else { return true }
delegate?.searchButtonDidTap(text: text)
self.hideKeyboard()
return true
}
}
4 changes: 4 additions & 0 deletions Runnect-iOS/Runnect-iOS/Global/Utils/Toast.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ public extension UIViewController {
func showToast(message: String) {
Toast.show(message: message, view: self.view, safeAreaBottomInset: self.safeAreaBottomInset())
}

func showNetworkFailureToast() {
showToast(message: "네트워크 통신 실패")
}
}

public class Toast {
Expand Down
12 changes: 12 additions & 0 deletions Runnect-iOS/Runnect-iOS/Global/Utils/convertLocationObject.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,15 @@ extension NMGLatLng {
return CLLocation(latitude: lat, longitude: lng)
}
}

extension DepartureLocationModel {
func toNMGLatLng() -> NMGLatLng {
guard let lat = Double(self.latitude),
let lng = Double(self.longitude)
else {
return NMGLatLng(lat: 37.52901832956373, lng: 126.9136196847032)
}

return NMGLatLng(lat: lat, lng: lng)
}
}
2 changes: 0 additions & 2 deletions Runnect-iOS/Runnect-iOS/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
<string>위치 정보 권한이 필요합니다.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>위치 정보 권한이 필요합니다.</string>
<key>NMFClientId</key>
<string>1vyblfmq7l</string>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// DepartureSearchingResponseDto.swift
// Runnect-iOS
//
// Created by sejin on 2023/01/06.
//

import Foundation

// MARK: - DepartureSearchingResponseDto

struct DepartureSearchingResponseDto: Codable {
let documents: [KakaoAddressResult]
}

// MARK: - KakaoAddressResult

struct KakaoAddressResult: Codable {
let addressName, categoryGroupCode, categoryGroupName, categoryName: String
let distance, id, phone, placeName: String
let placeURL: String
let roadAddressName, latitude, longitude: String

enum CodingKeys: String, CodingKey {
case addressName = "address_name"
case categoryGroupCode = "category_group_code"
case categoryGroupName = "category_group_name"
case categoryName = "category_name"
case distance, id, phone
case placeName = "place_name"
case placeURL = "place_url"
case roadAddressName = "road_address_name"
case longitude = "x"
case latitude = "y"
}

func toDepartureLocationModel() -> DepartureLocationModel {
return DepartureLocationModel(departureName: self.placeName, departureAddress: self.addressName, latitude: self.latitude, longitude: self.longitude)
}
}
Empty file.
Empty file.
Empty file.
Empty file.
19 changes: 19 additions & 0 deletions Runnect-iOS/Runnect-iOS/Network/Foundation/BaseResponse.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// BaseResponse.swift
// Runnect-iOS
//
// Created by sejin on 2023/01/06.
//

import Foundation

struct BaseResponse<T: Codable>: Codable {
let status: Int
let success: Bool
let message: String
let data: T?
}

/// data가 없는 API 통신에서 사용할 BlankData 구조체
struct BlankData: Codable {
}
28 changes: 28 additions & 0 deletions Runnect-iOS/Runnect-iOS/Network/Foundation/NetworkHelper.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// NetworkHelper.swift
// Runnect-iOS
//
// Created by sejin on 2023/01/06.
//

import Foundation

import Moya

struct NetworkHelper {
private init() {}

// 상태 코드와 데이터, decoding type을 가지고 통신의 결과를 핸들링하는 함수
static func parseJSON<T: Codable> (by statusCode: Int, data: Data, type: T.Type) -> NetworkResult<Any> {
let decoder = JSONDecoder()

guard let decodedData = try? decoder.decode(BaseResponse<T>.self, from: data) else { return .pathErr("pathErr") }

switch statusCode {
case 200..<300: return .success(decodedData.data as Any)
case 400..<500: return .requestErr(decodedData.data as Any)
case 500..<600: return .serverErr
default: return .networkFail
}
}
}
16 changes: 16 additions & 0 deletions Runnect-iOS/Runnect-iOS/Network/Foundation/NetworkResult.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// NetworkResult.swift
// Runnect-iOS
//
// Created by sejin on 2023/01/06.
//

import Foundation

enum NetworkResult<T> {
case success(T) // 서버 통신 성공했을 때
case requestErr(T) // 요청 에러 발생했을 때
case pathErr(T) // 경로 에러 발생했을 때
case serverErr // 서버의 내부 에러가 발생했을 때
case networkFail // 네트워크 연결 실패했을 때
}
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// DepartureLocationModel.swift
// Runnect-iOS
//
// Created by sejin on 2023/01/06.
//

import Foundation

struct DepartureLocationModel {
let departureName: String
let departureAddress: String
let latitude: String
let longitude: String
}
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// DepartureSearchingRouter.swift
// Runnect-iOS
//
// Created by sejin on 2023/01/06.
//

import Foundation

import Moya

enum DepartureSearchingRouter {
case getAddress(keyword: String)
}

extension DepartureSearchingRouter: TargetType {
var baseURL: URL {
guard let url = URL(string: Config.kakaoAddressBaseURL) else {
fatalError("baseURL could not be configured")
}

return url
}

var path: String {
switch self {
case .getAddress:
return "/keyword.json"
}
}

var method: Moya.Method {
switch self {
case .getAddress:
return .get
}
}

var task: Moya.Task {
switch self {
case .getAddress(let keyword):
return .requestParameters(parameters: ["query": keyword], encoding: URLEncoding.default)
}
}

var headers: [String: String]? {
return ["Content-Type": "application/json",
"Authorization": "KakaoAK \(Config.kakaoRestAPIKey)"]
}
}
Empty file.
Empty file.
Empty file.
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ extension CourseDrawingHomeVC {
extension CourseDrawingHomeVC {
@objc private func pushToDepartureSearchVC() {
let departureSearchVC = DepartureSearchVC()
departureSearchVC.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(departureSearchVC, animated: true)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import Combine
final class CourseDrawingVC: UIViewController {

// MARK: - Properties

private var departureLocationModel: DepartureLocationModel?

var pathImage: UIImage?

private var cancelBag = CancelBag()
Expand All @@ -36,7 +39,7 @@ final class CourseDrawingVC: UIViewController {
$0.axis = .vertical
}

private let mapView = RNMapView().makeStartMarkerAtUserLocation()
private let mapView = RNMapView()

private let departureLocationLabel = UILabel().then {
$0.font = .b1
Expand Down Expand Up @@ -107,6 +110,14 @@ final class CourseDrawingVC: UIViewController {
// MARK: - Methods

extension CourseDrawingVC {
func setData(model: DepartureLocationModel) {
self.departureLocationModel = model

self.mapView.makeStartMarker(at: model.toNMGLatLng(), withCameraMove: true)
self.departureLocationLabel.text = model.departureName
self.departureDetailLocationLabel.text = model.departureAddress
}

private func setAddTarget() {
self.decideDepartureButton.addTarget(self, action: #selector(decideDepartureButtonDidTap), for: .touchUpInside)
self.undoButton.addTarget(self, action: #selector(undoButtonDidTap), for: .touchUpInside)
Expand All @@ -133,8 +144,8 @@ extension CourseDrawingVC {
}.store(in: cancelBag)
}

private func setNavigationGesture(_ enabled: Bool) {
navigationController?.interactivePopGestureRecognizer?.isEnabled = enabled
private func setNavigationGesture(_ isEnabled: Bool) {
navigationController?.interactivePopGestureRecognizer?.isEnabled = isEnabled
}

private func presentAlertVC() {
Expand Down
Loading