Notice
Recent Posts
Recent Comments
Link
투케이2K
42. (TWOK/UTIL) [Ios/Swift] A_CookieWebview - 쿠키 설정 및 웹뷰 로드 수행 실시 클래스 본문
투케이2K 유틸파일
42. (TWOK/UTIL) [Ios/Swift] A_CookieWebview - 쿠키 설정 및 웹뷰 로드 수행 실시 클래스
투케이2K 2022. 5. 9. 16:45[설 명]
프로그램 : Ios / Swift
설 명 : 쿠키 설정 및 웹뷰 로드 수행 실시 클래스
[소스 코드]
import UIKit
import SafariServices
import WebKit
import AVFoundation
import Photos
class A_CookieWebview: UIViewController, WKNavigationDelegate, WKScriptMessageHandler, WKUIDelegate {
// MARK: - [클래스 설명]
/*
// -----------------------------------------
1. 사용하는 스토리보드 : Main
2. 쿠키 삽입 및 웹뷰 화면 호출 액티비티 화면
// -----------------------------------------
*/
// MARK: [쿠키 웹뷰 로직 설명 실시]
/*
* // -----------------------------------------
* 1. A_Main 클래스 에서 setCookieSettings 자바스크립트 브릿지 명령 받으면 쿠키 삽입 및 웹뷰 호출 수행 실시
* 2. 자바스크립트에서 내려받은 데이터에서 헤더 값이 있는 경우 헤더 값을 추가하는 로직 / 없으면 일반 웹뷰 호출 로직 수행
* 3. 쿠키 설정 로직 설정
* - [1]. 웹뷰 설정 및 최초 로드 (init_WebView) 시 헤더 쪽에 쿠키 추가 실시 [URLRequest.addValue("데이터", forHTTPHeaderField: "Cookie")]
* - [2]. addJavaScriptBridge() 자바스크립트 통신 브릿지 설정 부분 에서 WKUserScript / addUserScript 사용해 웹뷰 로드 될 때 [사전] 쿠키 값 설정
* - [3]. 실시간 주소 변경 부분 decidePolicyFor() 에서 decisionHandler(.allow) 브라우저 내 로직 허용 실시
* // -----------------------------------------
* */
// MARK: - [빠른 로직 찾기 : 주석 로직 찾기]
// -----------------------------------------
// [SEARCH FAST] : [웹뷰 설정]
// [SEARCH FAST] : [자바스크립트 통신]
// [SEARCH FAST] : [동적 헤더 추가 실시]
// [SEARCH FAST] : [쿠키 설정 실시]
// [SEARCH FAST] : [실시간 쿠키 값 확인 실시]
// -----------------------------------------
// MARK: - [자바스크립트에서 전달 받은 쿠키 설정 데이터 형식]
/*
// -----------------------------------------
[쿠키 설정 방식]
{
"header" : [
{"Cookie" : "JSESSIONID=61f0aa76ad66d12300000000; domain=m.test.ac.kr; path=/;"}, // [쿠키 스트링 값]
{"Autholization" : "1234"} // [헤더 권한 설정]
],
"url" : "https://m.test.ac.kr/v3/app", // [웹뷰 주소 로드 수행]
"domain" : "https://m.test.ac.kr" // [쿠키 설정 도메인]
}
// -----------------------------------------
[일반 주소 호출]
{
"url" : "https://www.naver.com"
}
// -----------------------------------------
*/
// MARK: - [웹뷰 전역 변수 선언 부분]
private var main_webview: WKWebView? = nil // [동적으로 웹뷰 생성]
// [뷰 컨트롤러 종료 시 호출되는 함수]
deinit {
// [WKWebView Progress 퍼센트 가져오기 이벤트 제거]
self.main_webview?.removeObserver(
self,
forKeyPath: #keyPath(WKWebView.estimatedProgress)
)
}
let javascriptController = WKUserContentController() // [자바스크립트 통신 사용]
let javascriptConfig = WKWebViewConfiguration() // [자바스크립트 통신 사용]
let kwebviewPreference = WKPreferences() // [자바스크립트 통신 사용]
// MARK: - [전역 변수 선언 실시]
let ACTIVITY_NAME = "A_CookieWebview" // [액티비티 명칭 지정]
var saveData = "" // [프리퍼런스에 저장된 데이터]
var loadUrl = "" // [웹뷰 로드 주소]
var cookieDomain = "" // [쿠키 설정 도메인 주소]
var cookieString = "" // [쿠키 스트링 문자열 저장 값]
var sharedCookies: Array<HTTPCookie> = [] // [쿠키 값 저장 배열]
var headerExist = false // [자바스크립트로 넘어온 헤더 데이터 있는지 체크 실시]
var headerArray : Array<Dictionary<String, Any>>? = nil // [헤더 정보를 담는 배열]
var errorExist = false // [에러 발생 여부값]
// MARK: - [뷰 로드 실시]
override func viewDidLoad() {
super.viewDidLoad()
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> viewDidLoad() :: 뷰 로드 실시]")
print("====================================")
print("")
// -----------------------------------------
// [웹뷰 리로드 플래그 값 초기화 실시]
// S_Preference().setString(_sKey: S_FinalData.PRE_WV_COOKIE_RELOAD_FLAG, _sValue: "")
// -----------------------------------------
// -----------------------------------------
// [뷰 컨트롤러 배경 색상 지정]
self.view.backgroundColor = UIColor.init(rgb: 0xffffff).withAlphaComponent(1.0)
// -----------------------------------------
// -----------------------------------------
// [자바스크립트에서 전달 받은 웹뷰 초기 로드 데이터 확인 실시]
self.saveData = S_Preference().getString(_sKey: S_FinalData.PRE_WV_COOKIE_DATA)
if C_Util().stringNotNull(str: self.saveData) == true { // [널 데이터가 아닌 경우]
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> viewDidLoad() :: 웹뷰 로드 정보 확인 실시]")
print("-------------------------------")
print("saveData :: \(self.saveData)")
print("====================================")
print("")
// [프리퍼런스 데이터 초기화 실시]
S_Preference().setString(_sKey: S_FinalData.PRE_WV_COOKIE_DATA, _sValue: "")
// [사전 json 데이터로 파싱 가능한지 체크 실시]
if C_Util().stringJsonObjectEnable(str: self.saveData) == true { // [json 데이터로 변경 가능한 경우]
// [딕셔너리 객체 생성 실시 및 전체 json 데이터 파싱]
var jsonDic : Dictionary<String, Any> = C_Util().jsonObject_To_Dic(jsonString: self.saveData)
// [세부 데이터 파싱 수행 실시]
do {
// MARK: [1]. url 데이터가 포함되어 있는지 확인 실시 (웹뷰 로드 주소)
if jsonDic.keys.contains("url") {
self.loadUrl = String(describing: jsonDic["url"] ?? "")
}
// MARK: [2]. 도메인 주소가 포함되어 있는지 확인 실시 (쿠키 설정 도메인 주소)
if jsonDic.keys.contains("domain") {
self.cookieDomain = String(describing: jsonDic["domain"] ?? "")
self.cookieDomain = self.cookieDomain.replaceAll(_string: "https://", _replace: "")
self.cookieDomain = self.cookieDomain.replaceAll(_string: "http://", _replace: "")
}
// MARK: [3]. 웹뷰 로드에 필요한 헤더 값이 포함되어있는지 확인 실시 (헤더 , 쿠키 값)
if jsonDic.keys.contains("header") {
self.headerArray = jsonDic["header"] as! Array<Dictionary<String, Any>>
}
// MARK: [4]. 파싱한 데이터 검증 수행 실시
if C_Util().stringNotNull(str: self.loadUrl) == true { // [웹뷰 로드 주소가 널이 아닌 경우]
// [도메인 주소와 헤더 값이 널이 아닌 지 확인]
if C_Util().stringNotNull(str: self.cookieDomain) == true
&& self.headerArray != nil && self.headerArray!.count>0 && self.headerArray?.isEmpty == false {
// [헤더 배열을 돌면서 세부적인 설정 값 파싱 실시]
for i in stride(from: 0, through: self.headerArray!.count-1, by: 1) {
var jsonObj : Dictionary<String, Any> = self.headerArray![i] // [배열 각 번지 지정]
// MARK: [개별 딕셔너리 데이터 확인 실시]
for (key, value) in jsonObj {
/*
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> viewDidLoad() :: [헤더] 배열 값 파싱 수행 실시]")
print("-------------------------------")
print("array :: headerArray")
print("-------------------------------")
print("key :: ", "\(key)")
print("-------------------------------")
print("value :: ", jsonObj["\(key)"] ?? "")
print("====================================")
print("")
// */
// [실제 헤더가 포함된 경우 플래그 값 설정]
self.headerExist = true
// MARK: [쿠키 스트링 값 저장]
if "\(key)".lowercased().trim().contains("cookie") { // [key 값이 쿠키 인 경우]
// [쿠키 스트링 값 포맷 수행 실시]
///*
self.cookieString = jsonObj["\(key)"] as? String ?? ""
if self.cookieString.hasSuffix(";") == false { // [쿠키 스트링 값 문자열 마지막이 ; 세미 콜론으로 종료하는 지 확인]
self.cookieString += ";"
}
self.cookieString = self.cookieString.replaceAll(_string: " ", _replace: "") // [공백 제거 실시]
// */
/*
// -----------------------------------------
MARK: [쿠키 스트링 형태 설명]
// -----------------------------------------
1. 쿠키 스트링 형태 : JSESSIONID=61f0aa76ad66d12308000000;domain=m.test.ac.kr;path=/;
// -----------------------------------------
2. 주요 사항 : 쿠키 스트링은 각 데이터 별로 [;] 세미콜론 구분이 필요하다
// -----------------------------------------
*/
// [for 문을 돌면서 = [등호] 와 [;] 세미 콜론 개수 카운트 실시 >> 쿠키 스트링 형식 문자열 검사]
var check_1 = 0 // 특수문자 [=] 개수
var check_2 = 0 // 특수문자 [;] 개수
for c in self.cookieString { // [charAt 확인 실시]
if "\(c)" == "=" {
check_1 += 1
}
if "\(c)" == ";" {
check_2 += 1
}
}
// [정상적인 쿠키 스트링 값이 아닌 경우]
if check_1 != check_2 {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> viewDidLoad() :: 쿠키 설정 데이터 포맷 양식 확인 에러]")
print("-------------------------------")
print("error :: 쿠키 설정에 필요한 데이터 확인 중 문제가 발생했습니다. [cookie data format check error]")
print("-------------------------------")
print("cookieString :: \(self.cookieString)")
print("====================================")
print("")
// [쿠키 스트링 값 초기화]
self.cookieString = ""
// [액티비티 종료 팝업창 호출 실시]
self.showAlertFinish(
tittle: "[알림]",
content: "쿠키 설정에 필요한 데이터 확인 중 문제가 발생했습니다. [cookie data format check error]",
okBtb: "확인",
noBtn: ""
)
}
else {
// [정상적으로 포맷을 수행한 쿠키 값을 배열에 삽입 실시]
jsonObj["\(key)"] = self.cookieString
self.headerArray![i] = jsonObj
}
}
}
}
///*
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> viewDidLoad() :: 웹뷰 로드 [쿠키] 설정 데이터 [검증] 수행]")
print("-------------------------------")
print("url :: ", "\(self.loadUrl)")
print("-------------------------------")
print("domain :: ", "\(self.cookieDomain)")
print("-------------------------------")
print("header :: ", "\(self.headerArray?.description)")
print("-------------------------------")
print("cookieString :: ", "\(self.cookieString)")
print("====================================")
print("")
// */
// [SEARCH FAST] : [웹뷰 설정]
self.init_WebView(_loadType: 1, _loadUrl: self.loadUrl)
}
else { // [일반 주소 로드 실시]
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> viewDidLoad() :: 웹뷰 로드 [일반] 설정 데이터 [검증] 수행]")
print("-------------------------------")
print("url :: ", "\(self.loadUrl)")
print("====================================")
print("")
// [SEARCH FAST] : [웹뷰 설정]
self.init_WebView(_loadType: 0, _loadUrl: self.loadUrl)
}
}
else { // [웹뷰 로드 주소가 널 인 경우]
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> viewDidLoad() :: 웹뷰 로드 주소 확인 에러]")
print("-------------------------------")
print("error :: 웹뷰 로드에 필요한 주소 데이터를 다시 확인해주세요. [url data is null]")
print("-------------------------------")
print("saveData :: \(self.saveData)")
print("====================================")
print("")
// [액티비티 종료 팝업창 호출 실시]
self.showAlertFinish(
tittle: "[알림]",
content: "웹뷰 로드에 필요한 주소 데이터를 다시 확인해주세요. [url data is null]",
okBtb: "확인",
noBtn: ""
)
}
}
catch {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> viewDidLoad() :: 웹뷰 로드 정보 데이터 파싱 에러]")
print("-------------------------------")
print("catch :: ", error.localizedDescription)
print("====================================")
print("")
}
}
else { // [json 데이터로 변경 못하는 경우]
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> viewDidLoad() :: 웹뷰 로드 정보 확인 에러]")
print("-------------------------------")
print("error :: 데이터 json 형식 여부를 다시 확인해주세요. [data parsing error]")
print("-------------------------------")
print("saveData :: \(self.saveData)")
print("====================================")
print("")
// [액티비티 종료 팝업창 호출 실시]
self.showAlertFinish(
tittle: "[알림]",
content: "데이터 json 형식 여부를 다시 확인해주세요. [data parsing error]",
okBtb: "확인",
noBtn: ""
)
}
}
else { // [널 데이터 인 경우]
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> viewDidLoad() :: 웹뷰 로드 정보 확인 실패]")
print("-------------------------------")
print("error :: 웹뷰 로드에 필요한 데이터를 다시 확인해주세요. [data is null]")
print("-------------------------------")
print("saveData :: \(self.saveData)")
print("====================================")
print("")
// [프리퍼런스 데이터 초기화 실시]
S_Preference().setString(_sKey: S_FinalData.PRE_WV_COOKIE_DATA, _sValue: "")
// [액티비티 종료 팝업창 호출 실시]
self.showAlertFinish(
tittle: "[알림]",
content: "웹뷰 로드에 필요한 데이터를 다시 확인해주세요. [data is null]",
okBtb: "확인",
noBtn: ""
)
}
// -----------------------------------------
}
// MARK: - [뷰 컨트롤러 파일에서 설정 : 상태바 콘텐츠 색상 변경]
override var preferredStatusBarStyle: UIStatusBarStyle {
if #available(iOS 13, *) {
//return .lightContent // [흰 색상 콘텐츠 표시]
return .darkContent // [검은 색상 콘텐츠 표시]
//return .default // [검은 색상 콘텐츠 표시]
} else {
return .default
}
}
// MARK: - [뷰 로드 완료]
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> viewWillAppear() :: 뷰 로드 완료]")
print("====================================")
print("")
}
// MARK: - [뷰 화면 표시]
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> viewDidAppear() :: 뷰 화면 표시]")
print("====================================")
print("")
// -----------------------------------------
// [SEARCH FAST] : [포그라운드 및 백그라운드 상태 확인]
NotificationCenter.default.addObserver( // [포그라운드]
self,
selector: #selector(self.checkForeground),
name: UIApplication.willEnterForegroundNotification,
object: nil
)
NotificationCenter.default.addObserver( // [백그라운드]
self,
selector: #selector(self.checkBackground),
name: UIApplication.didEnterBackgroundNotification,
object: nil
)
// -----------------------------------------
// -----------------------------------------
// [포그라운드 처리 실시]
self.checkForeground()
// -----------------------------------------
}
// MARK: - [뷰 정지 상태]
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> viewWillDisappear() :: 뷰 정지 상태]")
print("====================================")
print("")
}
// MARK: - [뷰 종료 상태]
override func viewDidDisappear(_ animated: Bool) {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> viewDidDisappear() :: 뷰 종료 상태]")
print("====================================")
print("")
// -----------------------------------------
// [SEARCH FAST] : [포그라운드 및 백그라운드 상태 확인]
NotificationCenter.default.removeObserver( // [포그라운드]
self,
name: UIApplication.willEnterForegroundNotification,
object: nil
)
NotificationCenter.default.removeObserver( // [백그라운드]
self,
name: UIApplication.didEnterBackgroundNotification,
object: nil
)
// -----------------------------------------
}
// MARK: - [포그라운드 상태 처리 메소드 작성]
@objc func checkForeground() {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> checkForeground() :: 뷰 컨트롤러 포그라운드]")
print("====================================")
print("")
}
// MARK: - [백그라운드 상태 처리 메소드 작성]
@objc func checkBackground() {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> checkBackground() :: 뷰 컨트롤러 백그라운드]")
print("====================================")
print("")
}
// MARK: - [SEARCH FAST] : [웹뷰 설정]
func init_WebView(_loadType:Int, _loadUrl:String){
let statusBarHeight = UIApplication.shared.statusBarFrame.height
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> init_WebView() :: 웹뷰 초기 설정 값 정의 및 웹뷰 로드 수행 실시]")
print("-------------------------------")
print("_loadType [로드 타입] :: \(_loadType)")
print("-------------------------------")
print("_loadUrl [로드 주소] :: \(_loadUrl)")
print("-------------------------------")
print("statusBarHeight [상태 바 높이] :: ", statusBarHeight)
print("====================================")
print("")
/*
// -----------------------------------------
// [원하는 캐시 데이터만 골라서 삭제]
let websiteDataTypes = NSSet(array:
[WKWebsiteDataTypeDiskCache, // 디스크 캐시
WKWebsiteDataTypeMemoryCache, // 메모리 캐시
WKWebsiteDataTypeCookies, // 웹 쿠키,
WKWebsiteDataTypeOfflineWebApplicationCache, // 앱 캐시
WKWebsiteDataTypeWebSQLDatabases, // 웹 SQL 데이터 베이스
WKWebsiteDataTypeIndexedDBDatabases // 데이터 베이스 정보
//WKWebsiteDataTypeLocalStorage // 로컬 스토리지
//WKWebsiteDataTypeSessionStorage // 세션 스토리지
])
let date = NSDate(timeIntervalSince1970: 0)
WKWebsiteDataStore.default().removeData(ofTypes: websiteDataTypes as! Set, modifiedSince: date as Date, completionHandler:{
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> init_WebView() :: 사전 캐시 및 세션 데이터 삭제 수행]")
print("-------------------------------")
print("type :: removeData")
print("====================================")
print("")
})
// -----------------------------------------
// -----------------------------------------
// [URL 요청 후 잔여 캐시 데이터 삭제]
URLCache.shared.removeAllCachedResponses()
// -----------------------------------------
// -----------------------------------------
// [설치된 날짜 가져오는 코드]
let urlToDocumentsFolder: URL? = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last
let installDate = try? FileManager.default.attributesOfItem(atPath: (urlToDocumentsFolder?.path)!)[.creationDate] as! Date
// [설치된 날짜부터 지금까지의 cookie all clear]
URLSession.shared.configuration.httpCookieStorage?.removeCookies(since: installDate!)
// [로그 출력 실시]
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> init_WebView() :: 사전 캐시 및 세션 데이터 삭제 수행]")
print("-------------------------------")
print("type :: URLSession removeCookies")
print("====================================")
print("")
// -----------------------------------------
// */
// -----------------------------------------
// [웹 보기에 대한 쿠키, 디스크 및 메모리 캐시, 기타 유형의 데이터를 관리하는 개체]
//self.javascriptConfig.websiteDataStore = WKWebsiteDataStore.default() // [디폴트]
self.javascriptConfig.websiteDataStore = WKWebsiteDataStore.nonPersistent() // ㅡㅁㄱ[쿠키 셋팅]
// -----------------------------------------
// -----------------------------------------
// [SEARCH FAST] : [자바스크립트 통신]
// [웹뷰 로드 (전) 쿠키 값 설정 실시]
self.addJavaScriptBridge()
// -----------------------------------------
// -----------------------------------------
// [웹뷰 전체 화면 설정 실시]
self.main_webview = WKWebView.init(
frame: CGRect.init(
x: 0,
y: statusBarHeight,
width: self.view.frame.width, // [웹뷰에 맞게 화면 맞춤]
height: self.view.frame.height - statusBarHeight // [웹뷰에 맞게 화면 맞춤 길이 맞춤]
),
configuration: self.javascriptConfig // MARK: [자바스크립트 저장 공간 지정]
)
// -----------------------------------------
// -----------------------------------------
// [웹뷰 옵션값 지정]
self.main_webview?.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true // [자바스크립트 활성화]
self.main_webview?.navigationDelegate = self // [웹뷰 변경 상태 감지 위함]
//self.main_webview?.allowsBackForwardNavigationGestures = true // [웹뷰 뒤로가기, 앞으로 가기 제스처 사용]
self.main_webview?.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: .new, context: nil) // [웹뷰 로드 상태 퍼센트 확인]
self.main_webview?.uiDelegate = self // [alert 팝업창 이벤트 받기 위함]
self.main_webview?.translatesAutoresizingMaskIntoConstraints = false
//self.main_webview?.scrollView.bounces = true
self.main_webview?.scrollView.showsHorizontalScrollIndicator = false
self.main_webview?.scrollView.scrollsToTop = true
// -----------------------------------------
// -----------------------------------------
// [웹뷰 스크롤 바운스 방지]
self.main_webview?.scrollView.alwaysBounceVertical = false
self.main_webview?.scrollView.bounces = false
// -----------------------------------------
// -----------------------------------------
// [액티비티 화면에 웹뷰 화면 추가 실시]
self.view.addSubview(self.main_webview!)
// -----------------------------------------
// -----------------------------------------
// [웹뷰 로드 헤더 값 설정 및 웹뷰 로드 수행 실시]
let url = URL (string: _loadUrl) // [웹뷰 로드 주소]
var request = URLRequest(url: url! as URL) // [request 지정]
if _loadType == 1 && self.headerExist == true { // [웹뷰 쿠키 설정 값으로 로드 수행]
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> init_WebView() :: [쿠키] 웹뷰 설정 및 로드 수행 실시]")
print("====================================")
print("")
// MARK: [for 문을 돌면서 헤더 배열 값을 request.addValue 추가 실시]
// [SEARCH FAST] : [동적 헤더 추가 실시]
for i in stride(from: 0, through: self.headerArray!.count-1, by: 1) {
let jsonObj : Dictionary<String, Any> = self.headerArray![i] // [배열 각 번지 지정]
// MARK: [개별 딕셔너리 데이터 확인 실시]
for (key, value) in jsonObj {
let keyData:String = "\(key)" as? String ?? "" // [key]
let valueData:String = jsonObj["\(key)"] as? String ?? "" // [value]
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> init_WebView() :: 웹뷰 로드 동적 [헤더] 값 추가 실시]")
print("-------------------------------")
print("key :: ", "\(keyData)")
print("-------------------------------")
print("value :: ", "\(valueData)")
print("====================================")
/*
// -----------------------------------------
// MARK: [쿠키 추가 로직 설명]
// -----------------------------------------
1. URLRequest addValue 를 통해서 웹뷰 로드 시 헤더 쪽에 쿠키 추가
// -----------------------------------------
2. 자바스크립트 통신 브릿지 추가 부분에서 addUserScript 를 통해서 쿠키 값 설정
// -----------------------------------------
3. 쿠키 스트링 형태 : JSESSIONID=61f0aa76ad66d12308000000;domain=m.test.ac.kr;path=/;
// -----------------------------------------
*/
// [헤더 필드에 추가 실시]
request.addValue(valueData, forHTTPHeaderField: keyData)
}
}
// MARK: [쿠키 설정 헤더 값 지정 웹뷰 주소 로드 실시]
self.main_webview!.load(request)
}
else { // [일반 웹뷰 설정으로 로드 수행]
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> init_WebView() :: [일반] 웹뷰 설정 및 로드 수행 실시]")
print("====================================")
print("")
// MARK: [일반 주소 호출 실시]
self.main_webview!.load(request)
}
// -----------------------------------------
// -----------------------------------------
// [네이티브 버튼 활성 및 비활성 처리]
///*
let button = UIButton(
frame: CGRect(
x: self.view.frame.size.width - 55,
y: statusBarHeight + 0,
width: 40,
height: 40
)
) // 마진 및 사이즈 지정
button.backgroundColor = .blue // [배경 색상 지정]
button.setTitle("", for: .normal) // [타이틀 지정]
//button.setImage(UIImage(named: "closecirclebtn.png")! as UIImage, for: .normal) // [버튼 이미지]
button.addTarget(self, action: #selector(self.buttonAction), for: .touchUpInside) // [클릭 이벤트 지정]
self.view.addSubview(button) // [뷰에 추가 실시]
// */
// -----------------------------------------
}
// MARK: - [자바스크립트 통신을 위한 초기화 부분]
// [SEARCH FAST] : [자바스크립트 통신]
func addJavaScriptBridge(){
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> addJavaScriptBridge() :: 자바스크립트 통신 브릿지 추가]")
print("-------------------------------")
print("Bridge :: setMarket")
print("====================================")
print("")
// -----------------------------------------
// [브릿지 경로 추가 : 데이터 받을 경로 : 자바스크립트 >> IOS]
self.javascriptController.add(self, name: "setMarket") // [마켓 이동]
// -----------------------------------------
// -----------------------------------------
// MARK: [쿠키 값 널 여부 체크 실시 >> 웹뷰 로드 시 사전 쿠키 값 설정 실시]
// [SEARCH FAST] : [쿠키 설정 실시]
if C_Util().stringNotNull(str: self.cookieString) == true {
// [쿠키 스트링 값 포맷 실시]
var cookies = "document.cookie='"
cookies += self.cookieString
cookies += "'"
let cookieScript = WKUserScript(source: cookies, injectionTime: .atDocumentStart, forMainFrameOnly: false)
self.javascriptController.addUserScript(cookieScript)
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> addJavaScriptBridge() :: [사전] 쿠키 설정 값 추가 실시]")
print("-------------------------------")
print("cookieString [원본] :: \(self.cookieString)")
print("-------------------------------")
print("cookies [포맷] :: \(cookies)")
print("====================================")
print("")
}
// -----------------------------------------
// -----------------------------------------
self.javascriptConfig.userContentController = self.javascriptController
//self.main_webview = WKWebView(frame: self.view.bounds, configuration: javascriptConfig)
// -----------------------------------------
}
// MARK: - [자바스크립트 >> IOS 통신 부분]
// [SEARCH FAST] : [자바스크립트 통신]
@available(iOS 8.0, *)
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
// -----------------------------------------
// [SEARCH FAST] : [자바스크립트 통신 수행]
// -----------------------------------------
// -----------------------------------------
// [웹 코드] window.webkit.messageHandlers.setMarket.postMessage(jsonString);
// -----------------------------------------
if message.name == "setMarket" {
guard let checkType = message.body as? String // [전달 받은 메시지 확인]
else {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> userContentController :: setMarket() :: JS >> IOS]")
print("-------------------------------")
print("error :: [type] :: ", type(of: message.body))
print("====================================")
print("")
// [에러 팝업창 알림 표시]
self.showAlert(
type: 0,
tittle: S_FinalData.AL_TITLE,
content: S_FinalData.ERROR_DATA_NULL + " [setMarket]",
okBtb: S_FinalData.AL_OK,
noBtn: ""
)
// [리턴 종료]
return
}
// -----------------------------------------
// [자바스크립트에서 전달 받은 데이터 저장]
let receiveData = message.body as! String
// -----------------------------------------
// [자바스크립트 데이터 방어 로직 추가 실시 : 데이터 널 체크]
if C_Util().stringNotNull(str: receiveData) == true { // [널 값이 아닌 경우]
}
else { // [널 값인 경우]
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> userContentController :: setMarket() :: JS >> IOS]")
print("-------------------------------")
print("전달받은 데이터 :: ", receiveData)
print("-------------------------------")
print("error :: [msg] :: ", S_FinalData.ERROR_DATA_NULL)
print("====================================")
print("")
// [에러 팝업창 알림 표시]
self.showAlert(
type: 0,
tittle: S_FinalData.AL_TITLE,
content: S_FinalData.ERROR_DATA_NULL + " [setMarket]",
okBtb: S_FinalData.AL_OK,
noBtn: ""
)
// [리턴 종료]
return
}
// -----------------------------------------
// [자바스크립트 데이터 방어 로직 추가 실시 : key 값 체크]
if C_Util().stringMultiContains(str: receiveData.lowercased(), array: ["ios", "id"]) == true {
}
else {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> userContentController :: setMarket() :: JS >> IOS]")
print("-------------------------------")
print("전달받은 데이터 :: ", receiveData)
print("-------------------------------")
print("error :: [msg] :: ", S_FinalData.ERROR_PARSING_KEY)
print("====================================")
print("")
// [에러 팝업창 알림 표시]
self.showAlert(
type: 0,
tittle: S_FinalData.AL_TITLE,
content: S_FinalData.ERROR_PARSING_KEY + " [setMarket]",
okBtb: S_FinalData.AL_OK,
noBtn: ""
)
// [리턴 종료]
return
}
// -----------------------------------------
// [자바스크립트 데이터 방어 로직 추가 실시 : json 데이터 형식 체크 실시]
if C_Util().stringJsonObjectEnable(str: receiveData) == true {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> userContentController :: setMarket() :: JS >> IOS]")
print("-------------------------------")
print("전달받은 데이터 :: ", receiveData)
print("-------------------------------")
print("설 명 :: ", "마켓 이동 정보 전달 받음")
print("-------------------------------")
print("로 직 :: ", "마켓 수행 실시")
print("====================================")
print("")
// [json 형식 문자열을 딕셔너리로 변환 실시]
let jsonDic = C_Util().jsonObject_To_Dic(jsonString: receiveData)
// [세부 json 데이터 받기 실시]
if jsonDic.keys.contains("ios") == true { // [키값이 존재할 경우]
do {
// -----------------------------------------
// [딕셔너리에 세부 데이터 저장 실시]
var dicData : Dictionary<String, Any> = jsonDic["ios"] as! Dictionary<String, Any>
// -----------------------------------------
// [패키지명 및 앱 아이디 확인 실시]
let appId = dicData["id"] as! String // [앱 스토어 이동 아이디]
// -----------------------------------------
// [자바스크립트 전달 받은 데이터 확인 방어 로직 추가 : 에러 체크]
if C_Util().stringNotNull(str: appId) == true
&& appId.hasPrefix("id") == true { // [널 데이터 아님]
// [마켓 이동 수행 실시]
self.goMarketRun(_id: appId)
}
// -----------------------------------------
else { // [널 데이터]
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> userContentController :: setMarket() :: JS >> IOS]")
print("-------------------------------")
print("전달받은 데이터 :: ", receiveData)
print("-------------------------------")
print("error :: [msg] :: ", S_FinalData.ERROR_PARSING_DATA)
print("====================================")
print("")
// [에러 팝업창 알림 표시]
self.showAlert(
type: 0,
tittle: S_FinalData.AL_TITLE,
content: S_FinalData.ERROR_PARSING_DATA + " [setMarket]",
okBtb: S_FinalData.AL_OK,
noBtn: ""
)
// [리턴 종료]
return
}
// -----------------------------------------
}
catch {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> userContentController :: setMarket() :: JS >> IOS]")
print("-------------------------------")
print("전달받은 데이터 :: ", receiveData)
print("-------------------------------")
print("catch :: ", error.localizedDescription)
print("====================================")
print("")
}
}
}
else {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> userContentController :: setMarket() :: JS >> IOS]")
print("-------------------------------")
print("전달받은 데이터 :: ", receiveData)
print("-------------------------------")
print("error :: [msg] :: ", S_FinalData.ERROR_JSON_PARSING)
print("====================================")
print("")
// [에러 팝업창 알림 표시]
self.showAlert(
type: 0,
tittle: S_FinalData.AL_TITLE,
content: S_FinalData.ERROR_JSON_PARSING + " [setMarket]",
okBtb: S_FinalData.AL_OK,
noBtn: ""
)
// [리턴 종료]
return
}
}
// -----------------------------------------
}
// MARK: - [IOS >> 자바스크립트 통신 부분]
// -----------------------------------------
// [SEARCH FAST] : [자바스크립트 통신]
// -----------------------------------------
func iosToJs_shakeResult(){
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> iosToJs_shakeResult() :: IOS >> JS]")
print("-------------------------------")
print("JS 함수 :: shakeResult")
print("-------------------------------")
print("설 명 :: ", "디바이스 흔들기 이벤트 발생 전달")
print("====================================")
print("")
// MARK: [함수 호출]
self.main_webview!.evaluateJavaScript("shakeResult('\("")')") { (success, error) in
if error != nil {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> iosToJs_shakeResult() :: IOS >> JS]")
print("-------------------------------")
print("JS 함수 :: shakeResult")
print("-------------------------------")
print("설 명 :: ", "디바이스 흔들기 이벤트 발생 전달")
print("-------------------------------")
print("전송 결과 [error] :: ", error)
print("====================================")
print("")
}
else {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> iosToJs_shakeResult() :: IOS >> JS]")
print("-------------------------------")
print("JS 함수 :: shakeResult")
print("-------------------------------")
print("설 명 :: ", "디바이스 흔들기 이벤트 발생 전달")
print("-------------------------------")
print("전송 결과 [success] :: ", "OK")
print("====================================")
print("")
}
}
}
// MARK: - [웹뷰 로드 수행 시작 부분]
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
let _startUrl = String(describing: webView.url?.description ?? "")
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> didStartProvisionalNavigation() :: 웹뷰 로드 수행 시작]")
print("-------------------------------")
print("주 소 :: \(_startUrl ?? "")")
print("====================================")
print("")
}
// MARK: - [실시간 웹뷰 로드 상태 퍼센트 확인 부분 : 0.1 ~ 1.0]
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
// [0 ~ 1 사이의 실수형으로 결과값이 출력된다 [0 : 로딩 시작, 1 : 로딩 완료]]
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> observeValue() :: 실시간 웹뷰 로드 상태 확인]")
print("-------------------------------")
print("원 본 :: \(Float((self.main_webview?.estimatedProgress)!))")
print("-------------------------------")
print("퍼센트 :: \(Float((self.main_webview?.estimatedProgress)!)*100)")
print("====================================")
print("")
if Float((self.main_webview?.estimatedProgress)!) >= 1 {
// -----------------------------------------
DispatchQueue.main.async {
/*
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> observeValue() :: 웹뷰 로드 완료 상태]")
print("-------------------------------")
print("퍼센트 :: \(Float((self.main_webview?.estimatedProgress)!)*100)")
print("====================================")
print("")
// */
// -----------------------------------------
// MARK: [SEARCH FAST] : [실시간 쿠키 값 확인 실시]
// -----------------------------------------
/*
1. 쿠키 설정 웹뷰 로드 경우 로직
- [1]. 웹뷰 최초 로드 시 헤더 쪽에 쿠키 추가 실시
- [2]. addJavaScriptBridge() 에서 WKUserScript / addUserScript 사용해 웹뷰 로드 전 사전 쿠키 값 설정
*/
// -----------------------------------------
if self.main_webview != nil {
// [웹뷰 정상 표시 실시]
self.main_webview!.isHidden = false
// [웹뷰에 저장된 쿠키 값 확인 실시]
if #available(iOS 11.0, *) {
self.main_webview!.configuration.websiteDataStore.httpCookieStore.getAllCookies { cookies in
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> observeValue() :: 웹뷰 로드 완료 상태]")
print("-------------------------------")
print("퍼센트 :: \(Float((self.main_webview?.estimatedProgress)!)*100)")
print("-------------------------------")
print("웹뷰 저장된 쿠키 :: ", cookies.description)
print("====================================")
print("")
}
}
else {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> observeValue() :: 웹뷰 로드 완료 상태]")
print("-------------------------------")
print("퍼센트 :: \(Float((self.main_webview?.estimatedProgress)!)*100)")
print("-------------------------------")
print("웹뷰 저장된 쿠키 :: iOS 11.0 미만 디바이스")
print("====================================")
print("")
}
}
// -----------------------------------------
// -----------------------------------------
// MARK: [쿠키 설정 : evaluateJavaScript 자바스크립트 데이터 전송 방법]
// -----------------------------------------
/*
1. 웹뷰 최초 설정 및 로드 시 헤더 쪽에 쿠키 값 추가 및 로드 실시
2. 실시간 웹뷰 주소 완료 부분 확인 observeValue 에서 웹뷰 로드 100프로가 되면 evaluateJavaScript 자바스크립트로 쿠키 심는다
3. 실시간 웹뷰 주소 완료 부분 확인 observeValue 에서 쿠키가 정상적으로 심어지면 웹뷰 reload 를 통해서 다시 로드를 수행한다
4. 최종 웹뷰 reload 까지 완료 된 후에는 브라우저는 allow 이동 처리 실시
*/
// -----------------------------------------
// MARK: [자바스크립트 사용해서 쿠키 셋팅 실시]
/*
if C_Util().stringNotNull(str: self.cookieString) == true { // [쿠키 스트링 값이 널이 아닌 경우]
// MARK: [웹뷰 리로드 처리 플래그]
let load_flag = S_Preference().getString(_sKey: S_FinalData.PRE_WV_COOKIE_RELOAD_FLAG)
if C_Util().stringNotNull(str: load_flag) == true { // [널 아닌 경우]
// [쿠키 스트링 값 초기화]
self.cookieString = ""
// [웹뷰 정상 표시 실시]
self.main_webview!.isHidden = false
}
else { // MARK: [널인 경우 >> 웹뷰 쿠키 심기 >> 리로드 처리]
// [자바스크립트 사용해 쿠키를 셋팅하기 위해 형식 정의 실시]
var cookies = "document.cookie='"
cookies += self.cookieString
cookies += "'"
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> observeValue() :: 웹뷰 로드 완료 상태]")
print("-------------------------------")
print("쿠키 값 자바스크립트 셋팅 실시 :: \(cookies)")
print("====================================")
print("")
// MARK: [자바스크립트에 쿠키 셋팅 실시 >> evaluateJavaScript]
self.main_webview!.evaluateJavaScript("\(cookies)") { (success, error) in
if error != nil {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> observeValue() :: 쿠키 값 설정 수행 실시]")
print("-------------------------------")
print("설 명 :: ", "[IOS >> 자바스크립트] 쿠키 값 자바스크립트 셋팅")
print("-------------------------------")
print("cookies :: ", cookies)
print("-------------------------------")
print("전송 결과 [error] :: ", error)
print("====================================")
print("")
}
else {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> observeValue() :: 쿠키 값 설정 수행 실시]")
print("-------------------------------")
print("설 명 :: ", "[IOS >> 자바스크립트] 쿠키 값 자바스크립트 셋팅")
print("-------------------------------")
print("cookies :: ", cookies)
print("-------------------------------")
print("전송 결과 [success] :: ", "OK")
print("====================================")
print("")
// MARK: [웹뷰 리로드 플래그 값 확인 실시]
if C_Util().stringNotNull(str: load_flag) == true { // [널 아닌 경우]
// [웹뷰 정상 표시 실시]
self.main_webview!.isHidden = false
}
else { // [널 인 경우]
// [웹뷰 리로드 플래그 값 지정 실시]
S_Preference().setString(_sKey: S_FinalData.PRE_WV_COOKIE_RELOAD_FLAG, _sValue: "TRUE")
// [쿠키 생성 후 쿠키 정보가 반영된 웹페이지를 불러 올 수 있도록 새로 고침을 해줍니다]
self.main_webview!.reload() // MARK: [중요 부분]
}
}
}
}
}
// -----------------------------------------
else { // MARK: [일반 웹 접속 인 경우]
// [웹뷰 정상 표시 실시]
self.main_webview!.isHidden = false
}
// -----------------------------------------
// */
}
}
}
// MARK: - [웹뷰 로드 수행 완료 부분]
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
let _endUrl = String(describing: webView.url?.description ?? "")
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> didFinish() :: 웹뷰 로드 수행 완료]")
print("-------------------------------")
print("주 소 :: \(_endUrl)")
print("====================================")
print("")
}
// MARK: - [웹뷰 로드 수행 에러 확인]
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
// -----------------------------------------
let _nsError = (error as NSError).code
let _errorUrl = String(describing: webView.url?.description ?? "")
// -----------------------------------------
// -----------------------------------------
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> didFail() :: 웹뷰 로드 수행 에러]")
print("-------------------------------")
print("에러 주소 :: \(_errorUrl)")
print("-------------------------------")
print("에러 코드 :: \(_nsError)")
print("-------------------------------")
print("에러 메시지 :: \(S_WebViewErrorCode().checkError(_errorCode: _nsError))")
print("====================================")
print("")
// -----------------------------------------
}
// MARK: - [웹뷰 window open 새창 열기 및 닫기 이벤트 감지 실시]
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
// [url 주소 확인 실시]
let _urlString = navigationAction.request.url!.absoluteString
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> createWebViewWith() :: 웹뷰 [window open] 새창 이벤트 확인]")
print("====================================")
print("")
return nil
}
func webViewDidClose(_ webView: WKWebView) {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> webViewDidClose() :: 웹뷰 [window open] 닫기 이벤트 확인]")
print("====================================")
print("")
}
// MARK: - [웹뷰 실시간 url 변경 감지 실시]
private let websiteDataStore = WKWebsiteDataStore.default()
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
// -----------------------------------------
// [실시간 웹뷰 주소 변경 감지]
let _shouldUrl = String(describing: webView.url?.description ?? "")
var action: WKNavigationActionPolicy?
guard let url = navigationAction.request.url else { return }
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> decidePolicyFor() :: 웹뷰 실시간 url 변경 감지]")
print("-------------------------------")
print("주 소 :: \(url)")
print("====================================")
print("")
// -----------------------------------------
// -----------------------------------------
// [전화 이동 실시]
if "\(url)".hasPrefix("tel:") {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> decidePolicyFor() :: 웹뷰 실시간 url 변경 감지]")
print("-------------------------------")
print("주 소 :: \(url)")
print("-------------------------------")
print("로 직 :: 전화 걸기 이동 실시")
print("====================================")
print("")
// [전화 이동 실시]
self.goTelIntent(_url: "\(url)")
// [브라우저 내 로직 캔슬]
decisionHandler(.cancel)
return
}
// -----------------------------------------
// -----------------------------------------
// [이메일 이동 실시]
if "\(url)".hasPrefix("mailto:") {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> decidePolicyFor() :: 웹뷰 실시간 url 변경 감지]")
print("-------------------------------")
print("주 소 :: \(url)")
print("-------------------------------")
print("로 직 :: 메일 보내기 이동 실시")
print("====================================")
print("")
// [메일 이동 실시]
self.goMailIntent(_url: "\(url)")
// [브라우저 내 로직 캔슬]
decisionHandler(.cancel)
return
}
// -----------------------------------------
// -----------------------------------------
// [문자 이동 실시]
if "\(url)".hasPrefix("sms:") {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> decidePolicyFor() :: 웹뷰 실시간 url 변경 감지]")
print("-------------------------------")
print("주 소 :: \(url)")
print("-------------------------------")
print("로 직 :: 문자 보내기 실시")
print("====================================")
print("")
// [문자 이동 실시]
self.goSmsIntent(_url: "\(url)")
// [브라우저 내 로직 캔슬]
decisionHandler(.cancel)
return
}
// -----------------------------------------
// -----------------------------------------
// [하이퍼링크 이동 실시]
if "\(url)".hasPrefix("l:") {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> decidePolicyFor() :: 웹뷰 실시간 url 변경 감지]")
print("-------------------------------")
print("주 소 :: \(url)")
print("-------------------------------")
print("로 직 :: 하이퍼링크 이동 실시")
print("====================================")
print("")
// [링크 이동 실시]
self.goLinkIntent(_url: "\(url)")
// [브라우저 내 로직 캔슬]
decisionHandler(.cancel)
return
}
// -----------------------------------------
// -----------------------------------------
if self.main_webview != nil {
if #available(iOS 11.0, *) {
self.main_webview!.configuration.websiteDataStore.httpCookieStore.getAllCookies { cookies in
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> decidePolicyFor() :: 웹뷰 실시간 url 변경 감지]")
print("-------------------------------")
print("설 명 :: ", "저장된 쿠키값 확인 실시")
print("-------------------------------")
print("cookie [쿠키] :: ", cookies)
print("====================================")
print("")
}
} else {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> decidePolicyFor() :: 웹뷰 실시간 url 변경 감지]")
print("-------------------------------")
print("설 명 :: ", "저장된 쿠키값 확인 실시")
print("-------------------------------")
print("cookie [쿠키] :: iOS 버전 11 미만 디바이스")
print("====================================")
print("")
}
}
// -----------------------------------------
// [브라우저 로직 허용 실시]
decisionHandler(.allow)
return
// -----------------------------------------
}
// MARK: - [웹뷰 실시간 url status 상태 코드 감지 실시]
/*
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse,
decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
// -----------------------------------------
// [웹뷰 에러 코드 감지]
// -----------------------------------------
// [핸들러 처리 실시]
defer {
decisionHandler(.allow)
}
var _url = ""
// -----------------------------------------
if let url = navigationResponse.response.url {
_url = url.description
}
else {
_url = ""
}
// -----------------------------------------
// [응답 상태 값 확인 실시]
if let response = navigationResponse.response as? HTTPURLResponse {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> WKNavigationResponse() :: 웹뷰 실시간 url status 상태 코드 감지]")
print("-------------------------------")
print("주 소 :: \(_url)")
print("-------------------------------")
print("상태 코드 :: \(response.statusCode)")
print("====================================")
print("")
// MARK: [에러 응답 코드 인 경우]
// -----------------------------------------
if response.statusCode >= 400 {
// [무한 루프 방지 위해 기존에 저장된 에러 값 체크 실시]
let errorCheck = String(describing:S_Preference().getString(_sKey: S_FinalData.PRE_WEBVIEW_RELOAD))
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> WKNavigationResponse() :: 웹뷰 실시간 url status 상태 코드 감지]")
print("-------------------------------")
print("로 직 :: 에러 발생 로직 처리 실시")
print("-------------------------------")
print("[기존] 저장된 에러 발생 여부 :: \(errorCheck)")
print("====================================")
print("")
// -----------------------------------------
// MARK: [에러가 중복 실행된 경우 >> 에러 팝업창 표시]
if errorCheck != nil
&& errorCheck.count>0
&& errorCheck.trim().equals(_string: "") == false
&& errorCheck.trim().equals(_string: "1") == true { // MARK: [에러 팝업창]
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> WKNavigationResponse() :: 웹뷰 실시간 url status 상태 코드 감지]")
print("-------------------------------")
print("로 직 :: 재시도 최종 실패 >> [에러 팝업창] 웹뷰 로드 에러 표시 실시")
print("====================================")
print("")
// MARK: [실시간으로 웹뷰 에러가 발생한 경우 >> 에러 팝업창 표시]
// MARK: [사용자가 다시 접속 시 에러 발생한 경우 >> SceneDelegate >> sceneWillEnterForeground >> 앱 재기동]
// [에러 팝업창 표시]
self.showAlertWebview(
tittle:S_FinalData.AL_TITLE,
content:"URL : " + "\(_url)" + "\n" + "\n" +
"Error : " + S_FinalData.ERROR_WEBVIEW_LOAD + "\n" + "\n" +
"HTTPURLResponse : " + "\(response.statusCode)" + "\n" + "\n" +
"TIME : " + String(describing: C_Util().getNowDateTime24()) + "",
//_url:_url, // [에러 주소]
_url: S_FinalData.WV_LOAD_MAIN_ENZ_URL, // [메인 주소]
okBtb:S_FinalData.AL_OK,
noBtn:""
)
}
// -----------------------------------------
// MARK: [처음으로 에러가 발생한 경우 >> 프리퍼런스 데이터 널 인 경우 :: 재시도 기회 제공]
else {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> WKNavigationResponse() :: 웹뷰 실시간 url status 상태 코드 감지]")
print("-------------------------------")
print("로 직 :: 에러 최초 발생 >> [재시도] 웹 페이지 다시 로드 수행 실시")
print("====================================")
print("")
// -----------------------------------------
// MARK: [웹뷰 재호출 프리퍼런스 값 지정 실시]
S_Preference().setString(_sKey: S_FinalData.PRE_WEBVIEW_RELOAD, _sValue: "1")
// -----------------------------------------
// -----------------------------------------
// [SEARCH FAST] : [웹뷰 세션 및 캐시 삭제 수행]
self.clearWebViewChahe()
// -----------------------------------------
// -----------------------------------------
// [웹뷰 객체 지우기 실시]
if self.main_webview != nil {
// [웹뷰 제거 실시]
self.main_webview?.removeFromSuperview()
self.main_webview = nil
// [자바스크립트 통신 사용 초기화]
self.javascriptController = WKUserContentController()
}
// -----------------------------------------
// -----------------------------------------
// [SEARCH FAST] : [인트로 화면 처리]
self.introBg.isHidden = false // [로딩 이미지 활성]
// -----------------------------------------
// -----------------------------------------
// [SEARCH FAST] : [웹뷰 로드 수행 실시]
self.init_WebView(_loadUrl: S_FinalData.WV_LOAD_MAIN_ENZ_URL)
// -----------------------------------------
}
}
// -----------------------------------------
else { // MARK: [정상 응답 코드 인 경우]
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> WKNavigationResponse() :: 웹뷰 실시간 url status 상태 코드 감지]")
print("-------------------------------")
print("로 직 :: [정상] 웹뷰 이동 로직 처리 실시")
print("====================================")
print("")
// MARK: [웹뷰 재호출 프리퍼런스 값 지정 실시]
S_Preference().setString(_sKey: S_FinalData.PRE_WEBVIEW_RELOAD, _sValue: "")
}
// -----------------------------------------
}
}
// */
// MARK: - [웹뷰 모달창 닫힐때 앱 종료현상 방지]
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - [웹뷰 alert 팝업창 처리]
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String,
initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void){
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> runJavaScriptAlertPanelWithMessage() :: alert 팝업창 처리]")
print("-------------------------------")
print("message :: \(message)")
print("====================================")
print("")
// [팝업창 처리 실시]
let alertController = UIAlertController(title: "", message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "확인", style: .default, handler: { (action) in completionHandler() }))
self.present(alertController, animated: true, completion: nil)
}
// MARK: - [웹뷰 confirm 팝업창 처리]
func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> runJavaScriptConfirmPanelWithMessage() :: confirm 팝업창 처리]")
print("-------------------------------")
print("message :: \(message)")
print("====================================")
print("")
// [팝업창 처리 실시]
let alertController = UIAlertController(title: "", message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "취소", style: .default, handler: { (action) in completionHandler(false) }))
alertController.addAction(UIAlertAction(title: "확인", style: .default, handler: { (action) in completionHandler(true) }))
self.present(alertController, animated: true, completion: nil)
}
// MARK: - [웹뷰 상단 버튼 닫기 클릭 이벤트]
@objc func buttonAction(sender: UIButton!) {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> buttonAction() :: 웹뷰 닫기 버튼 클릭 이벤트 발생]")
print("====================================")
print("")
// -----------------------------------------
// [현재 액티비티 닫기 수행 실시]
self.dismiss(animated: false, completion: nil)
// -----------------------------------------
}
// MARK: [액티비티 종료 팝업창 메소드]
func showAlertFinish(tittle:String, content:String, okBtb:String, noBtn:String) {
// [메인 큐에서 비동기 방식 실행 : UI 동작 실시]
DispatchQueue.main.async {
print("")
print("====================================")
print("[\(self.ACTIVITY_NAME) >> showAlertFinish() :: 액티비티 종료 팝업창 호출 실시]")
print("tittle :: \(tittle)")
print("content :: \(content)")
print("====================================")
print("")
// [UIAlertController 객체 정의 실시]
let alert = UIAlertController(title: tittle + "\n", message: content + "\n", preferredStyle: UIAlertController.Style.alert)
// [인풋으로 들어온 확인 버튼이 nil 아닌 경우]
if(okBtb != "" && okBtb.count>0){
let okAction = UIAlertAction(title: okBtb, style: .default) { (action) in
// -------------------------------
// [확인 버튼 클릭 이벤트 내용 정의 실시]
// -------------------------------
// [현재 액티비티 닫기 수행 실시]
self.dismiss(animated: false, completion: nil)
// -------------------------------
return
// -------------------------------
}
alert.addAction(okAction) // [버튼 클릭 이벤트 객체 연결]
}
// [인풋으로 들어온 취소 버튼이 nil 아닌 경우]
if(noBtn != "" && noBtn.count>0){
let noAction = UIAlertAction(title: noBtn, style: .default) { (action) in
// -------------------------------
// [취소 버튼 클릭 이벤트 내용 정의 실시]
// -------------------------------
return
// -------------------------------
}
alert.addAction(noAction) // [버튼 클릭 이벤트 객체 연결]
}
// [alert 팝업창 활성 실시]
self.present(alert, animated: false, completion: nil)
}
}
} // MARK: [클래스 종료]
반응형
'투케이2K 유틸파일' 카테고리의 다른 글
Comments