Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Setting] #4 - 프로젝트 세팅 #5

Merged
merged 3 commits into from
Dec 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Runnect-iOS/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ target 'Runnect-iOS' do
pod 'Kingfisher', '~> 7.0'
pod 'SnapKit', '~> 5.6.0'
pod 'Moya', '~> 15.0'
pod 'Then'


# Pods for Runnect-iOS
Expand Down
6 changes: 5 additions & 1 deletion Runnect-iOS/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ PODS:
- NMapsMap (3.16.1):
- NMapsGeometry
- SnapKit (5.6.0)
- Then (3.0.0)

DEPENDENCIES:
- Kingfisher (~> 7.0)
- Moya (~> 15.0)
- NMapsMap
- SnapKit (~> 5.6.0)
- Then

SPEC REPOS:
trunk:
Expand All @@ -24,6 +26,7 @@ SPEC REPOS:
- NMapsGeometry
- NMapsMap
- SnapKit
- Then

SPEC CHECKSUMS:
Alamofire: 4e95d97098eacb88856099c4fc79b526a299e48c
Expand All @@ -32,7 +35,8 @@ SPEC CHECKSUMS:
NMapsGeometry: 53c573ead66466681cf123f99f698dc8071a4b83
NMapsMap: 926c3a303d381a24bec8da3cd6e198f50af93ae9
SnapKit: e01d52ebb8ddbc333eefe2132acf85c8227d9c25
Then: 844265ae87834bbe1147d91d5d41a404da2ec27d

PODFILE CHECKSUM: f23513cb80e72754bbf29355e1160abe4b35c783
PODFILE CHECKSUM: bec9bfadf42d34524a80ccc0e46829d1fe943ddb

COCOAPODS: 1.11.3
16 changes: 16 additions & 0 deletions Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
CE4545CD295D7AF4003201E1 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE4545CC295D7AF4003201E1 /* ViewController.swift */; };
CE4545D2295D7AF5003201E1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CE4545D1295D7AF5003201E1 /* Assets.xcassets */; };
CE4545D5295D7AF5003201E1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CE4545D3295D7AF5003201E1 /* LaunchScreen.storyboard */; };
CE58759E29601476005D967E /* LoadingIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE58759D29601476005D967E /* LoadingIndicator.swift */; };
CE5875A029601500005D967E /* Toast.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE58759F29601500005D967E /* Toast.swift */; };
CE5875A2296015A2005D967E /* NetworkLoggerPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5875A1296015A2005D967E /* NetworkLoggerPlugin.swift */; };
CE5875A4296015D2005D967E /* Encodable+.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5875A3296015D2005D967E /* Encodable+.swift */; };
CE6655BF295D82E200C64E12 /* .gitkeep in Resources */ = {isa = PBXBuildFile; fileRef = CE6655BE295D82E200C64E12 /* .gitkeep */; };
CE6655C8295D849F00C64E12 /* StringLiterals.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6655C7295D849F00C64E12 /* StringLiterals.swift */; };
CE6655CA295D84DD00C64E12 /* UserDefaultKeyList.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6655C9295D84DD00C64E12 /* UserDefaultKeyList.swift */; };
Expand Down Expand Up @@ -63,6 +67,10 @@
CE4545D1295D7AF5003201E1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
CE4545D4295D7AF5003201E1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
CE4545D6295D7AF5003201E1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
CE58759D29601476005D967E /* LoadingIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingIndicator.swift; sourceTree = "<group>"; };
CE58759F29601500005D967E /* Toast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toast.swift; sourceTree = "<group>"; };
CE5875A1296015A2005D967E /* NetworkLoggerPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkLoggerPlugin.swift; sourceTree = "<group>"; };
CE5875A3296015D2005D967E /* Encodable+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Encodable+.swift"; sourceTree = "<group>"; };
CE6655B8295D81C900C64E12 /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
CE6655BC295D82CF00C64E12 /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
CE6655BD295D82D800C64E12 /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
Expand Down Expand Up @@ -241,6 +249,7 @@
isa = PBXGroup;
children = (
CE6655BD295D82D800C64E12 /* .gitkeep */,
CE5875A1296015A2005D967E /* NetworkLoggerPlugin.swift */,
);
path = Foundation;
sourceTree = "<group>";
Expand Down Expand Up @@ -270,6 +279,8 @@
CE66560D295D92A500C64E12 /* setStatusBarBackgroundColor.swift */,
CE66560F295D92C200C64E12 /* setTextLineHeight.swift */,
CE665611295D92E400C64E12 /* UserDefaultWrapper.swift */,
CE58759D29601476005D967E /* LoadingIndicator.swift */,
CE58759F29601500005D967E /* Toast.swift */,
);
path = Utils;
sourceTree = "<group>";
Expand Down Expand Up @@ -368,6 +379,7 @@
CE6655D6295D86F900C64E12 /* String+.swift */,
CE6655D8295D871B00C64E12 /* URL+.swift */,
CE665609295D924A00C64E12 /* Result+.swift */,
CE5875A3296015D2005D967E /* Encodable+.swift */,
);
path = "Foundation+";
sourceTree = "<group>";
Expand Down Expand Up @@ -539,10 +551,13 @@
CE66560A295D924A00C64E12 /* Result+.swift in Sources */,
CE66560E295D92A500C64E12 /* setStatusBarBackgroundColor.swift in Sources */,
CE6655D7295D86F900C64E12 /* String+.swift in Sources */,
CE58759E29601476005D967E /* LoadingIndicator.swift in Sources */,
CE5875A2296015A2005D967E /* NetworkLoggerPlugin.swift in Sources */,
CE4545C9295D7AF4003201E1 /* AppDelegate.swift in Sources */,
CE6655C8295D849F00C64E12 /* StringLiterals.swift in Sources */,
CE6655E0295D87D200C64E12 /* UIDevice+.swift in Sources */,
CE6655E8295D889600C64E12 /* UISwitch+.swift in Sources */,
CE5875A029601500005D967E /* Toast.swift in Sources */,
CE6655F6295D90B600C64E12 /* addToolBar.swift in Sources */,
CE6655F0295D891B00C64E12 /* UITextView+.swift in Sources */,
CE6655EE295D88E600C64E12 /* UITextField+.swift in Sources */,
Expand All @@ -560,6 +575,7 @@
CE665612295D92E400C64E12 /* UserDefaultWrapper.swift in Sources */,
CE665610295D92C200C64E12 /* setTextLineHeight.swift in Sources */,
CE6655E2295D87EB00C64E12 /* UIImage+.swift in Sources */,
CE5875A4296015D2005D967E /* Encodable+.swift in Sources */,
CE6655D2295D862A00C64E12 /* Publisher+Driver.swift in Sources */,
CE6655E6295D887F00C64E12 /* UIStackView+.swift in Sources */,
CE6655CA295D84DD00C64E12 /* UserDefaultKeyList.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// Encodable+.swift
// Runnect-iOS
//
// Created by sejin on 2022/12/31.
//

import Foundation

// MARK: - Encodable Extension

extension Encodable {

func asParameter() throws -> [String: Any] {
let data = try JSONEncoder().encode(self)
guard let dictionary = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
as? [String: Any] else {
throw NSError()
}

return dictionary
}
}
36 changes: 36 additions & 0 deletions Runnect-iOS/Runnect-iOS/Global/Utils/LoadingIndicator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// LoadingIndicator.swift
// Runnect-iOS
//
// Created by sejin on 2022/12/31.
//

import UIKit

class LoadingIndicator {
static func showLoading() {
DispatchQueue.main.async {
// 최상단에 있는 window 객체 획득
guard let window = UIApplication.shared.windows.last else { return }

let loadingIndicatorView: UIActivityIndicatorView
if let existedView = window.subviews.first(where: { $0 is UIActivityIndicatorView }) as? UIActivityIndicatorView {
loadingIndicatorView = existedView
} else {
loadingIndicatorView = UIActivityIndicatorView(style: .large)
loadingIndicatorView.frame = window.frame
loadingIndicatorView.color = .lightGray
window.addSubview(loadingIndicatorView)
}

loadingIndicatorView.startAnimating()
}
}

static func hideLoading() {
DispatchQueue.main.async {
guard let window = UIApplication.shared.windows.last else { return }
window.subviews.filter({ $0 is UIActivityIndicatorView }).forEach { $0.removeFromSuperview() }
}
}
}
61 changes: 61 additions & 0 deletions Runnect-iOS/Runnect-iOS/Global/Utils/Toast.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//
// Toast.swift
// Runnect-iOS
//
// Created by sejin on 2022/12/31.
//

import UIKit

import SnapKit

public extension UIViewController {
func showToast(message: String) {
Toast.show(message: message, view: self.view, safeAreaBottomInset: self.safeAreaBottomInset())
}
}

public class Toast {
public static func show(message: String, view: UIView, safeAreaBottomInset: CGFloat = 0) {

let toastContainer = UIView()
let toastLabel = UILabel()

toastContainer.backgroundColor = .lightGray
toastContainer.alpha = 1
toastContainer.layer.cornerRadius = 9
toastContainer.clipsToBounds = true
toastContainer.isUserInteractionEnabled = false

toastLabel.textColor = .white
toastLabel.textAlignment = .center
toastLabel.text = message
toastLabel.clipsToBounds = true
toastLabel.numberOfLines = 0
toastLabel.sizeToFit()

toastContainer.addSubview(toastLabel)
view.addSubview(toastContainer)

toastContainer.snp.makeConstraints {
$0.centerX.equalToSuperview()
$0.bottom.equalToSuperview().inset(safeAreaBottomInset+40)
$0.width.equalTo(100)
$0.height.equalTo(44)
}

toastLabel.snp.makeConstraints {
$0.center.equalToSuperview()
}

UIView.animate(withDuration: 0.4, delay: 0.0, options: .curveEaseIn, animations: {
toastContainer.alpha = 1.0
}, completion: { _ in
UIView.animate(withDuration: 0.4, delay: 1.0, options: .curveEaseOut, animations: {
toastContainer.alpha = 0.0
}, completion: {_ in
toastContainer.removeFromSuperview()
})
})
}
}
8 changes: 4 additions & 4 deletions Runnect-iOS/Runnect-iOS/Global/Utils/adjusted+.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,24 @@ import UIKit

extension CGFloat {
var adjusted: CGFloat {
let ratio: CGFloat = UIScreen.main.bounds.width / 375
let ratio: CGFloat = UIScreen.main.bounds.width / 390
return self * ratio
}

var adjustedH: CGFloat {
let ratio: CGFloat = UIScreen.main.bounds.height / 812
let ratio: CGFloat = UIScreen.main.bounds.height / 844
return self * ratio
}
}

extension Double {
var adjusted: Double {
let ratio: Double = Double(UIScreen.main.bounds.width / 375)
let ratio: Double = Double(UIScreen.main.bounds.width / 390)
return self * ratio
}

var adjustedH: Double {
let ratio: Double = Double(UIScreen.main.bounds.height / 812)
let ratio: Double = Double(UIScreen.main.bounds.height / 844)
return self * ratio
}
}
8 changes: 8 additions & 0 deletions Runnect-iOS/Runnect-iOS/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string>위치 정보 권한이 필요합니다.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>위치 정보 권한이 필요합니다.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>위치 정보 권한이 필요합니다.</string>
<key>NMFClientId</key>
<string>1vyblfmq7l</string>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
Expand Down
122 changes: 122 additions & 0 deletions Runnect-iOS/Runnect-iOS/Network/Foundation/NetworkLoggerPlugin.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
//
// NetworkLoggerPlugin.swift
// Runnect-iOS
//
// Created by sejin on 2022/12/31.
//

import Foundation

import Moya

/// Logs network activity (outgoing requests and incoming responses).
public final class NetworkLoggerPlugin: PluginType {
fileprivate let loggerId = "Moya_Logger"
fileprivate let dateFormatString = "dd/MM/yyyy HH:mm:ss"
fileprivate let dateFormatter = DateFormatter()
fileprivate let separator = ", "
fileprivate let terminator = "\n"
fileprivate let cURLTerminator = "\\\n"
fileprivate let output: (_ separator: String, _ terminator: String, _ items: Any...) -> Void
fileprivate let requestDataFormatter: ((Data) -> (String))?
fileprivate let responseDataFormatter: ((Data) -> (Data))?

/// A Boolean value determing whether response body data should be logged.
public let isVerbose: Bool
public let cURL: Bool

/// Initializes a NetworkLoggerPlugin.
public init(verbose: Bool = true, cURL: Bool = false, output: ((_ separator: String, _ terminator: String, _ items: Any...) -> Void)? = nil, requestDataFormatter: ((Data) -> (String))? = nil, responseDataFormatter: ((Data) -> (Data))? = nil) {
self.cURL = cURL
self.isVerbose = verbose
self.output = output ?? NetworkLoggerPlugin.reversedPrint
self.requestDataFormatter = requestDataFormatter
self.responseDataFormatter = responseDataFormatter
}

public func willSend(_ request: RequestType, target: TargetType) {
if let request = request as? CustomDebugStringConvertible, cURL {
output(separator, terminator, request.debugDescription)
return
}
outputItems(logNetworkRequest(request.request as URLRequest?))
}

public func didReceive(_ result: Result<Moya.Response, MoyaError>, target: TargetType) {
if case .success(let response) = result {
outputItems(logNetworkResponse(response.response, data: response.data, target: target))
} else {
print(result)
outputItems(logNetworkResponse(nil, data: nil, target: target))
}
}

fileprivate func outputItems(_ items: [String]) {
if isVerbose {
items.forEach { output(separator, terminator, $0) }
} else {
output(separator, terminator, items)
}
}
}

private extension NetworkLoggerPlugin {

var date: String {
dateFormatter.dateFormat = dateFormatString
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
return dateFormatter.string(from: Date())
}

func format(_ loggerId: String, date: String, identifier: String, message: String) -> String {
return "\(loggerId): [\(date)] \(identifier): \(message)"
}

func logNetworkRequest(_ request: URLRequest?) -> [String] {

var output = [String]()

output += [format(loggerId, date: date, identifier: "Request", message: request?.description ?? "(invalid request)")]

if let headers = request?.allHTTPHeaderFields {
output += [format(loggerId, date: date, identifier: "Request Headers", message: headers.description)]
}

if let bodyStream = request?.httpBodyStream {
output += [format(loggerId, date: date, identifier: "Request Body Stream", message: bodyStream.description)]
}

if let httpMethod = request?.httpMethod {
output += [format(loggerId, date: date, identifier: "HTTP Request Method", message: httpMethod)]
}

if let body = request?.httpBody, let stringOutput = requestDataFormatter?(body) ?? String(data: body, encoding: .utf8), isVerbose {
output += [format(loggerId, date: date, identifier: "Request Body", message: stringOutput)]
}

return output
}

func logNetworkResponse(_ response: HTTPURLResponse?, data: Data?, target: TargetType) -> [String] {
guard let response = response else {
return [format(loggerId, date: date, identifier: "Response", message: "Received empty network response for \(target).")]
}

var output = [String]()
output += [format(loggerId, date: date, identifier: "Response", message: response.description)]

if let data = data, let stringData = String(data: responseDataFormatter?(data) ?? data, encoding: String.Encoding.utf8), isVerbose {
output += [stringData]
}

return output
}
}

fileprivate extension NetworkLoggerPlugin {
static func reversedPrint(_ separator: String, terminator: String, items: Any...) {
for item in items {
print(item, separator: separator, terminator: terminator)
}
}
}