diff --git a/.gitignore b/.gitignore
index e69de29..504faf8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+WebAppUIKitBase/SecretCode.swift
\ No newline at end of file
diff --git a/WebAppUIKitBase/Base.lproj/Main.storyboard b/WebAppUIKitBase/Base.lproj/Main.storyboard
deleted file mode 100644
index 25a7638..0000000
--- a/WebAppUIKitBase/Base.lproj/Main.storyboard
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/WebAppUIKitBase/Common/AppDelegate.swift b/WebAppUIKitBase/Common/AppDelegate.swift
new file mode 100644
index 0000000..4dd12c0
--- /dev/null
+++ b/WebAppUIKitBase/Common/AppDelegate.swift
@@ -0,0 +1,33 @@
+//
+// AppDelegate.swift
+// WebAppUIKitBase
+//
+// Created by Sean Kim on 10/21/24.
+//
+
+import UIKit
+
+@main
+class AppDelegate: UIResponder, UIApplicationDelegate {
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+ // Override point for customization after application launch.
+ return true
+ }
+
+ // MARK: UISceneSession Lifecycle
+
+ func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
+ // Called when a new scene session is being created.
+ // Use this method to select a configuration to create the new scene with.
+ return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
+ }
+
+ func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
+ // Called when the user discards a scene session.
+ // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
+ // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
+ }
+
+
+}
+
diff --git a/WebAppUIKitBase/Common/CommonUtils.swift b/WebAppUIKitBase/Common/CommonUtils.swift
new file mode 100644
index 0000000..f62c8e7
--- /dev/null
+++ b/WebAppUIKitBase/Common/CommonUtils.swift
@@ -0,0 +1,8 @@
+//
+// CommonUtils.swift
+// WebAppUIKitBase
+//
+// Created by Sean Kim on 10/21/24.
+//
+
+import Foundation
diff --git a/WebAppUIKitBase/Common/Prefix.swift b/WebAppUIKitBase/Common/Prefix.swift
new file mode 100644
index 0000000..e9c4a3b
--- /dev/null
+++ b/WebAppUIKitBase/Common/Prefix.swift
@@ -0,0 +1,440 @@
+//
+// SwiftUI_Prefix.swift
+// PersonalHealthDiary
+//
+// Created by Sean Kim on 2/20/24.
+//
+import SwiftUI
+
+// MARK: - TYPEALIAS
+typealias VOID_TO_VOID = () -> ()
+
+// MARK: - VARIABLE
+public var APPSTORE_URL = "https://itunes.apple.com/app/"
+public var KEYBOARD_UP_HEIGHT: CGFloat = 46.0
+
+enum Compare: Int{
+ case bigger = 0
+ case smaller
+ case equal
+ case error
+}
+
+// MARK: - FUNCTION
+/// print 를 조금 더 자세하게 표기해주는 함수
+public func printLog(_ object: T, _ file: String = #file, _ function: String = #function, _ line: Int = #line){
+#if DEBUG
+ let dateString = Date().convertString("yyyy/MM/dd HH:mm:ss:SSS")
+ Swift.print(
+// """
+// __________ __________
+// |* TIME = [\(dateString)] || FILE = [\(file.lastPathComponent)]
+// | NAME = [\(function)] || LINE = [\(line)]
+// |>>> PRINT = \(object)
+//  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
+// """
+ """
+ __________ __________ __________ __________
+ * LOCATION : [\(file.lastPathComponent) : \(line)] - \(function)
+ | TIME : [\(dateString)]
+ > NOTE : \(object)
+  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
+ """
+ )
+#else
+
+#endif
+}
+
+public func getDeviceWidth() -> CGFloat { UIScreen.main.bounds.size.width }
+public func getDeviceHeight() -> CGFloat { UIScreen.main.bounds.size.height }
+
+
+/// 탈옥 여부 파악 함수
+public func isIllegalDevice() -> Bool {
+ func canOpen(path: String) -> Bool {
+ let file = fopen(path, "r")
+ guard file != nil else { return false }
+ fclose(file)
+ return true
+ }
+
+ guard let cydiaUrlScheme = NSURL(string: "cydia://package/com.example.package") else { return false }
+ if UIApplication.shared.canOpenURL(cydiaUrlScheme as URL) {
+ return true
+ }
+
+#if arch(i386) || arch(x86_64)
+ return false
+#endif
+
+ let fileManager = FileManager.default
+ if fileManager.fileExists(atPath: "/Applications/Cydia.app") ||
+ fileManager.fileExists(atPath: "/Library/MobileSubstrate/MobileSubstrate.dylib") ||
+ fileManager.fileExists(atPath: "/bin/bash") ||
+ fileManager.fileExists(atPath: "/usr/sbin/sshd") ||
+ fileManager.fileExists(atPath: "/etc/apt") ||
+ fileManager.fileExists(atPath: "/usr/bin/ssh") ||
+ fileManager.fileExists(atPath: "/private/var/lib/apt") {
+ return true
+ }
+ if canOpen(path: "/Applications/Cydia.app") ||
+ canOpen(path: "/Library/MobileSubstrate/MobileSubstrate.dylib") ||
+ canOpen(path: "/bin/bash") ||
+ canOpen(path: "/usr/sbin/sshd") ||
+ canOpen(path: "/etc/apt") ||
+ canOpen(path: "/usr/bin/ssh") {
+ return true
+ }
+ let path = "/private/" + NSUUID().uuidString
+ do {
+ try "anyString".write(toFile: path, atomically: true, encoding: String.Encoding.utf8)
+ try fileManager.removeItem(atPath: path)
+ return true
+ } catch let error { // 이 부분
+ printLog("Jail ERROR: \(error))")
+ return false
+ }
+}
+
+public func fontNameCheck() {
+ for family: String in UIFont.familyNames {
+ print(family)
+ for names : String in UIFont.fontNames(forFamilyName: family){
+ printLog("\(names)")
+ }
+ }
+}
+
+/// a 가 b 보다 클 경우 true 반환 ( 그외 전부 false)
+public func isBigger (_ a: Int, _ b: Int) -> Bool {
+ if a > b { return true } else { return false }
+}
+
+/// JSON 형태의 String 을 받아서 Dictionary 의 형태로 내보냄
+public func jsonToDict(_ input: String) -> [String: Any] {
+ if let jsonData = input.data(using: .utf8){
+ do {
+ if let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
+ return jsonObject
+ }
+ } catch let error { // 이 부분
+ printLog("JSON ERROR: \(error))")
+ }
+ }
+ return [:]
+}
+
+func versionChange(ver: String) -> [Int] {
+ return ver.components(separatedBy: ["."]).map {Int($0) ?? 0}
+}
+
+/// a 가 b 보다 OOO 하다.
+func compareVersion(_ a: String, _ b: String) -> Compare {
+ let aList = versionChange(ver: a)
+ let bList = versionChange(ver: b)
+ if aList.count != bList.count { return .error }
+ else {
+ for i in 0 ..< aList.count {
+ if aList[i] > bList[i] { return .bigger }
+ else if aList[i] < bList[i] { return .smaller }
+ }
+ return .equal
+ }
+}
+
+func copyToClipboard(_ text: String){
+ UIPasteboard.general.string = text
+}
+
+
+
+// MARK: - CUSTOM COMPONENTS
+
+
+// MARK: - EXTENSION
+extension String {
+ /// 마지막 경로 구성 요소
+ var lastPathComponent: String {
+ get {
+ return (self as NSString).lastPathComponent
+ }
+ }
+
+ /// 원하는 길이 만큼 절단
+ func cut(start: Int, end: Int) -> String {
+ let startIndex = self.index(self.startIndex,offsetBy: start >= 0 ? start : 0)
+ let endIndex = self.index(self.startIndex,offsetBy: end >= 0 ? end : 0)
+ let result: String = "\(self[startIndex ..< endIndex])"
+ return result
+ }
+
+ /// 글자 하나 단위로 구분
+ func letter() -> [String] {
+ return self.map { String($0) }
+ }
+
+ /// 단어 하나 단위로 구문 (띄어쓰기)
+ func word() -> [String] {
+ return self.components(separatedBy: " ")
+ }
+
+ /// Date() 로 변환 -> (Bool, Date) 출력
+ func convertDate(_ dateFormat: String = "yyyyMMdd") -> (Bool, Date) {
+ let dateFormatter = Date().setDateFormatter(dateFormat)
+ if let convert = dateFormatter.date(from: self) {
+ return (true, convert)
+ } else {
+ return (false, Date())
+ }
+ }
+
+ /// 정규식 체크
+ ///
+ /// 이메일 정규식 예시: "[A-Z0-9a-z._%+-]+@[A-Z0-9a-z._%+-]+\\.[A-Za-z]{2,64}"
+ /// 비밀번호 정규식 에시: "[A-Z0-9a-z._%+-]{6,12}"
+ func checkFilter(_ filter: String) -> Bool {
+ if self == "" { return false }
+ return self.range(of: filter, options: .regularExpression) != nil
+
+ }
+
+ /// Bool 값에 맞게 DateFormat을 반환
+ static func makeDateFormat(year: Bool, month: Bool, day: Bool, dayOfWeek: Bool = false, am_pm: Bool = false, hour: Bool = false,_ fullTime: Bool = true, minute: Bool = false, second: Bool = false, mSecond: Bool = false, mSDigit: Int = 1) -> String {
+
+ var dateFormat = ""
+
+ if year {
+ dateFormat = dateFormat + "yyyy"
+ }
+ if month {
+ dateFormat = dateFormat + "MM"
+ }
+ if day {
+ dateFormat = dateFormat + "dd"
+ }
+ if dayOfWeek {
+ dateFormat = dateFormat + "EEEEEE"
+ }
+
+ if am_pm {
+ dateFormat = dateFormat + "a"
+ }
+
+ if fullTime { // 24시간
+ if hour {
+ dateFormat = dateFormat + "HH"
+ }
+ } else { // 12시간
+ if hour {
+ dateFormat = dateFormat + "hh"
+ }
+ }
+
+ if minute {
+ dateFormat = dateFormat + "mm"
+ }
+
+ if second {
+ dateFormat = dateFormat + "ss"
+ }
+
+ if mSecond {
+ for _ in 0 ..< mSDigit {
+ dateFormat = dateFormat + "S"
+ }
+ }
+
+ return dateFormat
+ }
+
+ /// 날짜를 합쳐서 하나의 String으로 반환
+ static func combineDate(year: Int, month: Int, day: Int) -> String {
+ return "\(year * 10000 + month * 100 + day)"
+ }
+
+ func stringToInt() -> Int {
+ if let intValue = Int(self) {
+ return intValue
+ } else {
+ return 0
+ }
+ }
+}
+
+extension Date {
+ /// 연도 표시
+ ///
+ /// 변환에 실패시 현재 날짜의 년 표시
+ var year: Int {
+ let dateFormatter = self.setDateFormatter("yyyy")
+ if let year = Int(dateFormatter.string(from: self)){
+ return year
+ } else {
+ return Calendar.current.component(.year, from: self)
+ }
+ }
+
+ /// 월 표시
+ ///
+ /// 변환 실패시 현재 날짜의 월 표시
+ var month: Int {
+ let dateFormatter = self.setDateFormatter("MM")
+ if let month = Int(dateFormatter.string(from: self)) {
+ return month
+ } else {
+ return Calendar.current.component(.month, from: self)
+ }
+ }
+
+ /// 일 표시
+ ///
+ /// 변환 실패시 현재 날짜의 월 표시
+ var day: Int {
+ let dateFormatter = self.setDateFormatter("dd")
+ if let day = Int(dateFormatter.string(from: self)) {
+ return day
+ } else {
+ return Calendar.current.component(.day, from: self)
+ }
+ }
+
+ /// 요일 표시
+ ///
+ /// 일요일 부터 시작해 0~6까지 반환
+ ///
+ /// -1 반환시 오류 발생
+ var dayOfWeek: Int {
+ let dateFormatter = self.setDateFormatter("EEEEEE")
+ let convert = dateFormatter.string(from: self)
+ switch convert {
+ case "일":
+ return 0
+ case "월":
+ return 1
+ case "화":
+ return 2
+ case "수":
+ return 3
+ case "목":
+ return 4
+ case "금":
+ return 5
+ case "토":
+ return 6
+ default:
+ return -1
+ }
+ }
+
+ func setDateFormatter(_ dateFormat: String) -> DateFormatter {
+ let dateFormatter = DateFormatter()
+ dateFormatter.dateFormat = dateFormat
+ dateFormatter.timeZone = TimeZone(abbreviation: "KST")
+ dateFormatter.locale = Locale(identifier: "ko_kr")
+ return dateFormatter
+ }
+
+ /// String 값으로 변환
+ func convertString(_ dateFormat: String = "yyyyMMdd") -> String {
+ let dateFormatter = self.setDateFormatter(dateFormat)
+ return dateFormatter.string(from: self)
+ }
+
+
+ /// 해당 년도가 윤년인지 확인
+ ///
+ /// 값이 정확하지 않으면 현재 날짜로 파악
+ func checkLeapMonth() -> Bool {
+ if self.year % 4 == 0 {
+ if self.year % 100 == 0 {
+ if self.year % 400 == 0 {
+ return true
+ }
+ } else {
+ return true
+ }
+ }
+ return false
+ }
+
+ /// 해당 월의 날짜 수 확인
+ ///
+ /// 값이 정확하지 않으면 현재 날짜로 파악
+ func getLastDayOfMonth() -> Int {
+ switch self.month {
+ case 1,3,5,7,8,10,12 :
+ return 31
+ case 2:
+ if self.checkLeapMonth() {
+ return 29
+ } else {
+ return 28
+ }
+ case 4,6,9,11:
+ return 30
+ default:
+ return -1
+ }
+ }
+}
+
+
+extension Font {
+ enum NPS_Font : String {
+ case regular
+ case bold
+
+ var value: String {
+ switch self {
+ case .regular:
+ return "NPS-font-Regular"
+ case .bold:
+ return "NPS-font-Bold"
+ }
+ }
+ }
+
+ static func nps(font: NPS_Font = .regular, size: CGFloat = 12) -> Font {
+ return .custom(font.value, size: size)
+ }
+
+
+}
+
+extension View {
+ func endTextEditing() {
+ UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
+ }
+}
+
+// MARK: - ANNOTATION
+
+/// 사용방법
+/// @UserDefault (key: "keyName", defaultValue: "default") var 변수
+/// print(변수)
+/// - 위에처럼 하게 되면 UserDefaults에 저장된 key 값을 갖고있는걸 보여주든가 기본 값 보여줌
+/// 변수 = 변경값
+/// - 위에처럼 하게되면 UserDefaults에 해당 key 값에 변경값을 저장하고 들고 있음
+@propertyWrapper
+struct UserDefault {
+ private let ud: UserDefaults = .standard
+ private let key: String
+ private var defaultValue: T
+
+ var wrappedValue: T {
+ set { ud.set(newValue, forKey: key) }
+ get { ud.object(forKey: key) as? T ?? defaultValue }
+ }
+
+ init(key: String, defaultValue: T) {
+ self.key = key
+ self.defaultValue = defaultValue
+ }
+
+ ///사용법: _변수.removeData()
+ /// - 중요사항 변수 앞에 _ 무조건 붙여야 함
+ func removeData() {
+ ud.removeObject(forKey: key)
+ }
+}
diff --git a/WebAppUIKitBase/Common/Protocol/LoactionProtocol.swift b/WebAppUIKitBase/Common/Protocol/LoactionProtocol.swift
new file mode 100644
index 0000000..a351262
--- /dev/null
+++ b/WebAppUIKitBase/Common/Protocol/LoactionProtocol.swift
@@ -0,0 +1,8 @@
+//
+// LoactionProtocol.swift
+// WebAppUIKitBase
+//
+// Created by Sean Kim on 10/21/24.
+//
+
+import Foundation
diff --git a/WebAppUIKitBase/SceneDelegate.swift b/WebAppUIKitBase/Common/SceneDelegate.swift
similarity index 80%
rename from WebAppUIKitBase/SceneDelegate.swift
rename to WebAppUIKitBase/Common/SceneDelegate.swift
index 097a40a..8838e81 100644
--- a/WebAppUIKitBase/SceneDelegate.swift
+++ b/WebAppUIKitBase/Common/SceneDelegate.swift
@@ -13,10 +13,13 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
- // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
- // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
- // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
- guard let _ = (scene as? UIWindowScene) else { return }
+ guard let windowScene = (scene as? UIWindowScene) else { return }
+ window = UIWindow(frame: UIScreen.main.bounds)
+ window?.windowScene = windowScene
+ // 여기서 메인 화면 띄우는 걸 함
+ window?.rootViewController = IntroVC()
+
+ window?.makeKeyAndVisible()
}
func sceneDidDisconnect(_ scene: UIScene) {
diff --git a/WebAppUIKitBase/IntroVC.swift b/WebAppUIKitBase/IntroVC.swift
new file mode 100644
index 0000000..c03da97
--- /dev/null
+++ b/WebAppUIKitBase/IntroVC.swift
@@ -0,0 +1,8 @@
+//
+// IntroVC.swift
+// WebAppUIKitBase
+//
+// Created by Sean Kim on 10/21/24.
+//
+
+import Foundation
diff --git a/WebAppUIKitBase/Scene/AppDelegate.swift b/WebAppUIKitBase/Scene/AppDelegate.swift
new file mode 100644
index 0000000..4dd12c0
--- /dev/null
+++ b/WebAppUIKitBase/Scene/AppDelegate.swift
@@ -0,0 +1,33 @@
+//
+// AppDelegate.swift
+// WebAppUIKitBase
+//
+// Created by Sean Kim on 10/21/24.
+//
+
+import UIKit
+
+@main
+class AppDelegate: UIResponder, UIApplicationDelegate {
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+ // Override point for customization after application launch.
+ return true
+ }
+
+ // MARK: UISceneSession Lifecycle
+
+ func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
+ // Called when a new scene session is being created.
+ // Use this method to select a configuration to create the new scene with.
+ return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
+ }
+
+ func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
+ // Called when the user discards a scene session.
+ // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
+ // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
+ }
+
+
+}
+
diff --git a/WebAppUIKitBase/ViewController.swift b/WebAppUIKitBase/Scene/IntroVC.swift
similarity index 53%
rename from WebAppUIKitBase/ViewController.swift
rename to WebAppUIKitBase/Scene/IntroVC.swift
index ede38f7..1e67d9e 100644
--- a/WebAppUIKitBase/ViewController.swift
+++ b/WebAppUIKitBase/Scene/IntroVC.swift
@@ -1,5 +1,5 @@
//
-// ViewController.swift
+// IntroVC.swift
// WebAppUIKitBase
//
// Created by Sean Kim on 10/21/24.
@@ -7,13 +7,11 @@
import UIKit
-class ViewController: UIViewController {
-
+class IntroVC: UIViewController {
+
override func viewDidLoad() {
super.viewDidLoad()
- // Do any additional setup after loading the view.
+
+
}
-
-
}
-
diff --git a/WebAppUIKitBase/Scene/MainWebVC.swift b/WebAppUIKitBase/Scene/MainWebVC.swift
new file mode 100644
index 0000000..e9b227b
--- /dev/null
+++ b/WebAppUIKitBase/Scene/MainWebVC.swift
@@ -0,0 +1,8 @@
+//
+// MainWebVC.swift
+// WebAppUIKitBase
+//
+// Created by Sean Kim on 10/21/24.
+//
+
+import Foundation
diff --git a/WebAppUIKitBase/Scene/SceneDelegate.swift b/WebAppUIKitBase/Scene/SceneDelegate.swift
new file mode 100644
index 0000000..8838e81
--- /dev/null
+++ b/WebAppUIKitBase/Scene/SceneDelegate.swift
@@ -0,0 +1,55 @@
+//
+// SceneDelegate.swift
+// WebAppUIKitBase
+//
+// Created by Sean Kim on 10/21/24.
+//
+
+import UIKit
+
+class SceneDelegate: UIResponder, UIWindowSceneDelegate {
+
+ var window: UIWindow?
+
+
+ func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
+ guard let windowScene = (scene as? UIWindowScene) else { return }
+ window = UIWindow(frame: UIScreen.main.bounds)
+ window?.windowScene = windowScene
+ // 여기서 메인 화면 띄우는 걸 함
+ window?.rootViewController = IntroVC()
+
+ window?.makeKeyAndVisible()
+ }
+
+ func sceneDidDisconnect(_ scene: UIScene) {
+ // Called as the scene is being released by the system.
+ // This occurs shortly after the scene enters the background, or when its session is discarded.
+ // Release any resources associated with this scene that can be re-created the next time the scene connects.
+ // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
+ }
+
+ func sceneDidBecomeActive(_ scene: UIScene) {
+ // Called when the scene has moved from an inactive state to an active state.
+ // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
+ }
+
+ func sceneWillResignActive(_ scene: UIScene) {
+ // Called when the scene will move from an active state to an inactive state.
+ // This may occur due to temporary interruptions (ex. an incoming phone call).
+ }
+
+ func sceneWillEnterForeground(_ scene: UIScene) {
+ // Called as the scene transitions from the background to the foreground.
+ // Use this method to undo the changes made on entering the background.
+ }
+
+ func sceneDidEnterBackground(_ scene: UIScene) {
+ // Called as the scene transitions from the foreground to the background.
+ // Use this method to save data, release shared resources, and store enough scene-specific state information
+ // to restore the scene back to its current state.
+ }
+
+
+}
+
diff --git a/WebAppUIKitBase/SecretCode.swift b/WebAppUIKitBase/SecretCode.swift
new file mode 100644
index 0000000..612a4ad
--- /dev/null
+++ b/WebAppUIKitBase/SecretCode.swift
@@ -0,0 +1,8 @@
+//
+// SecretCode.swift
+// WebAppUIKitBase
+//
+// Created by Sean Kim on 10/21/24.
+//
+
+import Foundation