[✨] IntroVC 완성, 버전 체크, 위치정보 수신 등 기초적인 기능들 추가
This commit is contained in:
parent
a7d36694bb
commit
d9911cc30b
|
@ -6,6 +6,11 @@
|
|||
objectVersion = 77;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
A7D80D4D2CC5DFFF00E93F4D /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = A7D80D4C2CC5DFFF00E93F4D /* SnapKit */; };
|
||||
A7D80D502CC5E01D00E93F4D /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = A7D80D4F2CC5E01D00E93F4D /* Alamofire */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
A749CDFD2CC5D8CD0038D13D /* WebAppUIKitBase.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WebAppUIKitBase.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
@ -36,6 +41,8 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A7D80D4D2CC5DFFF00E93F4D /* SnapKit in Frameworks */,
|
||||
A7D80D502CC5E01D00E93F4D /* Alamofire in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -78,6 +85,8 @@
|
|||
);
|
||||
name = WebAppUIKitBase;
|
||||
packageProductDependencies = (
|
||||
A7D80D4C2CC5DFFF00E93F4D /* SnapKit */,
|
||||
A7D80D4F2CC5E01D00E93F4D /* Alamofire */,
|
||||
);
|
||||
productName = WebAppUIKitBase;
|
||||
productReference = A749CDFD2CC5D8CD0038D13D /* WebAppUIKitBase.app */;
|
||||
|
@ -107,6 +116,10 @@
|
|||
);
|
||||
mainGroup = A749CDF42CC5D8CD0038D13D;
|
||||
minimizedProjectReferenceProxies = 1;
|
||||
packageReferences = (
|
||||
A7D80D4B2CC5DFFF00E93F4D /* XCRemoteSwiftPackageReference "SnapKit" */,
|
||||
A7D80D4E2CC5E01D00E93F4D /* XCRemoteSwiftPackageReference "Alamofire" */,
|
||||
);
|
||||
preferredProjectObjectVersion = 77;
|
||||
productRefGroup = A749CDFE2CC5D8CD0038D13D /* Products */;
|
||||
projectDirPath = "";
|
||||
|
@ -144,20 +157,20 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 2.0.8.1;
|
||||
DEVELOPMENT_TEAM = 45MYH7ZHUQ;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = WebAppUIKitBase/Info.plist;
|
||||
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "검색과 길안내를 위해 사용합니다.";
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
|
||||
INFOPLIST_KEY_UIMainStoryboardFile = Main;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
MARKETING_VERSION = 2.0.8;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "kr.kro.sean-k.WebAppUIKitBase";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
|
@ -176,20 +189,20 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 2.0.8.1;
|
||||
DEVELOPMENT_TEAM = 45MYH7ZHUQ;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = WebAppUIKitBase/Info.plist;
|
||||
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "검색과 길안내를 위해 사용합니다.";
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
|
||||
INFOPLIST_KEY_UIMainStoryboardFile = Main;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
MARKETING_VERSION = 2.0.8;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "kr.kro.sean-k.WebAppUIKitBase";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
|
@ -343,6 +356,38 @@
|
|||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
A7D80D4B2CC5DFFF00E93F4D /* XCRemoteSwiftPackageReference "SnapKit" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/SnapKit/SnapKit.git";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 5.7.1;
|
||||
};
|
||||
};
|
||||
A7D80D4E2CC5E01D00E93F4D /* XCRemoteSwiftPackageReference "Alamofire" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/Alamofire/Alamofire.git";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 5.10.1;
|
||||
};
|
||||
};
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
A7D80D4C2CC5DFFF00E93F4D /* SnapKit */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = A7D80D4B2CC5DFFF00E93F4D /* XCRemoteSwiftPackageReference "SnapKit" */;
|
||||
productName = SnapKit;
|
||||
};
|
||||
A7D80D4F2CC5E01D00E93F4D /* Alamofire */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = A7D80D4E2CC5E01D00E93F4D /* XCRemoteSwiftPackageReference "Alamofire" */;
|
||||
productName = Alamofire;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
rootObject = A749CDF52CC5D8CD0038D13D /* Project object */;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"originHash" : "4d1117f641c000c6545947e4d48e126cc17473ec53f643df82900a33ad4936b2",
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "alamofire",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/Alamofire/Alamofire.git",
|
||||
"state" : {
|
||||
"revision" : "e16d3481f5ed35f0472cb93350085853d754913f",
|
||||
"version" : "5.10.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "snapkit",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/SnapKit/SnapKit.git",
|
||||
"state" : {
|
||||
"revision" : "2842e6e84e82eb9a8dac0100ca90d9444b0307f4",
|
||||
"version" : "5.7.1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"version" : 3
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Bucket
|
||||
uuid = "B820CAC2-8B2D-4CF9-9D9F-B449DF8BFD0D"
|
||||
type = "1"
|
||||
version = "2.0">
|
||||
</Bucket>
|
|
@ -1,36 +0,0 @@
|
|||
//
|
||||
// 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<UISceneSession>) {
|
||||
// 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.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -7,25 +7,43 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
import AdSupport
|
||||
import AppTrackingTransparency
|
||||
|
||||
@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
|
||||
/// 앱이 Active 로 전환될때 호출 : back -> fore 시 호출
|
||||
func applicationDidBecomeActive(_ application: UIApplication) {
|
||||
|
||||
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)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||
ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in
|
||||
switch status {
|
||||
case .notDetermined:
|
||||
printLog(status)
|
||||
case .restricted:
|
||||
printLog(status)
|
||||
case .denied:
|
||||
printLog(status)
|
||||
case .authorized:
|
||||
printLog(status)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
|
||||
// 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.
|
||||
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
|
||||
let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
|
||||
let token = tokenParts.joined()
|
||||
printLog("Device Tokens: \(token)")
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5,4 +5,128 @@
|
|||
// Created by Sean Kim on 10/21/24.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import CoreLocation
|
||||
|
||||
import Alamofire
|
||||
|
||||
class CommonUtils: NSObject, CLLocationManagerDelegate {
|
||||
static let shared: CommonUtils = CommonUtils()
|
||||
|
||||
private override init() {}
|
||||
|
||||
//MARK: - Location
|
||||
weak var locationDelegate: LocationDelegate?
|
||||
|
||||
let locationManager: CLLocationManager = {
|
||||
let manager = CLLocationManager()
|
||||
manager.desiredAccuracy = kCLLocationAccuracyBest
|
||||
manager.distanceFilter = kCLDistanceFilterNone
|
||||
return manager
|
||||
}()
|
||||
var lastLocation: CLLocation?
|
||||
|
||||
|
||||
public func checkLocationPermission() {
|
||||
printLog("[위치] Check Loc Permission")
|
||||
locationManager.delegate = self
|
||||
locationManager.requestWhenInUseAuthorization()
|
||||
self.toggleUpdatingLocation(true)
|
||||
}
|
||||
|
||||
public func toggleUpdatingLocation(_ toggle: Bool) {
|
||||
if toggle {
|
||||
locationManager.startUpdatingLocation()
|
||||
} else {
|
||||
locationManager.stopUpdatingLocation()
|
||||
}
|
||||
}
|
||||
|
||||
// 14이상인 경우만 산정해서 한거라서 14.0 미만을 원하면 다른 메서드를 만들어야 함
|
||||
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
|
||||
printLog("[위치] locationManagerDidChangeAuthorization") // 처음 불러 올 떄 요거 불려짐
|
||||
switch manager.authorizationStatus {
|
||||
case .authorizedAlways, .authorizedWhenInUse, .authorized:
|
||||
printLog("[위치] 권한 허용")
|
||||
self.locationDelegate?.checkPermission(true)
|
||||
self.toggleUpdatingLocation(true)
|
||||
default:
|
||||
printLog("[위치] 권한 미허용 & 기타 오류")
|
||||
self.locationDelegate?.checkPermission(false)
|
||||
self.toggleUpdatingLocation(false)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 14이상인 경우만 산정해서 한거라서 14.0 미만을 원하면 다른 메서드를 만들어야 함
|
||||
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
|
||||
printLog("[위치] didUpdateLocations") // 요건 값을 가져올 때 불려짐
|
||||
switch manager.authorizationStatus {
|
||||
case .authorizedAlways, .authorizedWhenInUse:
|
||||
printLog("[위치] 권한 허용")
|
||||
self.locationDelegate?.checkPermission(true)
|
||||
if let location = locations.first{
|
||||
printLog("[위치] 정보 수신 성공")
|
||||
self.locationDelegate?.getLocation(location)
|
||||
}
|
||||
default:
|
||||
printLog("[위치] 권한 미허용 & 기타 오류")
|
||||
self.locationDelegate?.checkPermission(false)
|
||||
}
|
||||
}
|
||||
|
||||
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
|
||||
printLog("[위치] didFailWithError")
|
||||
self.locationDelegate?.checkPermission(false)
|
||||
}
|
||||
|
||||
|
||||
// MARK: - URL
|
||||
func afGET(url: String, param: [String:String], headers: HTTPHeaders?) async throws -> Any {
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
AF.request(url,
|
||||
method: .get,
|
||||
parameters: param,
|
||||
headers: headers)
|
||||
.validate(statusCode: 200 ..< 300)
|
||||
.responseString { response in
|
||||
printLog("[LOG] response: \(response)")
|
||||
switch response.result {
|
||||
case .success(let value):
|
||||
printLog("[LOG]")
|
||||
continuation.resume(returning: value)
|
||||
case .failure(let error):
|
||||
printLog("[LOG]")
|
||||
continuation.resume(throwing: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 [:]
|
||||
}
|
||||
|
||||
public func jsonToType<T: Decodable>(_ input: String, as type: T.Type) -> T? {
|
||||
if let jsonData = input.data(using: .utf8) {
|
||||
do {
|
||||
let decodedObject = try JSONDecoder().decode(T.self, from: jsonData)
|
||||
return decodedObject
|
||||
} catch let error {
|
||||
printLog("JSON 디코딩 오류: \(error)")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
//
|
||||
// Created by Sean Kim on 2/20/24.
|
||||
//
|
||||
import SwiftUI
|
||||
import UIKit
|
||||
|
||||
// MARK: - TYPEALIAS
|
||||
typealias VOID_TO_VOID = () -> ()
|
||||
|
@ -26,13 +26,6 @@ public func printLog<T>(_ object: T, _ file: String = #file, _ function: String
|
|||
#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)
|
||||
|
@ -149,9 +142,6 @@ func copyToClipboard(_ text: String){
|
|||
|
||||
|
||||
|
||||
// MARK: - CUSTOM COMPONENTS
|
||||
|
||||
|
||||
// MARK: - EXTENSION
|
||||
extension String {
|
||||
/// 마지막 경로 구성 요소
|
||||
|
@ -379,35 +369,28 @@ extension Date {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
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"
|
||||
extension UIViewController {
|
||||
public func makeUIAlert(title: String, message: String, okTitle: String, okAction:((UIAlertAction) -> Void)? = nil, completion: (() -> ())? = nil) {
|
||||
let alertController = UIAlertController(title: "\(title)", message: "\(message)", preferredStyle: .alert)
|
||||
let okAction = UIAlertAction(title: "\(okTitle)", style: .default, handler: okAction)
|
||||
alertController.addAction(okAction)
|
||||
self.present(alertController, animated: true, completion: completion)
|
||||
}
|
||||
|
||||
public func makeUITwoAlert(title: String, message: String, okTitle: String, okAction:((UIAlertAction) -> Void)? = nil, cancelTitle: String, cancelAction:((UIAlertAction) -> Void)? = nil, completion: (() -> ())? = nil) {
|
||||
let alertController = UIAlertController(title: "\(title)", message: "\(message)", preferredStyle: .alert)
|
||||
let okAction = UIAlertAction(title: "\(okTitle)", style: .default, handler: okAction)
|
||||
alertController.addAction(okAction)
|
||||
|
||||
let cancelAction = UIAlertAction(title: "\(cancelTitle)", style: .cancel, handler: cancelAction)
|
||||
alertController.addAction(cancelAction)
|
||||
|
||||
self.present(alertController, animated: true, completion: completion)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
/// 사용방법
|
||||
|
|
|
@ -5,4 +5,15 @@
|
|||
// Created by Sean Kim on 10/21/24.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
//import Foundation
|
||||
import CoreLocation
|
||||
|
||||
protocol LocationDelegate: NSObject {
|
||||
func checkPermission(_ type: Bool)
|
||||
func getLocation(_ location: CLLocation)
|
||||
}
|
||||
|
||||
extension LocationDelegate {
|
||||
func checkPermission(_ type: Bool) {}
|
||||
func getLocation(_ location: CLLocation) {}
|
||||
}
|
||||
|
|
|
@ -22,33 +22,14 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|||
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 scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
|
||||
guard let url = URLContexts.first?.url else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
<string>Default Configuration</string>
|
||||
<key>UISceneDelegateClassName</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
|
||||
<key>UISceneStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
//
|
||||
// IntroVC.swift
|
||||
// WebAppUIKitBase
|
||||
//
|
||||
// Created by Sean Kim on 10/21/24.
|
||||
//
|
||||
|
||||
import Foundation
|
|
@ -1,33 +0,0 @@
|
|||
//
|
||||
// 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<UISceneSession>) {
|
||||
// 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.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -6,12 +6,205 @@
|
|||
//
|
||||
|
||||
import UIKit
|
||||
import Alamofire
|
||||
|
||||
import SnapKit
|
||||
import CoreLocation
|
||||
|
||||
class IntroVC: UIViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
|
||||
CommonUtils.shared.locationDelegate = self
|
||||
}
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
if isIllegalDevice() {
|
||||
self.makeUIAlert(title: "안내",
|
||||
message: "변경된 OS를 사용하는 기기는 서비스를 이용할 수 없습니다.",
|
||||
okTitle: "확인") { _ in
|
||||
exit(1)
|
||||
}
|
||||
} else {
|
||||
if NetworkReachabilityManager.default?.isReachable == false {
|
||||
self.makeUIAlert(title: "서비스 연결 문제 발생",
|
||||
message: """
|
||||
네트워크 문제로 서비스에 연결하지 못하였습니다.
|
||||
네트워크 상태를 확인후 다시 실행해주세요.
|
||||
""",
|
||||
okTitle: "확인") { _ in
|
||||
exit(1)
|
||||
}
|
||||
} else {
|
||||
self.checkAppVersion()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func checkAppVersion() {
|
||||
Task {
|
||||
do {
|
||||
let result = try await CommonUtils.shared.afGET(url:VER_URL,
|
||||
param: VER_PARAM,
|
||||
headers: VER_HEADERS)
|
||||
// let result = """
|
||||
// {"status":{"code":"000","message":"성공"},"data":{"finalVer":"2.0.8","forceVer":"2.0.6","forceUpdtYn":"P","remark":"기능추가","checkVer":"9.9.9"}}
|
||||
// """
|
||||
printLog("Success : \(result)")
|
||||
let response = CommonUtils.shared.jsonToType("\(result)", as: VersionResponse.self)
|
||||
|
||||
if let code = response?.status.code, code == "000" {
|
||||
if let currentVer = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String,
|
||||
let finalVer = response?.data.finalVer, let forceVer = response?.data.forceVer,
|
||||
let checkVer = response?.data.checkVer, let forceUpdtYn = response?.data.forceUpdtYn
|
||||
{
|
||||
switch self.versionCompare(currentVer, finalVer) {
|
||||
case .equal, .bigger: // 업데이트 처리 필요 없음
|
||||
CommonUtils.shared.checkLocationPermission()
|
||||
case .smaller:
|
||||
switch self.versionCompare(currentVer, forceVer) {
|
||||
case .equal, .bigger:
|
||||
if forceUpdtYn == "P" {// PASS라서 P 한건데 Y 해도 된다.
|
||||
self.makeUITwoAlert(title: "업데이트 안내",
|
||||
message: "최신 버전이 새로 나왔어요\n지금 업데이트하시겠어요?",
|
||||
okTitle: "지금 업데이트",
|
||||
okAction: { _ in
|
||||
let appStoreURL = URL(string: "http://www.naver.com")!
|
||||
UIApplication.shared.open(appStoreURL, options: [:], completionHandler: nil)
|
||||
exit(1)
|
||||
}, cancelTitle: "나중에") { _ in
|
||||
CommonUtils.shared.checkLocationPermission()
|
||||
}
|
||||
} else {
|
||||
CommonUtils.shared.checkLocationPermission()
|
||||
}
|
||||
case .smaller:
|
||||
self.makeUIAlert(title: "업데이트 안내",
|
||||
message: "앱을 사용하시려면\n최신버전으로 업데이트 해주세요",
|
||||
okTitle: "지금 업데이트") { _ in
|
||||
let appStoreURL = URL(string: "http://www.naver.com")!
|
||||
UIApplication.shared.open(appStoreURL, options: [:], completionHandler: nil)
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw NSError(domain: "com.version.API",
|
||||
code: Int(response?.status.code ?? "") ?? -1,
|
||||
userInfo: [NSLocalizedDescriptionKey: "Version is Wrong"])
|
||||
}
|
||||
} else {
|
||||
throw NSError(domain: "com.version.API",
|
||||
code: Int(response?.status.code ?? "") ?? -1,
|
||||
userInfo: [NSLocalizedDescriptionKey: "Version is Wrong"])
|
||||
}
|
||||
} catch {
|
||||
printLog("App Check ERROR: \(error)")
|
||||
self.makeUIAlert(title: "서비스 연결 문제 발생",
|
||||
message: """
|
||||
일시적인 장애 또는 네트워크 문제로
|
||||
서비스에 연결하지 못하였습니다.
|
||||
문제가 계속될 경우 고객센터로 문의해 주세요
|
||||
""",
|
||||
okTitle: "확인") { _ in
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// compareVer에 비교를 할 문자열을 넣어주면 된다.
|
||||
///
|
||||
/// [결과 해석: 현재 버전이 비교 버전보다 (RESULT) 하다.]
|
||||
private func versionCompare(_ currentVer: String, _ compareVer: String) -> CompareVersion {
|
||||
let currentArray = currentVer.components(separatedBy: ["."]).map {Int($0) ?? 0}
|
||||
let compareArray = compareVer.components(separatedBy: ["."]).map {Int($0) ?? 0}
|
||||
|
||||
printLog("Ver current: \(currentArray)")
|
||||
printLog("Ver force: \(compareArray)")
|
||||
|
||||
for i in 0 ..< currentArray.count {
|
||||
if currentArray[i] > compareArray[i] {
|
||||
// 현재 버전이 비교하려는 버전보다 큰 경우 == 그냥 일반 동작을 시키면 된다.
|
||||
return .bigger
|
||||
} else if currentArray[i] < compareArray[i] {
|
||||
// 현재 버전이 비교하려는 버전보다 작은 경우 == 업데이트 조건 처리
|
||||
return .smaller
|
||||
}
|
||||
}
|
||||
|
||||
// 현재 버전이 비교 버전과 동일
|
||||
return .equal
|
||||
}
|
||||
|
||||
private func moveToWeb() {
|
||||
let VC = MainWebVC()
|
||||
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
|
||||
let window = windowScene.windows.first {
|
||||
window.rootViewController = VC
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension IntroVC: LocationDelegate {
|
||||
|
||||
func checkPermission(_ type: Bool) {
|
||||
if type {
|
||||
// CommonUtils.CommonUtils.shared.saveUdData("Y", forKey: "locationYn")
|
||||
} else {
|
||||
// CommonUtils.CommonUtils.shared.saveUdData("N", forKey: "locationYn")
|
||||
self.moveToWeb()
|
||||
}
|
||||
}
|
||||
|
||||
func getLocation(_ location: CLLocation) {
|
||||
CommonUtils.shared.locationManager.stopUpdatingLocation()
|
||||
let lat = location.coordinate.latitude
|
||||
let lng = location.coordinate.longitude
|
||||
CommonUtils.shared.lastLocation = location
|
||||
printLog("Intro \(String(describing: CommonUtils.shared.lastLocation))")
|
||||
printLog("Intro Delegate = lattitude : \(lat) longitude : \(lng)")
|
||||
printLog("위치 권한 허용 > 웹뷰 start")
|
||||
self.moveToWeb()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
enum CompareVersion: Int {
|
||||
case equal = 0
|
||||
case bigger
|
||||
case smaller
|
||||
}
|
||||
|
||||
class VersionResponse: Codable {
|
||||
let status: Status
|
||||
let data: VersionData
|
||||
}
|
||||
/// API 확인 변수
|
||||
///
|
||||
/// code: API 정상 확인 코드 (e.g. 000: 정상)
|
||||
///
|
||||
/// message: 코드에 대한 설명
|
||||
class Status: Codable {
|
||||
let code, message: String
|
||||
|
||||
}
|
||||
|
||||
/// API 데이터 변수
|
||||
///
|
||||
/// finaclVer: 현재 가장 최신 버전
|
||||
///
|
||||
/// forceVer: 이 버전보다 미만의 버전은 강제 업데이트 시행
|
||||
///
|
||||
/// checkVer: 개발용 및 업데이트 관련 버전
|
||||
///
|
||||
/// forceUpdYn: P(Y) 등의 값일 시 finalVer보다 미만의 경우 선택 업데이트 동작 시행
|
||||
///
|
||||
/// remark: 현재 버전 관련한 설명
|
||||
class VersionData: Codable {
|
||||
let finalVer, forceVer, checkVer: String?
|
||||
let forceUpdtYn: String?
|
||||
let remark: String?
|
||||
}
|
||||
|
|
|
@ -5,4 +5,15 @@
|
|||
// Created by Sean Kim on 10/21/24.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import WebKit
|
||||
|
||||
import SnapKit
|
||||
|
||||
class MainWebVC: UIViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.view.backgroundColor = .white
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
//
|
||||
// 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.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
//
|
||||
// SecretCode.swift
|
||||
// WebAppUIKitBase
|
||||
//
|
||||
// Created by Sean Kim on 10/21/24.
|
||||
//
|
||||
|
||||
import Foundation
|
Loading…
Reference in New Issue
Block a user